设计模式23种类图
- 格式:doc
- 大小:215.00 KB
- 文档页数:17
二十三种设计模式0 引言谈到设计模式,绝对应该一起来说说重构。
重构给我们带来了什么?除了作为对遗留代码的改进的方法,另一大意义在于,可以让我们在写程序的时候可以不需事先考虑太多的代码组织问题,当然这其中也包括了应用模式的问题。
尽管大多数开发者都已经养成了写代码前先从设计开始的习惯,但是,这种程度的设计,涉及到到大局、到总体架构、到主要的模块划分我觉得就够了。
换句话说,这时就能写代码了。
这就得益于重构的思想了。
如果没有重构的思想,有希望获得非常高质量的代码,我们就不得不在开始写代码前考虑更多其实并非非常稳定的代码组织及设计模式的应用问题,那开发效率当然就大打折扣了。
在重构和设计模式的合理应用之下,我们可以相对较早的开始写代码,并在功能尽早实现的同时,不断地通过重构和模式来改善我们的代码质量。
所以,下面的章节中,在谈模式的同时,我也会谈谈关于常用的这些模式的重构成本的理解。
重构成本越高意味着,在遇到类似的问题情形的时候,我们更应该提前考虑应用对应的设计模式,而重构成本比较低则说明,类似的情形下,完全可以先怎么方便,怎么快怎么写,哪怕代码不是很优雅也没关系,回头再重构也很容易。
1 创建型1.1FactoryMethod思想:Factory Method的主要思想是使一个类的实例化延迟到其子类。
场景:典型的应用场景如:在某个系统开发的较早阶段,有某些类的实例化过程,实例化方式可能还不是很确定,或者实际实例化的对象(可能是需要对象的某个子类中的一个)不确定,或者比较容易变化。
此时,如果直接将实例化过程写在某个函数中,那么一般就是if-else或select-case代码。
如果,候选项的数目较少、类型基本确定,那么这样的if-else还是可以接受的,一旦情形变得复杂、不确定性增加,更甚至包含这个构造过程的函数所在的类包含几个甚至更多类似的函数时,这样的if-else代码就会变得比较不那么容易维护了。
此时,应用本模式,可以将这种复杂情形隔离开,即将这类不确定的对象的实例化过程延迟到子类。
23种基本的设计模式设计模式指的是在软件设计过程中,面对特定问题时能够重复使用的解决方案。
设计模式可帮助开发人员更完整、更高效地解决问题,并提高代码的可读性和可维护性。
在软件开发中,有23种基本的设计模式。
1. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问点。
2. 工厂模式(Factory Pattern):通过工厂方法创建对象,而不是直接实例化。
3. 抽象工厂模式(Abstract Factory Pattern):提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。
4. 建造者模式(Builder Pattern):将一个复杂对象的构造与它的表示分离,使得同样的构造过程可以创建不同的表示。
5. 原型模式(Prototype Pattern):通过复制已有对象来创建新对象,而不是通过实例化。
6. 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的接口。
7. 桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们可以独立变化。
9. 装饰器模式(Decorator Pattern):动态地给一个对象添加额外的职责。
10. 外观模式(Facade Pattern):为子系统中的一组接口提供统一的接口,以提供更高级别的接口。
11. 享元模式(Flyweight Pattern):通过共享已存在的对象来减少内存占用。
12. 代理模式(Proxy Pattern):为其他对象提供一个代理以控制对这个对象的访问。
13. 模板方法模式(Template Method Pattern):定义一个操作中的算法骨架,而将一些步骤延迟到子类中。
14. 策略模式(Strategy Pattern):定义一系列的算法,将其逐个封装起来,并使它们可以相互替换。
15. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,让多个观察者对象同时监听其中一个主题对象。
23种设计模式记忆口诀1.单例模式:独一无二,最重要。
2.工厂模式:制造者,无需说。
3.抽象工厂:一族产品,同根源。
4.建造者模式:一步一步,建造家。
5.原型模式:克隆专家,快捷法。
6.适配器模式:转换者,聪明智。
7.桥接模式:结构优化,灵活性。
8.装饰模式:装饰者,美化家。
9.组合模式:树形结构,组合家。
10.外观模式:微缩封装,简洁家。
11.享元模式:享元工厂,节省家。
12.代理模式:替身幕后,保护家。
13.模板方法:算法继承,不变家。
14.策略模式:行为封装,灵活家。
15.命令模式:命令者,有权家。
16.职责链模式:可扩展,级别性。
17.状态模式:状态管理,干净家。
18.观察者模式:被观察,自主家。
19.中介者模式:中介者,沟通家。
20.迭代器模式:循环选择,简化家。
21.访问者模式:动态添加,扩展家。
22.备忘录模式:状态备份,还原家。
23.解释器模式:解释语言,特殊家。
以上23种设计模式,为了更好地记忆,我把它们组合成了一个口诀:最重要的单例模式,工厂与抽象同皇冠。
建造渐进如养家,克隆是原型美化家。
适配器桥接转化家,组合成树形结构家。
装饰装扮美化家,微缩封装外观家。
享元共用节省家,代理替身保护家。
策略模式灵活家,命令者有权家。
职责链扩展级别性,状态干净管理家。
被观察自主家,中介者沟通家。
循环迭代简化家,访问者动态扩展家。
备忘录变化还原家,解释语言特殊家。
这个口诀是通过把每个模式的主要特点和功能用简洁的语句表达出来,然后通过排列组合的方式形成的。
相信这个口诀会让你更容易地记忆这23种设计模式,并且可以在以后的工作中灵活地运用它们。
面向对象设计的23个设计模式详解面向对象设计是一种广泛应用于软件开发的思想,其核心在于将数据和操作封装在一起形成对象,并通过各种方式进行交互和组合,从而实现复杂的功能。
在这一过程中,设计模式起到了非常重要的作用,可以有效地提高代码的可读性、可维护性和可扩展性。
本文将对23种常见的设计模式进行详解。
一、创建型模式1.简单工厂模式简单工厂模式属于创建型模式,其目的是提供一个工厂类,使得创建对象的过程更加简单。
在这种模式中,使用者只需要提供所需对象的参数,而无需关心对象的具体实现细节。
简单工厂模式适合于对象创建过程较为简单的情况。
2.工厂方法模式工厂方法模式是简单工厂模式的进一步扩展,其核心在于将工厂类进行接口抽象化,使得不同的工厂类可以创建不同的对象实例。
工厂方法模式适合于对象创建过程较为复杂的情况。
它可以为工厂类添加新的产品类型,而不会影响原有的代码。
3.抽象工厂模式抽象工厂模式是工厂方法模式的进一步扩展,其目的是提供一个可以创建一系列相关或者独立的对象的接口。
在抽象工厂模式中,使用者只需要关心所需对象组合的类型,而无需关注对象的具体实现过程。
4.建造者模式建造者模式也是一种创建型模式,其目的在于将复杂对象分解为多个简单的部分,并将其组装起来形成复杂对象实例。
在建造者模式中,使用者只需要关注所需对象以及它们的组合方式,而无需关心对象的具体实现过程。
5.原型模式原型模式是一种基于克隆的创建型模式,其核心在于通过复制现有的对象实例来创建新的对象。
在原型模式中,对象实例的创建过程与对象所包含的状态密切相关。
原型模式适合于创建复杂对象实例,且这些对象实例之间是相对独立的情况。
二、结构型模式6.适配器模式适配器模式是一种结构型模式,其目的在于将一个类的接口转换为另一个类所能使用的接口。
在适配器模式中,使用者可以通过不同的适配器实现对象之间的互相调用。
7.桥接模式桥接模式是一种结构型模式,其目的在于将抽象部分与实现部分相互分离,从而使得两者可以独立变化。
23种设计模式记忆口诀
1.单例模式:唯一实例化,静态访问,线程不安全
2. 工厂方法模式:子类实现,工厂创建,扩展性强
3. 抽象工厂模式:创建一族产品,接口约束,扩展性强
4. 建造者模式:组合复杂对象,分步骤构建,灵活性高
5. 原型模式:克隆对象,避免重复创建,效率高
6. 适配器模式:兼容接口不同,类似转换器,易扩展
7. 桥接模式:抽象与实现分离,解耦合,易扩展
8. 装饰器模式:动态增强对象功能,不影响原有对象,易扩展
9. 组合模式:层次结构,统一访问,易扩展
10. 外观模式:简化复杂系统调用,易使用,易扩展
11. 享元模式:共享资源,避免重复创建,效率高
12. 代理模式:增强对象功能,控制对象访问,易扩展
13. 责任链模式:多个对象处理请求,自动传递,易扩展
14. 命令模式:将请求封装成对象,易扩展,易记录日志
15. 解释器模式:解释语言,易扩展,易维护
16. 迭代器模式:遍历集合,统一访问,易扩展
17. 中介者模式:分离对象间交互,降低耦合,易扩展
18. 观察者模式:对象状态改变,通知观察者,易扩展
19. 备忘录模式:保存对象状态,易恢复,易扩展
20. 状态模式:对象状态改变,自动改变行为,易扩展
21. 策略模式:选择不同策略,易切换,易扩展
22. 模板方法模式:定义操作流程,易扩展,易维护
23. 访问者模式:统一访问集合中对象,易扩展,易维护。
23种设计模式详解设计模式是指面向对象编程中,经过多次验证、被广泛接受的代码实现方法。
这些设计模式可以帮助开发者更快地解决问题,提高代码的可读性、可维护性、可扩展性。
目前,常用的设计模式有23种。
下面,我们来详细介绍一下这23种设计模式。
1. 单例模式(Singleton)单例模式是一种只允许生成一个实例的模式。
在实例化对象时,单例模式的生成过程比较特殊,需要先判断该类是否已经实例化过,如果已经实例化,则直接返回已有的实例对象,否则再进行实例化。
2. 工厂模式(Factory)工厂模式是一种生产对象实例的设计模式。
它将对象实例的生成过程封装在一个工厂类中,客户端需要对象时,只需要调用工厂类中对应的方法即可。
3. 抽象工厂模式(Abstract Factory)抽象工厂模式是一种扩展了工厂模式的模式。
它可以生成一系列相关或相互依赖的对象实例。
具体实现时,通常需要定义一个抽象工厂类和一些具体工厂类,来生产各种相关的对象实例。
4. 建造者模式(Builder)建造者模式是一种用于构建复杂对象的模式。
它将一个复杂对象的构建过程分解成多个简单的步骤,然后通过一个指挥者来管理这些步骤的执行,最终构建出一个复杂的对象。
5. 原型模式(Prototype)原型模式是一种通过复制已有对象来创建新对象的模式。
一般来说,系统中的对象包含大量相同或相似的部分,通过复制对象可以帮助我们节省生成对象的时间和资源。
6. 适配器模式(Adapter)适配器模式是一种将不兼容接口转换为兼容接口的模式。
具体实现时,需要定义一个适配器类,该类实现了客户端所期望的接口,而且还包装了原有不兼容的接口,使其能够兼容客户端期望的接口。
7. 桥接模式(Bridge)桥接模式是一种将抽象部分与其实现部分分离开来的模式。
具体实现时,需要定义抽象部分和实现部分的接口,然后定义一个桥接类,将抽象部分和实现部分联系起来。
8. 组合模式(Composite)组合模式是一种将具有相同属性和方法的对象组合成树形结构的模式。
23种设计模式记忆口诀根据内容要求,对23种设计模式进行简要说明,并整理成口诀。
设计模式是软件开发中常用的一种解决方案,它提供了面向对象设计和编程中常见问题的解决思路和方法。
根据GoF(Gang of Four)的分类,设计模式可以分为创建型、结构型和行为型三种类型,共23种设计模式。
1. 创建型模式(Creational Patterns):- 工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,但由子类决定实例化的类。
- 抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关对象或依赖对象的接口,而无须指定它们的具体类。
- 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。
- 原型模式(Prototype Pattern):用于创建重复性对象的一个原型。
- 建造者模式(Builder Pattern):将一个复杂对象的构建和表示分离,使得同样的构建过程可以创建不同的表示。
2. 结构型模式(Structural Patterns):- 适配器模式(Adapter Pattern):将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。
- 桥接模式(Bridge Pattern):将抽象部分和它真正的实现分离,使它们独立的变化。
- 装饰器模式(Decorator Pattern):动态地将责任附加到对象上,扩展功能。
- 外观模式(Facade Pattern):为子系统中的一组接口提供一个统一的接口,以简化系统的使用。
3. 行为型模式(Behavioral Patterns):- 策略模式(Strategy Pattern):定义一系列算法,将每个算法封装起来,并使它们可以相互替换。
- 模板方法模式(Template Method Pattern):定义一个算法的骨架,由子类实现具体步骤。
23种设计模式记忆技巧设计模式是一种解决设计问题的方案,在软件开发过程中起到了重要的作用。
然而,记忆设计模式的名称、特征和用法有时可能会让人感到困难。
为了帮助大家记住常用的23种设计模式,我将分享一些记忆技巧。
1. 单例模式(Singleton Pattern):想象一个宇宙中只存在一个唯一的太阳。
2. 简单工厂模式(Simple Factory Pattern):把工厂当做一个有丰富经验的魔术师,可以根据参数创建魔术道具。
3. 工厂方法模式(Factory Method Pattern):把工厂当做一个可以生产各种不同产品的工厂。
4. 抽象工厂模式(Abstract Factory Pattern):想象一个超级工厂,可以生产各种不同类型的产品。
5. 建造者模式(Builder Pattern):抽象出建造过程,让一个团队可以用不同的组件构建出不同的产品。
6. 原型模式(Prototype Pattern):把对象看作是一个可复制的模板。
7. 适配器模式(Adapter Pattern):把一个接口转换成另一个接口,就像使用插头转换器。
8. 桥接模式(Bridge Pattern):想象一个人过河,桥是连接两岸的桥梁。
9. 装饰器模式(Decorator Pattern):想象一个圣诞树,可以在上面加入各种装饰品。
11. 外观模式(Facade Pattern):把一系列复杂的操作封装成一个简单的接口。
12. 享元模式(Flyweight Pattern):把对象分为内部状态和外部状态,尽量共享内部状态。
13. 代理模式(Proxy Pattern):想象一个忙碌的明星,通过经纪人代理各种事务。
14. 策略模式(Strategy Pattern):将不同的策略封装成不同的对象,可以根据需求动态选择策略。
15. 模板方法模式(Template Method Pattern):定义一个算法的骨架,具体步骤由子类实现。
23种设计模式的经典运用介绍设计模式是解决软件设计中常见问题的可重复使用的解决方案。
本文将介绍23种经典的设计模式,并给出它们在实际开发中的应用示例。
通过学习这些设计模式,您将增加对软件设计的理解,并能够更好地解决问题。
创建型设计模式1.工厂方法模式(F a c t o r y M e t h o d)工厂方法模式通过定义一个创建对象的接口,但由子类决定实例化具体类。
这种方法可以延迟实例化过程,具有更高的灵活性和可扩展性。
应用场景:-在一个系统中,希望客户端与具体类的实例化解耦。
-希望通过增加具体类的扩展来增加系统的灵活性。
2.抽象工厂模式(A b s t r a c t F a c t o r y)抽象工厂模式提供一个接口,用于创建相关或依赖对象组。
这种模式将对象的实例化推迟到子类中,从而实现了解耦。
应用场景:-当一个系统独立于其产品的创建、组合和表示时。
-当需要一个系列的相互依赖的对象而无需指定其具体类时。
3.单例模式(S i n gl e t o n)单例模式确保一个类只有一个实例,并提供一个全局访问点。
这种模式常用于控制对资源的访问,例如数据库连接或日志文件。
应用场景:-当需要一个类的唯一实例,并且该实例需要被多个客户端共享时。
-当需要限制系统中特定类的实例数量时。
4.原型模式(P r o to t y p e)原型模式通过复制现有对象来创建新对象。
这种模式对于创建需要消耗大量资源的对象非常有用,可以通过克隆现有对象来提高性能。
应用场景:-当一个系统的某些对象的创建比较昂贵时。
-当需要避免构造函数调用,而直接通过复制现有对象来创建新对象时。
5.建造者模式(B ui l d e r)建造者模式将一个复杂对象的构建过程与其表现分离,使得相同的构建过程可以创建不同的表现。
应用场景:-当想要构建一些复杂对象时,如生成器。
-当需要创建对象的过程具有多个步骤,并且每个步骤都可以按需选择或省略时。
结构型设计模式6.适配器模式(A da p t e r)适配器模式将一个类的接口转换为客户端所期望的另一个接口。
23种经典设计模式UML类图汇总2009年06月08日星期一上午 11:02创建型模式1、FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了。
麦当劳和肯德基就是生产鸡翅的Factory工厂模式:客户类和工厂类分开。
消费者任何时候需要某种产品,只需向工厂请求即可。
消费者无须修改就可以接纳新产品。
缺点是当产品修改时,工厂类也要做相应的修改。
如:如何创建及如何向客户端提供。
2、BUILDER—MM最爱听的就是“我爱你”这句话了,见到不同地方的MM,要能够用她们的方言跟她说这句话哦,我有一个多种语言翻译机,上面每种语言都有一个按键,见到MM我只要按对应的键,它就能够用相应的语言说出“我爱你”这句话了,国外的MM也可以轻松搞掂,这就是我的“我爱你”builder。
(这一定比美军在伊拉克用的翻译机好卖)建造模式:将产品的内部表象和产品的生成过程分割开来,从而使一个建造过程生成具有不同的内部表象的产品对象。
建造模式使得产品内部表象可以独立的变化,客户不必知道产品内部组成的细节。
建造模式可以强制实行一种分步骤进行的建造过程。
3、FACTORY METHOD—请MM去麦当劳吃汉堡,不同的MM有不同的口味,要每个都记住是一件烦人的事情,我一般采用Factory Method模式,带着MM到服务员那儿,说“要一个汉堡”,具体要什么样的汉堡呢,让MM直接跟服务员说就行了。
工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
4、PROTOTYPE—跟MM用QQ聊天,一定要说些深情的话语了,我搜集了好多肉麻的情话,需要时只要copy出来放到QQ里面就行了,这就是我的情话prototype了。
23种设计模式总结设计模式是一种解决反复出现的设计问题的方案,它们被广泛应用于软件设计和架构中。
在这里,我们列举了23种常用的设计模式,分别属于创建型、结构型和行为型模式。
一、创建型模式1. 工厂方法模式(Factory Method Pattern)定义一个创建对象的接口,但让子类决定实例化哪个类。
工厂方法模式是让类来进行对象的创建,而不是由你的代码直接new 出来。
2. 抽象工厂模式(Abstract Factory Pattern)提供一个接口,用于创建一系列相关或相互依赖的对象。
3. 单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。
4. 建造者模式(Builder Pattern)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
5. 原型模式(Prototype Pattern)用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
二、结构型模式6. 适配器模式(Adapter Pattern)将一个类的接口转换成客户希望的另外一个接口。
适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。
7. 桥接模式(Bridge Pattern)将抽象部分与它的实现部分分离,使它们都可以独立地变化。
8. 组合模式(Composite Pattern)将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
9. 装饰器模式(Decorator Pattern)动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器比生成子类更为灵活。
10. 外观模式(Facade Pattern)为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,使得这一子系统更加容易使用。
11. 享元模式(Flyweight Pattern)运用共享技术有效地支持大量细粒度的对象。
Factory模式1.简单工厂模式,又称静态工厂模式2.工厂方法模式3. 抽象工厂模式抽象工厂模式与工厂方法模式的最大区别在于,工厂方法模式针对的是一个产品等级结构;而抽象工厂模式则需要面对多个产品等级结构。
Builder模式Builder模式利用一个Director对象和ConcreteBuilder对象一个一个地建造出所有的零件,从而建造出完整的Product。
Builder模式将产品的结构和产品的零件建造过程对客户端隐藏起来,把对建造过程进行指挥的责任和具体的建造者零件的责任分割开来,达到责任划分和封装的目的。
使用Builder模式的场合:●需要生成的产品对象有复杂的内部结构。
每一个内部成分本身可以是对象,也可以紧紧是产品对象的一个组成部分。
●需要生成的产品对象的属性相互以来。
Builder模式可以强制实行一种分步骤进行的建造过程,因此,如果产品对象的一个属性必须在另一个属性被赋值之后才可以被赋值,使用建造模式便是一个很好的设计思想。
●在对象创建过程中会使用到系统中的其他一些对象,这些对象在产品对象的创建过程中不易得到。
Prototype模式通过给出一个原型对象来指明所要创建的对象的类型,然后用赋值这个原型对象的办法创建出更多同类型的对象。
CloneableAdapter模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作,也就是说把接口不同而功能相同或相近的多个接口加以转换。
1.类的Adapter模式的结构2.对象的Adapter模式的结构注意两种结构的区别:主要就是Adaptee和Adapter的关系,一个为继承关系,一个为依赖关系。
使用Adapter模式的场合:●系统需要使用现在的类,而此类的接口不符合系统的需要。
●想要建立一个可以重复使用的类,用语与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。
这些源类不一定有很复杂的接口。
23种设计模式UML 类图及对应示例代码1.DoFactory.GangOfFour.Abstract.StructuralAbstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
工厂模式:客户类和工厂类分开。
消费者任何时候需要某种产品,只需向工厂请求即可。
消费者无须修改就可以接纳新产品。
缺点是当产品修改时,工厂类也要做相应的修改。
如:如何创建及如何向客户端提供。
using System;namespace DoFactory.GangOfFour.Abstract.Structural{///<summary>/// MainApp startup class for Structural/// Abstract Factory Design Pattern.///</summary>class MainApp{///<summary>/// Entry point into console application.///</summary>public static void Main(){// Abstract factory #1AbstractFactory factory1 = new ConcreteFactory1(); Client client1 = new Client(factory1);client1.Run();// Abstract factory #2AbstractFactory factory2 = new ConcreteFactory2(); Client client2 = new Client(factory2);client2.Run();// Wait for user inputConsole.Read();}}// "AbstractFactory"abstract class AbstractFactory{public abstract AbstractProductA CreateProductA();public abstract AbstractProductB CreateProductB();}// "ConcreteFactory1"class ConcreteFactory1 : AbstractFactory{public override AbstractProductA CreateProductA(){return new ProductA1();}public override AbstractProductB CreateProductB(){return new ProductB1();}}// "ConcreteFactory2"class ConcreteFactory2 : AbstractFactory{public override AbstractProductA CreateProductA() {return new ProductA2();}public override AbstractProductB CreateProductB() {return new ProductB2();}}// "AbstractProductA"abstract class AbstractProductA{}// "AbstractProductB"abstract class AbstractProductB{public abstract void Interact(AbstractProductA a); }// "ProductA1"class ProductA1 : AbstractProductA{}// "ProductB1"class ProductB1 : AbstractProductB{public override void Interact(AbstractProductA a) {Console.WriteLine(this.GetType().Name +" interacts with " + a.GetType().Name);}}// "ProductA2"class ProductA2 : AbstractProductA{}// "ProductB2"class ProductB2 : AbstractProductB{public override void Interact(AbstractProductA a){Console.WriteLine(this.GetType().Name +" interacts with " + a.GetType().Name);}}// "Client" - the interaction environment of the products class Client{private AbstractProductA AbstractProductA;private AbstractProductB AbstractProductB;// Constructorpublic Client(AbstractFactory factory){AbstractProductB = factory.CreateProductB();AbstractProductA = factory.CreateProductA();}public void Run(){AbstractProductB.Interact(AbstractProductA);}}}2.DoFactory.GangOfFour.Adapter.StructuralAdapter:将一个类的接口转换成客户希望的另一个接口,使得原来由于接口不兼容而不能一起工作的那些类可以一起工作。
软件设计常见的23种设计模式 在现代软件开发当中,设计模式起到⾄关重要的作⽤。
尤其是⾃从⾯向对象的语⾔普遍使⽤以后,促成了团队合作设计的热潮,⽽在此时,没有⼀个好的设计模式,软件设计⼏乎成了不可能完成的任务。
⼀般模式有4个基本要素:模式名称(pattern name)、问题(problem)、解决⽅案(solution)、效果(consequences)。
常见23种模式概述: 1)抽象⼯⼚模式(Abstract Factory):提供⼀个创建⼀系列相关或相互依赖对象的接⼝,⽽⽆需指定它们具体的类。
2)适配器模式(Adapter):将⼀个类的接⼝转换成客户希望的另外⼀个接⼝。
适配器模式使得原本由于接⼝不兼容⽽不能⼀起⼯作的类可以⼀起⼯作。
3)桥梁模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独⽴地变化。
4)建造模式(Builder):将⼀个复杂对象的构建与它的表⽰分离,使同样的构建过程可以创建不同的表⽰。
5)责任链模式(Chain of Responsibility):为解除请求的发送者和接收者之间耦合,⽽使多个对象都有机会处理这个请求。
将这些对象连成⼀条链,并沿着这条链传递该请求,直到有⼀个对象处理它。
6)命令模式(Command):将⼀个请求封装为⼀个对象,从⽽可⽤不同的请求对客户进⾏参数化;对请求排队或记录请求⽇志,以及⽀持可取消的操作。
7)合成模式(Composite):将对象组合成树形结构以表⽰“部分-整体”的层次结构。
它使得客户对单个对象和复合对象的使⽤具有⼀致性。
8)装饰模式(Decorator):动态地给⼀个对象添加⼀些额外的职责。
就扩展功能⽽⾔,它能⽣成⼦类的⽅式更为灵活。
9)门⾯模式(Facade):为⼦系统中的⼀组接⼝提供⼀个⼀致的界⾯,门⾯模式定义了⼀个⾼层接⼝,这个接⼝使得这⼀⼦系统更加容易使⽤。
10)⼯⼚⽅法(Factory Method):定义⼀个⽤于创建对象的接⼝,让⼦类决定将哪⼀个类实例化。
谈到设计模式,绝对应该一起来说说重构。
重构给我们带来了什么?除了作为对遗留代码的改进的方法,另一大意义在于,可以让我们在写程序的时候可以不需事先考虑太多的代码组织问题,当然这其中也包括了应用模式的问题。
尽管大多数开发者都已经养成了写代码前先从设计开始的习惯,但是,这种程度的设计,涉及到到大局、到总体架构、到主要的模块划分我觉得就够了。
换句话说,这时就能写代码了。
这就得益于重构的思想了。
如果没有重构的思想,有希望获得非常高质量的代码,我们就不得不在开始写代码前考虑更多其实并非非常稳定的代码组织及设计模式的应用问题,那开发效率当然就大打折扣了。
在重构和设计模式的合理应用之下,我们可以相对较早的开始写代码,并在功能尽早实现的同时,不断地通过重构和模式来改善我们的代码质量。
所以,下面的章节中,在谈模式的同时,我也会谈谈关于常用的这些模式的重构成本的理解。
重构成本越高意味着,在遇到类似的问题情形的时候,我们更应该提前考虑应用对应的设计模式,而重构成本比较低则说明,类似的情形下,完全可以先怎么方便,怎么快怎么写,哪怕代码不是很优雅也没关系,回头再重构也很容易。
1 创建型1.1 FactoryMethod思想:Factory Method的主要思想是使一个类的实例化延迟到其子类。
场景:典型的应用场景如:在某个系统开发的较早阶段,有某些类的实例化过程,实例化方式可能还不是很确定,或者实际实例化的对象(可能是需要对象的某个子类中的一个)不确定,或者比较容易变化。
此时,如果直接将实例化过程写在某个函数中,那么一般就是if-else或select-case代码。
如果,候选项的数目较少、类型基本确定,那么这样的if-else还是可以接受的,一旦情形变得复杂、不确定性增加,更甚至包含这个构造过程的函数所在的类包含几个甚至更多类似的函数时,这样的if-else代码就会变得比较不那么容易维护了。
此时,应用本模式,可以将这种复杂情形隔离开,即将这类不确定的对象的实例化过程延迟到子类。
实现:该模式的典型实现方法就是将调用类定义为一个虚类,在调用类定义一个专门用于构造不确定的对象实例的虚函数,再将实际的对象实例化代码留到调用类的子类来实现。
如果,被构造的对象比较复杂的话,同时可以将这个对象定义为可以继承、甚至虚类,再在不同的调用类的子类中按需返回被构造类的子类。
重构成本:低。
该模式的重构成本实际上还与调用类自己的实例化方式相关。
如果调用类是通过Factory方式(此处“Factory方式”泛指对象的实例化通过Factory Method或Abstract Factory这样的相对独立出来的方式构造)构造的,那么,重构成本相对就会更低。
否则,重构时可能除了增加调用类的子类,还要将所有实例化调用类的地方,修改为以新增的子类代替。
可能这样的子类还不止一个,那就可以考虑迭代应用模式来改善调用类的实例化代码。
1.2 AbstractFactory思想:不直接通过对象的具体实现类,而是通过使用专门的类来负责一组相关联的对象的创建。
场景:最典型的应用场景是:您只想暴露对象的接口而不想暴露具体的实现类,但是又想提供实例化对象的接口给用户;或者,您希望所有的对象能够集中在一个或一组类(通常称作工厂类)来创建,从而可以更方便的对对象的实例化过程进行动态配置(此时只需要修改工厂类的代码或配置)。
实现:该模式的实现是比较清晰简单的,如上图,就是定义创建和返回各种类对象实例的工厂类。
在最复杂而灵活的情形,无论工厂类本身还是被创建的对象类都可能需要有一个继承体系。
简单情形其实可以只是一个工厂类和需要被创建的对象类。
不一定非要像上图中结构那么完备(累赘)。
重构成本:中。
如果一开始所有的对象都是直接创建,例如通过new实例化的,而之后想重构为Abstract Factory模式,那么,很自然的我们需要替换所有直接的new实例化代码为对工厂类对象创建方法的调用。
考虑到像Resharper这样的重构工具的支持,找出对某个方法或构造函数的调用位置这样的操作相对还是比较容易,重构成本也不是非常高。
同时,重构成本还和被创建对象的构造函数的重载数量相关。
您需要根据实际情况考虑,是否工厂类要映射被创建对象的所有重载版本的构造函数。
1.3Builder思想:将一个类的创建过程和他的主体部分分离。
场景:该模式的典型的应用场景是:一个类的创建过程可能比较复杂,或者创建过程中的某些阶段可能会容易变化;或者多个类的创建过程比较类似,但是主体不同。
实现:在以上提到的两种场景中,我们就可以取出一个类的创建过程的代码,定义一个专门的Builder类,而在原来创建类对象实例的地方,将这个Builder类的实例作为参数传入。
还有第二个重点,就是Builder类可以将将整个创建过程分为几个阶段,每个阶段不必在类中直接实现,而可以通过继承体系在子类中实现,或者通过子类的方法过载来修改创建过程中的某个阶段,但是重用其他的阶段。
可以发现,该模式将一个对象的复杂创建过程重用到非常高的层次。
这正是它的意义所在。
重构成本:低。
该模式的重构成本我觉得是非常低的,因为一般来讲,创建过程的代码本来也就应该在原来的类的构造函数中,把它Extract出来就好了。
如果发现多个类的创建过程有比较多的代码重复或类似,那么就可以重用这些提取出来的Builder类或者Builder类中的某些阶段。
1.4Prototype思想:克隆一个已有的类的实例(大家相比都用过甚至写过类的Clone实现,应该很容易理解了)。
场景:应用Clone的场景应该说非常多,理想情况下我当然希望任何类都能Clone,需要的时候就能Clone一份一模一样的出来。
实现:这里将的实现主要之实现的表现形式,而不是如何用具体的语言来实现。
因此,只要为需要Clone能力的类定义一个Clone方法就行。
当然,一般,主流的程序语言框架都已经定义了通用的Clone接口(当然也可以自己定义),继承并实现该接口和方法就好。
重构成本:极低。
不多解释了吧。
1.5 Singleton思想:保证一个类只有一个唯一的实例。
场景:生活中有些对象就是只要一个就好了,我们的代码中为什么要每次都为这样的对象生成一个实例呢?实现:最简单的实现方式就是使用一个static型的类实例,每次对该对象的创建请求都返回这个static的唯一实例就行。
重构成本:极低。
2 结构型Adapter思想:将一个类的接口转换成另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
场景:该模式的应用场景太多了,很多需要的功能模块的接口和我们需要的不完全一致或者有多余或不足,但是需要和我们的系统协同工作,通过Adapter把它包装一下就能让使它接口兼容了。
实现:定义一个Adapter类,包含需要包装的类,实现需要的其它接口,调用被包装的类的方法来实现需要的接口。
重构成本:低。
Bridge思想:将一个类的抽象定义和具体实现解耦。
场景:该模式的典型应用场景是:一个类的抽象定义已经确定,但是,其实现代码甚至原理可能会不同。
比如:我们最熟悉的图形界面中的window的实现,无论在什么操作系统,什么平台的机器上,一个window应具有的抽象定义基本上是一致的,但是,其实现代码肯定会因为平台不同,机器的代码指令不同而不同。
此时,如果希望您写的window类能跨平台,应用Bridge 模式就是一个好主意。
实现:该模式的实现方法很简单,就是除了定义类的抽象定义之外,将一个类的所有实现代码独立出一个实现类。
这样一来,无论是抽象定义还是实现类都能分别修改和重用,但只要两部分的交互接口不变,还是可以方便的互相组装。
当然,实际上也没有必要隔离出“所有实现代码”,只需要隔离需要的部分就行了。
因此,也可以说,从代码结构来看,Builder模式是一种变种的Bridge模式的。
也经常有人将Bridge模式和接口相比较,如果隔离出所有的实现,那么的确接口的方式也能做到抽象定义和实现分离,但是,Bridge有其优势如下:一、究竟隔离多少代码到Bridge类中可以灵活确定,二、减少了总的类的数目,三、允许被隔离出来的Bridge类被其它的类直接共享使用。
重构成本:中。
将所有的(或很大部分)实现代码分离开来总还是一件不大,但是,也不小的事。
所以标个“中”在这里。
:)Composite思想:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
场景:该模式的应用场景极其类似,比如像图形系统,如电路设计、UML建模系统,或者像web 的显示元素等,都是那种需要整体和部分具有使用接口上的一定的一致性的需求的结构,实际上,我觉得这样的系统如果不使用Composite模式将会是惨不忍睹的。
实现:该模式的实现主要就是要表示整体或部分的所有类都继承自同一的基类或接口,从而拥有使用接口上一定的一致性。
重构成本:高。
2.4Decorator思想:为一个对象已有的子类添加一些额外的职责。
场景:该模式的使用场景,主要是有的时候我们不愿意定义逻辑上新的子类,因为没有新的逻辑含义上的子类概念,而只是想为一个已存在的子类附加一些职责。
实现:该模式的实现主要就是定义一个物理上的新的子类,但是,它只是包含要附加职责的类,传递外部对相同接口的调用,在这个传递调用的通道上附加额外的功能。
突然想到,Decorator 模式是不是一定程度上也能代替DynamicProxy模式,从而成为一种AOP实现的方案呢?重构成本:低。
定义一个Decorator和一个已有类的逻辑上的子类,物理表现形式上都是一个子类,重构也确实不是难事。
2.5Facade思想:为子系统中的一组接口提供一个一致的界面,这个接口使得这一子系统更加容易使用。
场景:当你要为一个复杂子系统提供一个简单接口时。
子系统往往因为不断演化而变得越来越复杂。
大多数模式使用时都会产生更多更小的类。
这使得子系统更具可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。
Facade可以提供一个简单的缺省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过Facade层。
客户程序与抽象类的实现部分之间存在着很大的依赖性。
引入Facade 将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
当你需要构建一个层次结构的子系统时,使用Facade模式定义子系统中每层的入口点。
如果子系统之间是相互依赖的,你可以让它们仅通过Facade进行通讯,从而简化了它们之间的依赖关系。
(这里直接引用了《设计模式迷你手册》,因为觉得它确实已经说得很明了了,下面类似的情形我直接引用原文的就不再注明了,这里先说明一下,感谢《手册》作者的这些优秀总结。