设计模式是一种“小框架”,即体系结构。尝试使用简短的语言描述23种设计模式。
重要原则:
- 针对接口编程,而不是针对实现编程。
- 继承产生了依赖,破坏了封装性。
- 优先使用对象组合,而不是类继承。(组合往往难以实现,但是易于维护,拥抱了变化)
- 类继承是白箱复用,对象的组合是黑箱复用。
- 灵活性和可变性是简单性和高性能的敌人。
- 不修改源码的原则。
模式介绍:
注意:以下的“用户”指的是使用对象的程序员,并非最终使用应用的用户。
创建型模式(通常从工厂办法开始,后面重构):
- 抽象工厂(abstract factory):
用户不直接创建一个产品对象,而是通过一个工厂对象间接创建。(用户与实际实现分离) - 生成器(builder):
通过生成器一步步生成一个复杂产品对象。(生成器中维护一个产品对象,一直对产品进行升级,最后返回) - 工厂办法(factory method):
用户通过工厂办法实例化产品对象。(抽象工厂也是使用工厂办法实例产品对象的) - 原型(prototype):
每个对象都实现了clone方法,调用对象的clone就可以深拷贝出新的对象,同时可以通过参数自定义 - 单例(singleon):
一个类只有一个对象,并通过类方法获取到对象,实现对数据状态的共享。(全局变量)
结构型模式:
- 适配器(adapter):
已经有了两种接口的类,但是用户希望使用同一个的方式使用,在不改类源码的基础上对一个者类进行包装,让它表现出另一种类的接口,这个包装类就是适配器。(可以类比不同国家的插座,用户是用电器) - 桥接(bridge):
将若干类聚合在一个桥接类中,小类可以单独发展,不影响桥接类。(多继承改成聚合,和适配器模式是在生命的不同周期的不同叫法) - 组合(composite):
使用递归的方式实现树形结构,在一个对象中包含相同类实例的对象 - 装饰(decorator):
在不影响原本类的基础上,对一个实例对象动态增加功能。(将对象传给装饰类(和原类有同样的接口),并实例出新的对象) - 外观(facade):
基金是股票的外观,通过高级接口封装子系统。 - 享元(flyweight):
为了防止对象过多,可以共享细粒度的对象(类似String常量池) - 代理(proxy):
代理一个对象的访问,类似于适配器模式,不过代理是主动设计,适配器是事后补救。(保护对象,解耦)
行为型模式:
- 职责链(chain of responsibility):
每个对象中有下一个级别的对象,当用户的一个调用目前的对象无法满足的时候会调用下一个对象,形成了一条一直测试能否执行的链,直到被解决或者到了最后一个。(用户的调用不能保证处理,有关部门的感觉) - 命令(command):
用户的请求是一个命令对象,将命令提交给处理的对象,然后对命令进行队列处理,类似事务(增加,删除)。(餐厅:一般的请求类似于喊一句老板给我来碗面,而命令模式类似于给老板一张勾选好的菜单) - 解释器(interpreter):
定义一个翻译器,将用户的请求翻译成明确的行为 - 迭代器(iterator):
一个对象内部聚合了多个对象,使用暴露出来的方法顺序访问内部对象(多种遍历方式)。类似于一个next()方法。(游标的感觉) - 中介者(mediator):
转发者,各个对象不必相互引用,只需要引用相同的中介者,由中介者转发操作。(降低了耦合) - 备忘录(memento):
将对象中的状态属性复制成一个备忘录对象,并交给负责人对象保存,如果需要恢复就从负责人那里获取(类似于悔棋,撤回等操作,相比直接存储整个对象,使用备忘录存比较经济) - 观察者(observer):
订阅或者依赖关系,当发布者发布了新的内容,订阅者都响应操作。实现:发布者维护一个订阅者列表,当发布者发布涉及订阅者的内容时,使用订阅者引用调用响应的方法。 - 状态(state):
为对象设置不同的状态,当用户调用相同的方法时,表现出来的效果依赖当前对象的状态。(类似于王者荣耀中的移动,当不同状态下:受控,疾跑等,移动速度不同) - 策略(strategy):
将算法封装成对象使用,使得算法可以发展可以更换 - 模板办法(template method):
父类只是骨架,子类继承实现不同的行为 - 访问者(visitor):
对象写一个固定方法(参数为访问者),并调用访问者(对象作为参数)。这样,在访问者中就可以访问原对象中的方法了。如果需求有变化,只需要修改访问者即可。