设计模式
并非所有开发语言都支持所有设计模式,有的开发语言只支持个别设计模式。
创建型模式(Creational)
关注对象的实例化过程,包括了如何实例化对象、隐藏对象的创建细节等。
单例模式(Singleton Pattern)
确保一个类只有一个实例,并提供该实例的全局访问点。
数据库类设计,只连接一次数据库,防止打开多个数据库连接
使用一个私有构造函数、一个私有静态变量以及一个公有静态函数来实现。
私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
简单工厂
在创建一个对象时不向客户暴露内部细节,并提供一个创建对象的通用接口。
简单工厂又叫静态工厂方法模式,简单工厂模式是通过一个静态方法创建对象的。
违反开闭原则(对于扩展是开放的,对于修改是关闭的)
新增时需要改动原有类文件,在里面新增方法或判断。
调用时用同一个对象,但用的方法不一样,或传进去的参数不一样。如:
1 2 3 4 5 6 7 8 9 10 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
简单工厂: 调用时
SimpleFactoty
一样,createMan
方法不一样 工厂方法: 调用时SimpleFactoty
不一样,createMan
方法一样
工厂方法
定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。
遵循开闭原则。
新增方法不用改原有类文件,新增文件后继承上游类或接口即可调用。
调用时,对象不一样,但调用方法和返回类型皆为一致。
如:
1 2 3 4 5 |
|
使用场景:
- 日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
- 数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
- 设计一个连接服务器的框架,需要三个协议,”POP3”、”IMAP”、”HTTP”,可以把这三个作为产品类,共同实现一个接口。
在工厂方法中,由子类来创建对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
|
与简单工厂不同的是前面的
FactoryMan
对象是变化的,create
方法是固定的。
抽象工厂
提供一个接口,用于创建 相关的对象家族 。
抽象工厂模式是工厂模式的一个扩展,如果抽象工厂只有一个产品体系就会退化成工厂模式。属于简单工厂和工厂模式的合体。
违反开闭原则
新增时 可能 需要改动原有类文件,在里面新增方法或判断。同样要继承上游类或接口。
调用时,对象和调用方法都可不一样。
如:
1 2 3 4 5 6 |
|
体现出了面向接口编程的思想,其实就是用工厂方法生产具有多维度变化的产品类。
缺点:产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 工厂里加代码,又要在具体的实现加代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
|
生成器
封装一个对象的构造过程,并允许按步骤构造。
原型模式
使用原型实例指定要创建对象的类型,通过复制这个原型来创建新对象。
行为型
责任链
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链发送该请求,直到有一个对象处理它为止。
命令
将命令封装成对象中,具有以下作用:
- 使用命令来参数化其它对象
- 将命令放入队列中进行排队
- 将命令的操作记录到日志中
- 支持可撤销的操作
解释器
为语言创建解释器,通常由语言的语法和语法分析来定义。
迭代器
提供一种顺序访问聚合对象元素的方法,并且不暴露聚合对象的内部表示。
中介者
集中相关对象之间复杂的沟通和控制方式。
备忘录
在不违反封装的情况下获得对象的内部状态,从而在需要时可以将对象恢复到最初状态。
观察者
定义对象之间的一对多依赖,当一个对象状态改变时,它的所有依赖都会收到通知并且自动更新状态。
主题(Subject)是被观察的对象,而其所有依赖者(Observer)称为观察者。
状态
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它所属的类。
策略
定义一系列算法,封装每个算法,并使它们可以互换。
策略模式可以让算法独立于使用它的客户端。
模板方法
定义算法框架,并将一些步骤的实现延迟到子类。
通过模板方法,子类可以重新定义算法的某些步骤,而不用改变算法的结构。
访问者
为一个对象结构(比如组合结构)增加新能力。
空对象
使用什么都不做
的空对象来代替 NULL。
一个方法返回 NULL,意味着方法的调用端需要去检查返回值是否是 NULL,这么做会导致非常多的冗余的检查代码。并且如果某一个调用端忘记了做这个检查返回值,而直接使用返回的对象,那么就有可能抛出空指针异常。
结构型
适配器
把一个类接口转换成另一个用户需要的接口。
桥接
将抽象与实现分离开来,使它们可以独立变化。
组合
将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独对象和组合对象。
装饰
为对象动态添加功能。
外观
提供了一个统一的接口,用来访问子系统中的一群接口,从而让子系统更容易使用。
享元
利用共享的方式来支持大量细粒度的对象,这些对象一部分内部状态是相同的。
代理
控制对其它对象的访问。