23种设计模式对比与总结
设计模式总结:便于快速查看
前言:个人觉得设计模式就是各个对象在不同的时机、不同的调用方被创建,组合结构和封装的侧重点有些不同,从而形成了各个模式的概念。
1. 简单工厂模式
通过在工厂类中进行判断,然后创建需要的功能类。
优点:不必使用具体的功能类去创建该类的实例。缺点:新增一个功能类就需要在工厂类中增加一个判断。
2. 策略模式
假设一个功能类是一个策略,调用的时候需要创建这个策略的实例,传进一个类似策略控制中心的方法中,然后通过策略基类调用这个传进去的实例子类的方法。
优点:就是相对工厂模式免去了创建那个功能类的判断,简化了工厂模式。缺点:就是把子类实例赋值给了父类,这样就丢掉了子类新增的功能。
3. 工厂方法模式(属于工厂模式)
把简单工厂模式中的工厂类,做了进一步的抽象为接口或抽象类,给各个功能创建一个对应的工厂类,然后在这个工厂类里面去创建对应的实例。
缺点:当新增一个功能类,就需要创建对于的工厂类,相比简单工厂模式,免去了判断创建那个具体实例,但会创建过多的类,还不如策略模式。
4. 装饰模式
一般情况下,当一个基类写好之后,我们也许不愿意去改动,也不能改动,原因是
这样的在项目中用得比较久的基类,一旦改动,也许会影响其他功能模块,但是,
又要在该类上面添加功能。使用继承,当在A阶段,写出继承类,用过一段时间,发
现又要添加新功能,于是又要从原始类或A阶段的类继承,周而复始,慢慢的,子类就越来越多,层级就越来越深。然而,事实上,在C阶段需要A阶段的功能,但不需要B阶段的功能,在这种复杂情形下,继承就显得不灵活,于是想到了装饰模式。
装饰模式:
需要扩展一个类的功能,或给一个类增加附加责任
需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
在使用装饰模式前,需要了解虚方法和抽象方法的区别:虚方法,是实例方法,可以在子类中覆盖,也可以由该类对象直接调用。抽象方法需要写在抽象类中,抽象类不能实例化,所以要使用抽象方法必须由子类实现后方可调用。
该模式中,要被扩展的类可以是包含抽象方法的抽象类,也可以是包含虚方法的实例类,也可以是普通实例类。装饰模式就是在原有基类上做扩展,至于基类是什么性质并不重要.
装饰模式在C#代码,和扩展方法,惊人的类似。
5. 代理模式
代理类成为实际想调用对象的中间件,可以控制对实际调用对象的访问权限;维护实际调用对象的一个引用。
6. 原型模式
创建好了一个实例,然后用这个实例,通过克隆方式创建另一个同类型的实例,而不必关心这个新实例是如何创建的。
原型模式使用时需要注意浅拷贝与深拷贝的问题。
7. 建造者模式
每个对象都具备自己的功能,但是,它们的创建方式却是一样的。这个时候就需要中间这个建造者类来负责功能对象实例的创建。在调用端只需调用特定的方法即可。
这个和策略模式有点类似。
8. 抽象工厂模式
使用该功能类的功能类,利用抽象工厂去创建该功能类的实例。这样的好处在于尽可能的避免去创建功能的实例。
更牛逼的做法就是使用反射去创建这个功能类的实例,在调用端就一点都不需要知道要去实例化那个具体的功能类。这当然不是抽象工厂模式独有的。
9. 外观模式
外观模式:为外界调用提供一个统一的接口,把其他类中需要用到的方法提取出来,由外观类进行调用。然后在调用段实例化外观类,以间接调用需要的方法。这种方式形式上和代理模式有异曲同工之妙。
10.模板模式
模板模式:其实就是抽象出各个具体操作类的公共操作方法,在子类重新实现,然后使用子类去实例化父类。这个模板类其实可以使用接口替换。事实上接口才是专门用来定义操作规范。当然,当有些公共方法,各个子类均有一致需求,此时就不应使用接口,使用抽象类。
11. 状态模式
一个方法的判断逻辑太长,就不容易修改。方法过长,其本质就是,就是本类在不同条件下的状态转移。状态模式,就是将这些判断分开到各个能表示当前状态的独立类中。
12. 备忘录模式
备忘录模式:事实上我觉得这个东西没什么用,安照这种方式进行备份,会因为值类型与引用类型的不同而导致数据丢失。
13. 适配器模式
适配器模式:其实就是代理模式的一个变种,代码的编写方式都差不多。只是,使用这两种模式的出发点不一样,导致这两种模式产生了细微的差别。
14. 组合模式
当对象或系统之间出现部分与整体,或类似树状结构的情况时,考虑组合模式。相对装饰模式来说,这两个有异曲同工之妙,都强调对象间的组合,但是,装饰模式同时强调组合的顺序,而组合模式则是随意组合与移除。
15. 单例模式
能避免同一对象被反复实例化。比如说,访问数据库的连接对象就比普通对象实例化的时间要长;WCF中,维护服务器端远程对象的创建等,这类情况,很有必要用单例模式进行处理对象的实例化。
16. 迭代器模式
提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。
Foreach就是这种模式应用的代表。
17. 职责链模式
职责链模式:就是一个将请求或命令进行转发的流程,类似工作流。并且,也非常类似状态模式,它们共同的特点就是将一个复杂的判断逻辑,转移到各个子类,然后在由子类进行简单判断。
状态模式与职责链模式的区别:状态模式是让各个状态对象自己知道其下一个处理的对象是谁,即在编译时便设定好了的;而职责链模式中的各个对象并不指定其下一个处理的对象到底是谁,只有在客户端才设定。
18. 命令模式
当有客户端发送了一系列的命令或请求,去要求某个对象实现什么操作,可使用命令模式,相当于多个命令发给一个对象。
这一点和观察者模式非常的类似。观察者模式也是某个对象,发出消息,然后由中间对象通知观察者然后去做什么,封装的是要执行操作的对象。而命令模式,则是将各个操作封装成类,然后告知某个对象该做什么。两者的区别是封装的角度不同。
19. 桥接模式
依据合成/聚合原则,优先使用类之间的不同组合,来实现各个类要表现的功能,而不是使用继承。比如说:继承会延续父类的功能,然而,并不是所有的子类都需要这样的功能,但是抽象出的东西在父类,导致子类又必须要实现它,这样,父类就越来越庞大,子类又多了很多不必要的东西。因此,桥接模式更强调类之间的组合从而实现解耦。
对比组合模式,它更强调的是部分与整体间的组合,桥接模式强调的是平行级别上不同类的组合。
20. 解释器模式
举例:写好了C#代码,VB代码,此时需要个编译器来编译。这时,这个编译器就相当于解释器,解释好了交给CPU执行。
解释器跟适配器模式有点类似,但是,适配器模式不需要预先知道要适配的规则,解释器是根据规则去执行解释。
21. 享元模式
享元模式其实是为了避免创建过多的数据对象。比如此列:在象棋中只有红黑双方,红棋子只是红棋中的一颗,很多红棋其实可以使用一个红棋对象表示即可,在外部只需公开该棋的状态即可区分那个红棋,从而达到减少内存消耗的目的。
22.中介者模式
中介者模式:中介者类唯一要干的事情就是给各个成员对象发出通知。因此,中介者事先就应该知道有哪些成员。
中介者模式和代理模式,观察者模式非常的像。但是其它两种模式在调用的时候,并不需要事先设置那个类被代理,或是事先那些对象需要被通知。
23. 访问者模式
在不改变原有代码的结构上,又想去影响原来的类,或是访问原来类的成员,此时就可以使用访问者模式。但需要注意的是:事先需要构造好那些要访问的对象的对象结构。这个结构在访问者类中去维护。
24. 观察者模式
就是消息订阅--发布模式。本来原始的状况是需要在观察者类内部设置需要通知的对象。结果现在出现了事件。定义委托来通知其他对象,显得更简洁。
转帖自:23种设计模式对比与总结