2020年3月18日

二十三种设计模式(转)

作者 admin

一、创建型:

单例模式、工厂模式、抽象工厂模式、原型模式、建造者模式;

二、结构型:

代理模式,装饰器模式、适配器模式、外观模式、组合模式、享元模式、桥梁模式;

 

三、行为型:

策略模式、责任链模式、命令模式、中介者模式、模板方法模式、迭代器模式、访问者模式、观察者模式、解释器模式、备忘录模式、状态模式。

 

三类设计模式的特点:

 

 

六大原则

一、开放封闭(简称开闭)原则

Open-Close Principle(OCP):一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。目的就是保证程序的扩展性好,易于维护和升级。

开闭原则被称为面向对象设计的基石,实际上,其他原则都可以看作是实现开闭原则的工具和手段。意思就是:软件对扩展应该是开放的,对修改是封闭的,通俗来说就是,开发一个软件时,应该对其进行功能扩展,而在进行这些扩展时,不需要对原来的程序进行修改。

好处是:软件可用性非常灵活,扩展性强。需要新的功能时,可以增加新的模块来满足新需求。另外由于原来的模块没有修改,所以不用担心稳定性的问题。

二、单一职责原则

Single-Responsibilitiy Principle(SRP):对一个类而言,应该仅有一个引起它变化的原因。如果存在多于一个动机去改变一个类,那么这个类就具有多于一个的职责,就应该把多余的职责分离出去,再去创建一些类来完成每一个职责。

举个例子:一个人身兼数职,而这些事情相关性不大,甚至有冲突,那他就无法很好的解决这些问题职责,应该分到不同的人身上去做。

单一职责原则是实现高内聚低耦合的最好方法,没有之一。

复制代码
 1 class CellPhone:
 2   
 3     def call(string person):
 4       //打电话
 5       pass
 6     def hangup():
 7      //挂断电话
 8         pass
 9 
10     def sendMessage(string person):
11     //发送信息
12         pass
13     def receiveMessage():
14     //接受信息
15         pass
复制代码

上面的手机类虽然符合人们对手机的认识,但是实际上却拥有两个不同的职责:打电话、挂断电话和发短信、接受信息,因此引起它变化的原因就有多个,是比较脆弱的设计,应该将两种行为分离。

三、里氏代换原则

Liskov Substitution Principle:子类可以扩展父类的功能,但是不能改变父类原有的功能。

在第一条原则开放封闭原则中,主张“抽象”和“多态”。维持设计的封装性“抽象”是语言提供的功能,“多态”由继承语意实现。因此如何去度量继承关系中的质量?

答案是:继承必须明确确保超类(父类)所拥有的性质在子类中仍然成立。

在面向对象的思想中,一个对象就是一组状态和一系列行为的组合体。状态是对象的内在特性,行为是对象的外在特性。LSP表述的就是在同一继承体系中的队形应该具有共同的行为特征。

复制代码
 1 class bird:
 2     color = ''
 3     weight = ''
 4     def eat():
 5         pass
 6     def fly():
 7         print("fly")
 8         
 9 class chicken(bird):
10     def fly():
11         print("can not fly")
复制代码

在上述例子中,父类也就是对象鸟有两个行为也就是方法:eat()和fly(),在子类chicken中这两个行为也应该成立,但是现实中chicken是不能飞的,因此chicken中的fly()方法覆盖了父类中的方法。违反了VSP。

四、依赖倒置原则

Dependence Inversion Principle(DIP):是一个类与类之间的调用规则。这里的依赖就是代码中的耦合。高层模块不应该依赖底层模块,二者都应该依赖其抽象了;抽象不依赖细节;细节应该依赖抽象。接口编程。

主要思想就是:如果一个类中的一个成员或者参数成为一个具体的类型,那么这个类就依赖这个具体类型。如果在一个继承结构中,上层类中的一个成员或者参数为一个下层类型,那么就是这个继承结构高层依赖底层,就要尽量面向抽象或者接口编程。

举例:存在一个Driver类,成员为一个Car对象,还有一个driver()方法,Car对象中有两个方法start()与stop()。显然Driver依赖Car,也就是说Driver类调用了Car类中的方法。但是当增加Driver类对于Bus类的支持时(司机有需要开公交车),就必须更改Driver中的代码,就破坏了开放封闭原则。根本原因在于高层的的Driver类与底层的Car类仅仅的耦合在一起的。解决方法之一就是:对Car类和Bus类进行抽象,引入抽象类Automoble。而Car和Bus则是对Automobile的泛化。

经过这样的改造发现,原本的高层依赖底层,变成了高层与底层同时依赖抽象。这就是依赖倒转原则的本质。

 

五、接口隔离原则

接口隔离原则(Interface Segregation Principle):用于恰当的划分角色和接口,具有两种含义:1、用户不应该依赖它不需要的借口;2、类间的依赖关系应该建立在最小的的接口上。

将这两个定义概括为一句话:建立单一接口,代替庞大臃肿的接口。通俗来说就是:接口尽量细化,同时保证接口中的方法尽量的少。一个接口中包含太多的行为时,会导致它们与客户端的不正常依赖关系,要做的就是分离接口,从而实现解耦。

回到上述的单一职责原则,要求行为分离接口接口细化,感觉有些相同。但实际上,单一职责原则要求类与接口的职责单一,注重的是职责,没有要求接口尽量的少。

在接口隔离原则中,要求尽量使用多个专门的接口。专门的接口也就是提供给多个模块的接口。提供给几个模块就应该有几个接口,而不是建立一个臃肿庞大的接口,所有的模块都可以访问。

但是接口的设计是有限度的。接口的设计粒度越小系统越灵活,这是事实,但是接口太多这也就使得结构复杂,维护难度大。因此实际中,怎样把握就靠开发的经验和常识了。

六、迪米特原则

Law of Demeter(最小知识原则):一个对象应该对其他对象有最少的了解。通俗来说就是,一个类对自己需要耦合或者调用的类知道的最少,你类内部怎么复杂,我不管,那是你的事,我只知道你有那么多公用的方法,我能调用。

迪米特原则不希望类与类之间建立直接的接触。如果真的需要有联系,那么就通过它们的友元类来传达。举例来说:你需要买房子了,现在存在三座合适的楼盘A,B,C,但是你不必直接去楼盘买楼,而是在售楼处去了解情况。这样就减少了你(购房者)与楼盘两个类之间耦合。

但是应用迪米特原则很可能会造成一个后果:系统会存在大量的中介类,这些类(如上面的售楼处类)之所以存在是为了传递类之间的相互调用关系,这就一定会程度上增加了系统的复杂度。

迪米特原则核心观念就是:类间解耦,弱耦合。

原文地址 :https://www.cnblogs.com/welan/p/9005019.html

源码地址:https://github.com/weilanhanf/PythonDesignPatterns