1. 设计原则
封装变化
针对接口编程,不要针对实现编程
多用组合,少用继承
为了交互对象之间的松耦合设计而努力
类应该对扩展开放,对修改关闭
要依赖抽象,不要依赖具体类 - 依赖倒置原则(Dependency Inversion Principle)
只和朋友交谈
别找我,我会找你
类只有一个改变的理由
2. 策略模式(Strategy)
定义了算法族,分别封装起来,让它们之间可以相互替换,让算法的变化独立于使用算法的客户 - 鸭子模拟器
3. 观察者模式(Observer)
定义了对象之间的一对多依赖,当一个对象状态改变时,所有的依赖者都会收到通知并自动更新 - 气象观测站
观察者模式(Observer) = 出版者(Subject) + 订阅者(Observer)
Java内置了观察者模式,java.util.Observer(同Observer)和java.util.Observable(同Subject)。
3.1 如何定义观察者对象
实现java.util.Observer接口,调用Observable.addObserver()添加观察者,调用Observable.deleteObserver
()删除观察者
3.2 如何发通知
应用扩展Observable接口,然后调用setChanged()方法标记状态改变,接着调用两种notifyObservers()或
notifyObservers(Object arg)中一个
3.3 观察者如何接受通知
观察者的update(Observable o, Object arg)方法
如果推(push)数据给观察者,那么调用notifyObservers(Object arg)方法
如果观察者主动拉(pull),那么主题类中,先调用setChanged(),然后调用notifyObservers(),同时把所有参数给
出getXXX方法,以便观察者获取
//主题接口 - 对象使用此接口注册,删除,通知
interface Subject {
registerObserver()
removeObserver()
motifyObservers()
}
//观察者接口 - 只有一个update()方法,主题状态改变时被调用
interface Observer {
update()
}
//具体主题 - 实现注册,删除,通知,同时能获取和设置状态
ConcreteSubject implements Subject {
registerObserver() {...}
removeObserver(){...}
motifyObservers(){...}
getState()
setState()
}
//具体观察者 - 必须注册具体主题
ConcreteObserver implements Observer {
update()
}
4. 装饰器模式(Decorator)
动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案 - 星巴兹咖啡
Java I/O是典型的装饰器模式
//Component - 抽象组件
Component {
methodA()
methodB()
}
//ConcreteComponent - 具体组件
ConcreteComponent extends Component {
methodA()
methodB()
}
//Decorator - 装饰者共同接口
Decorator extends Component {
methodA()
methodB()
}
//ConcreteDecoratorA
ConcreteDecoratorA extends Decorator {
Component wrappedObj //可以记录装饰的对象
methodA()
methodB()
newBehavior()
}
//ConcreteDecoratorB
ConcreteDecoratorB extends Decorator {
Component wrappedObj //可以记录装饰的对象
Object newState //装饰者可以扩展Component状态
methodA()
methodB()
}
5. 工厂方法模式(Facotory Methods)
定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类 - 比萨店
简单工厂(Simple Factory): 一个工厂类,一个抽象产品类,一系列具体产品类
工厂方法(Factory Method): 一个抽象工厂类,一系列具体工厂类,一个抽象产品类,一系列具体产品类
抽象工厂(Simple Factory): 提供一个接口,用于创建相关或依赖对象的家族,而不需要指明具体类。注意,是创建
一个家族,说明里面产品很多啊
抽象工厂的每个方法看起来都像工厂方法,所以抽象工厂定义一组创建产品的接口,由工厂方法来实现
6. 单例模式(Singleton)
确保一个类只有一个实例,并提供全局访问点 - 巧克力工厂
7. 命令模式(Command)
将"请求"封装成对象,以便使用不同的请求、队列或者日志来参数化其他对象,同时支持撤销操作 - 神奇遥控器
Client: 客户端需要创建一个ConcreteCommand,同时设置Receiver
Invoker: 调用者持有命令对象,执行execute()方法
Command: 接口
ConcreteCommand: 具体执行者,会调用Receiver方法
Receiver: 进行必要的工作
能够进行Undo操作,在具体命令中记录先前状态,然后添加相应方法,重新设置到原来的状态
宏命令: 就是把一堆具体命令,放在一个方法中执行
还可以把命令模式用于队列请求,一个线程从队列中取出任务,然后执行execute()
日志请求: 每个命令执行时,可以存储状态到磁盘,如果Down之后,可以恢复
8. 适配器模式(Adapter)
将一个类的接口,转换成客户期望的另一个接口,让原本接口不兼容的类可以合作无间 - 鸭子和火鸡
适配器只是转换不同的接口,而装饰器可能会加入新的方法
9. 外观模式(Facade)
提供一个统一的接口,来访问子系统中的一群接口 - 家庭影院
比如要执行一系列操作,那么使用外观模式,把所有操作封装起来,给客户端一个方法调用即可
10. 模板方法(Template)
在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中 - 咖啡和茶的制作方法
可以自己实现一部分方法,另外一些方法在子类实现,那么就在父类定义抽象方法,让子类执行
//抽象类
abstract class AbstractClass {
//声明为final,以免子类改变该算法
final void templateMethdo() {
primitiveOperation1();
primitiveOperation2();
concreteOperation();
hook();
}
//定义两个原语操作,由子类实现
abstract void primitiveOperation1();
abstract void primitiveOperation2();
void concreteOperation() {
}
void hook() {} //子类来决定需不需要做事
}
11. 好莱坞原则
抽象组件决定什么时候使用低层组件,而不让低层组件依赖抽象组件
策略和模板都封装算法,策略用组合,而模板使用继承
12. 迭代器(Iterator)
提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部的表示。
13. 组合(Composite)
允许你将对象组合成树形结构来表现"整体/部分"层次结构。组合能让客户以一致的方式处理个别对象和对象组合。
对象村多种类型菜单
14. 状态模式(State)
允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类 - 万能糖果销售机
15. 代理模式(Proxy)
为另一个对象提供一个替身或占位符以控制对这个对象的访问
远程代理: 可以作为一个JVM对象的本地代表,调用代理方法,可以执行远程对象方法。譬如远端监控万能糖果机
虚拟代理: 创建开销大的对象代表。譬如CD浏览器,启用另外一个线程,从网络上下载CD封面
动态代理: java.lang.reflect,运行时动态创建代理类,实现一个多个接口,将方法的调用转发到你指定的类
保护代理: 让有权限的用户进行访问
16. 复合模式(Compound)
结合两个或以上的模式,组成一个解决方案,解决已在发生的一般性问题。
MVC结合了观察者模式,策略模式,组合模式