设计模式对比

2019-09-16  本文已影响0人  王侦

1.简单工厂、工厂模式和抽象工厂

简单工厂:将实现封装在Factory中;
工厂模式:将不同的实现封装在不同的Factory中;
抽象工厂:扩充产品类型,简单工厂和工厂模式针对的是一种类型的产品,而抽象工厂是针对多种相关联的产品簇,选择一个Factory,可以构建一个相互关联的产品簇。

2.构建类型的模式

工厂类模式:将类的实现封装在Factory中。
建造者模式:分离不变的整体构建算法和可变的部件构造。
原型模式:克隆生成对象。使用面向接口方式,可以实现多种克隆。注意深度拷贝怎么实现。
单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。注意饿汉式和懒汉式实现。最经典的的懒汉式实现是——静态内部类。

记忆方式——FBPS

3.结构型模式

适配器模式:转换匹配,复用功能。需要继承Target接口,然后调用Adaptee方法实现Target接口。
桥接模式:分离抽象和实现。让抽象部分拥有实现部分的接口对象,在抽象部分就可以通过这个接口来调用具体实现部分的功能。核心本质是面向接口编程。
组合模式:统一叶子对象和组合对象。将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
装饰器模式:动态组合。动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。装饰器一定要实现和组件类一致的接口,保证它们是同一个类型,并具有同一个外观,这样组合完成的装饰才能够递归的调用下去。
享元模式:分离出大量细粒度重复对象,然后放到实例池中进行共享。
外观模式:封装交互,简化调用。核心就是封装,降低耦合。
代理模式:为其它对象提供一种代理以控制对这个对象的访问。有静态代理和动态代理,动态代理包括JDK动态代理和CGLIB动态代理。

在做一个小分类:

封装降低耦合:外观模式;
功能增强:装饰器模式、代理模式;
面向接口编程:适配器模式、桥接模式、组合模式;

记忆方式:ABCDFFP

4.行为型

解释器模式Interpreter:解释指定文法的句子。
模板方法模式Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
责任链模式Chain of Responsibility:分离职责,动态组合。对象组成链。避免请求的发送者和接收者之间的耦合关系。
命令模式Command:把请求封装成为对象,并定义了统一的执行操作的接口,这个命令对象可以被存储、转发、记录、处理、撤销等。
迭代器模式Iterator:提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
中介者模式Mediator:用一个中介对象来封装一系列的对象交互。与主板的功能非常类似。
备忘录模式Memento:在不破坏封装的前提下,保存和恢复内部状态。
观察者模式Observer:当目标对象的状态发送变化时,依赖于它的对象都被通知并执行相应操作。
状态模式State:根据状态来分离和选择行为。在其内部状态改变时改变它的行为。
策略模式Strategy:定义一系列算法,并且它们可以相互替换。
访问者模式Visitor:预留通路,回调实现。可以在不改变类结构的前提下定义操作这些类的新操作。

记忆方式:

ITCCIMMOSSV
IT男要经常喝CC,I'm就是经常吃moss(地衣)V维生素含量高。

解释器相关:

解释器模式——按照文法解释句子
访问者模式——解释器可以按照访问者模式实现
组合模式——抽象语法树的结构就是组合模式

回调相关:

命令模式
模板方法模式
访问者模式

策略模式与模板方法模式组合(前提:所有方法骨架相同):

策略模式定义整个骨架
模板方法模式定义所有算法的骨架

封装

迭代器模式:提供统一的访问方式,隐藏内部表示
中介者模式:封装内部对象交互
外观模式:向外提供简化的接口调用
工厂类模式:封装类的实现

5.不同维度的联系(纵向和横向拓展)

5.1 整体三大类

记忆方式


5.2 设计模式原则

5.2.1 开闭原则(Open Closed Principle,OCP)

在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

要实现对扩展开放,对修改关闭,即遵循开闭原则,需要对系统进行抽象化设计,抽象可以基于抽象类或者接口。一般来说需要做到几点:

开闭原则的核心:面向接口或者面向抽象编程,这样基于里氏替换原则,可以方便地进行扩展而无需修改现有代码。

所以符合面向接口编程或者面向抽象编程的设计模式都符合开闭原则:

5.2.1 里氏代换原则(Liskov Substitution Principle,LSP)

所有引用基类的地方必须能透明地使用其子类的对象,也可以简单理解为任何基类可以出现的地方,子类一定可以出现。

只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对"开-闭"原则的补充。实现"开-闭"原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。

里氏代换原则是实现开闭原则的基础,它告诉我们在设计程序的时候进可能使用基类进行对象的定义和引用,在运行时再决定基类的具体子类型。

5.2.1 依赖倒转原则(Dependency Inversion Principle,DIP)

程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。

依赖倒转原则的注意事项:

例如:

5.2.2 单一职责原则(Single Responsibility Principle, SRP)

一个类或者模块应该有且只有一个改变的原因。如果一个类承担的职责过多,就等于把这些职责耦合在一起了。此原则的核心就是解耦和增强内聚性。

一个类不能做太多的东西。在软件系统中,一个类(一个模块、或者一个方法)承担的职责越多,那么其被复用的可能性就会越低。

项目分层:数据库层、service层、controller层。

5.2.3 接口隔离原则(Interface Segregation Principle,ISP)

户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上。简单来说就是建立单一的接口,不要建立臃肿庞大的接口。也就是接口尽量细化,同时接口中的方法尽量少。

接口隔离原则的规范:

符合ISP原则的设计模式:

5.2.4 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)

尽量使用合成/聚合,而不是通过继承达到复用的目的。

合成/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向内部持有的这些对象的委派达到复用已有功能的目的,而不是通过继承来获得已有的功能。

聚合(Aggregate)的概念:

合成(Composite)的概念:

继承复用破坏包装,因为继承将基类的实现细节暴露给派生类,基类的内部细节通常对子类来说是可见的,这种复用也称为"白箱复用"。这里有一个明显的问题是:派生类继承自基类,如果基类的实现发生改变,将会影响到所有派生类的实现;如果从基类继承而来的实现是静态的,不可能在运行时发生改变,不够灵活。

由于合成或聚合关系可以将已有的对象,一般叫成员对象,纳入到新对象中,使之成为新对象的一部分,因此新对象可以调用已有对象的功能,这样做可以使得成员对象的内部实现细节对于新对象不可见,所以这种复用又称为"黑箱"复用,相对继承关系而言,其耦合度相对较低,成员对象的变化对新对象的影响不大,可以在新对象中根据实际需要有选择性地调用成员对象的操作;合成/聚合复用可以在运行时动态进行,新对象可以动态地引用与成员对象类型相同的其他对象。

一般情况下,只有明确知道派生类和基类满IS A的时候才选用继承,当满足HAS A或者不能判断的情况下应该选用合成/聚合。

符合合成/聚合复用原则的设计模式:

GoF中说明的模式:

5.2.5 最少知识原则(Least Knowledge Principle,LKP)或者迪米特法则(Law of Demeter,LOD)

一个软件实体应当尽可能少地与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类(中间类或者跳转类)来转达。

迪米特法则的规则:

迪米特法则的核心观念就是类间解耦,也就降低类之间的耦合,只有类处于弱耦合状态,类的复用率才会提高。所谓降低类间耦合,实际上就是尽量减少对象之间的交互,如果两个对象之间不必彼此直接通信,那么这两个对象就不应当发生任何直接的相互作用,如果其中的一个对象需要调用另一个对象的某一个方法的话,可以通过第三者转发这个调用。简言之,就是通过引入一个合理的第三者来降低现有对象之间的耦合度。但是这样会引发一个问题,有可能产生大量的中间类或者跳转类,导致系统的复杂性提高,可维护性降低。

符合该原则的社模式:

5.3 其他分类

不能方便地对类进行修改:

5.4 GoF对设计模式用途的分类

记忆法总结

上一篇下一篇

猜你喜欢

热点阅读