设计模式对比

工厂模式vs建造者模式

工厂模式建造者模式都属于对象创建类模式,都用来创建类的对象,工厂模式注重的是整体对象的创建方法,而建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。

建造者模式在某些应用场景下甚至会关心产品的构建顺序,即使是相同的部件,装配顺序不同,产生的结果也不同,这也正是建造者模式的意图, 通过不同的部件不同装配产生不同的复杂对象

具体的应用中是选择工厂模式还是建造者模式,完全取决于做系统设计时的意图,若需要详细关注一个产品部件的生产、安装步骤则选择建造者模式,否则选择工厂模式

意图不同

工厂模式关注的是一个产品整体,无须关心产品的各部分是如何创建出来的,是一个对象创建的粗线条应用

建造者模式中一个具体产品的产生是依赖各个部件的产生以及装配顺序,关注的是由零件一步一步地组装出产品对象,通过细线条勾勒出一个复杂对象,关注的是产品组成部分的创建过程

产品复杂度不同

工厂模式创建的产品一般都是单一性质产品,工厂模式的对象粒度比较粗

建造者模式创建的则是一个复合产品,它由各个部件复合而成,部件不同产品对象当然不同,产品对象粒度比较细


代理模式vs装饰模式

装饰模式就是代理模式的一个特殊应用,两者的共同点是都具有相同的接口代理模式着重对代理过程的控制装饰模式则是对类的
功能进行加强或减弱,它着重类的功能变化

代理模式是把当前的行为功能委托给其他对象执行,代理类负责接口限定,包括是否可以调用真实角色,以及是否对发送到真实角色的消息进行变形处理,它不对被代理类的功能做任何处理, 保证原汁原味的调用,代理模式使用到极致开发就是AOP应用非常广泛

装饰模式是在要保证接口不变的情况下加强类的功能,它保证的是被修饰的对象功能比原始对象丰富,当然也可以减弱, 但不做准入条件判断准入参数过滤,如是否可以执行类的功能,过滤输入参数是否合规等, 这不是装饰模式关心的,实际应用中接触比较少,JDK的java.io.*包中就大量使用装饰模式。

1
OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"))

装饰模式vs适配器模式

装饰模式适配器模式通用类图上差别比较大,但它们都是包装作用,都是通过委托方式实现其功能

意图不同

装饰模式的意图是加强对象的功能

适配器模式关注的则是转化,主要意图是两个不同对象之间的转化

施与对象不同

装饰模式包装的是自己的兄弟类,隶属于同一个家族相同接口父类,只要在具有相同的属性行为的情况下,才能比较行为是增加还是减弱。

适配器模式修饰非血缘关系类,把一个非本家族的对象伪装成本家族的对象,必须是两个不同的对象,因为它着重于转换,只有两个不同的对象才有转换的必要。

场景不同

装饰模式任何时候都可以使用,只要是想增强类的功能。

适配器模式则是一个补救模式, 一般出现在系统成熟已经构建完毕的项目中, 作为一个紧急处理手段采用。

扩展性不同

装饰模式很容易扩展,今天不用这个修饰则去掉,明天想再使用则加上,且装饰类可以继续扩展下去。

适配器模式是在两个不同对象之间架起了一座沟通的桥梁,建立容易去掉困难,需要从系统整体考虑是否能够撤销。


命令模式vs策略模式

命令模式策略模式的类图很相似,只是命令模式多了一个接收者角色。

策略模式意图封装算法,它认为算法已经是一个完整的不可拆分原子业务,其意图是让这些算法独立,并且可以相互替换让行为的变化独立于拥有行为的客户

命令模式则是对动作的解耦, 把一个动作的执行分为执行对象接收者角色执行行为命令角色,让两者相互独立而不相互影响。且接收者的处理可以进行排队处理,在排队处理的过程中,可以进行撤销处理

关注点不同

策略模式关注的是算法替换的问题,一个新算法投产旧算法退休,或提供多种算法由调用者自己选择使用,算法的自由更替是它实现的要点。策略模式关注的是算法完整性封装性, 只有具备了这两个条件才能保证其可以自由切换。

命令模式则关注的是解耦问题,如何让请求者执行者解耦是它需要首先解决的,解耦的要求就是把请求的内容封装为一个一个的命令由接收者执行。由于封装成了命令,就同时可以对命令进行多种处理,如撤销、记录等。

角色功能不同

策略模式中的具体算法是负责一个完整算法逻辑,它是不可再拆分原子业务单元,一旦变更就是对算法整体的变更。

命令模式关注命令的实现,即功能的实现一个命令影响范围也仅仅是抽象命令具体命令,对它的修改不会扩散到模式外的模块。

使用场景不同

策略模式适用于算法要求变换的场景。

命令模式适用于解耦两个有紧耦合关系的对象场合多命令多撤销的场景。


策略模式vs状态模式

状态模式策略模式是亲兄弟两者非常相似,都是通过Context类封装一个具体的行为,都提供了一个封装方法,是高扩展性设计模式。

策略模式封装的是不同的算法,算法之间没有交互,以达到算法可以自由切换的目的。

状态模式封装的是不同的状态,以达到状态切换行为随之发生改变的目的。

环境角色职责不同

两者都有一个叫做Context环境角色的类,但是两者的区别很大,策略模式环境角色只是一个委托作用负责算法的替换

状态模式环境角色不仅仅是委托行为,它还具有登记状态变化的功能,与具体的状态类协作,共同完成状态切换行为随之切换的任务;

解决问题重点不同

策略模式旨在解决内部算法如何改变的问题,即将内部算法的改变对外界的影响降低到最小,它保证的是算法可以自由地切换

状态模式旨在解决内在状态的改变而引起行为改变的问题,它的出发点是事物的状态封装状态而暴露行为,一个对象的状态改变,从外界来看就好像是行为改变。

解决问题方法不同

策略模式只是确保算法可以自由切换,但是什么时候用什么算法它决定不了;

状态模式对外暴露的是行为状态的变化一般是由环境角色具体状态共同完成的,也就是说状态模式封装了状态的变化而暴露了不同的行为或行为结果

应用场景不同

策略模式只是一个算法的封装,可是一个有意义的对象,也可以是一个无意义的逻辑片段,策略模式是一系列平行的可相互替换的算法封装后的结果,这就限定了它的应用场景,即算法必须是平行的,否则策略模式就封装了一堆垃圾,产生了坏味道。

状态模式则要求有一系列状态发生变化的场景,它要求的是有状态有行为的场景,也就是一个对象必须具有二维即状态和行为描述才能采用状态模式,若只有状态没有行为,则状态的变化就失去了意义。

复杂度不同

策略模式结构比较简单、扩展比较容易且代码也容易阅读;

状态模式则通常比较复杂,它要从两个角色看到一个对象状态和行为的改变,虽然也很容易扩展,但一般不会进行大规模的扩张和修正;


观察者模式vs责任链模式

链中消息对象不同

责任链模式基本上不改变消息对象的结构,虽然每个节点都可以参与消费,但它的结构不会改变;

观察者模式中是允许改变对象结构的,链中传递的对象可以自由变化,只要上下级节点对传递对象了解即可,它不要求链中的消息对象不变化,它只要求链中相邻两个节点的消息对象固定

上下节点关系不同

责任链模式上下节点没有关系,都是接收同样的对象,所有传递的对象都是从链首传递过来,上一节点是什么没有关系,只要按照自己的逻辑处理就成。

观察者模式上下级关系很亲密,下级对上级顶礼膜拜,上级对下级绝对信任,链中的任意两个相邻节点都是一个牢固的独立团体

消息分销渠道不同

责任链模式中一个消息从链首传递进来后,就开始沿着链条向链尾运动方向是单一固定的

观察者模式有非常大的灵活性,一个消息传递到链首后,具体怎么传递是不固定的,可以以广播方式传递,也可以以跳跃方式传递,这取决于处理消息的逻辑;


策略模式vs桥梁模式

策略模式是一个行为模式,旨在封装一系列的行为策略模式是使用继承多态建立一套可以自由切换算法的模式

桥梁模式关注的是抽象实现分离,它是结构型模式,结构型模式研究的是如何建立一个软件架构,是解决在不破坏封装的情况下如何抽取出它的抽象部分实现部分,让抽象部分实现部分都可以独立地变化和扩展


门面模式vs中介模式

门面模式是以封装隔离为主要任务。

中介者模式则是以调和类之间的关系为主,因为要调和,所以具有了部分的业务逻辑控制

功能区别

门面模式只是增加了一个门面,它对子系统来说没有增加任何的功能,子系统若脱离门面模式是完全可以独立运行的

中介者模式增加了业务功能,它把各个类中原有耦合关系移植到了中介者,业务类不可能脱离中介者而独立存在,除非是想增加系统的复杂性和降低扩展性。

知晓状态不同

门面模式子系统不知道有门面存在

中介者模式每个业务类都知道中介者存在,因为要依靠中介者调和业务类之间的关系,它们对中介者非常了解;

封装程度不同

门面模式是一种简单的封装,所有的请求处理都委托给子系统完成

中介者模式则需要有一个中心,由中心协调业务类完成,且中心本身也完成部分业务,它属于更进一步的业务功能封装


包装模式对比

包装模式包括:装饰模式适配器模式门面模式代理模式桥梁模式,都是通过委托的方式对一个对象或一系列对象施行包装。

代理模式主要用在不希望展示一个对象内部细节的场景中,如一个远程服务不需要把远程连接的所有细节都暴露给外部模块,通过增加一个代理类,可很轻松地实现被代理类的功能封装。此外代理模式还可以用在一个对象的访问需要限制的场景中如AOP。

装饰模式是一种特殊的代理模式,它倡导的是在不改变接口的前提下为对象增强功能动态添加额外职责。就扩展性而言,它比子类更加灵活,如在一个已经运行的项目中,可很轻松地通过增加装饰类来扩展系统的功能。

适配器模式的主要意图是接口转换,把一个对象的接口转换成系统希望的另外一个接口,这里的系统指的不仅仅是一个应用,也可能是某个环境,比如通过接口转换可以屏蔽外界接口,以免外界接口深入系统内部,从而提高系统的稳定性和可靠性。

桥梁模式是在抽象层产生耦合解决的是自行扩展的问题,它可使两个有耦合关系的对象互不影响地扩展,如对于使用笔画图这样的需求,可采用桥梁模式设计成用什么笔画什么图的方案,至于以后需求的变更,如增加笔的类型,增加图形等,对该设计不会产生影响。

门面模式是一个粗粒度的封装,它提供一个方便访问子系统的接口,不具有任何的业务逻辑,仅仅是一个访问复杂系统的快速通道,没有它,子系统照样运行。