观察者模式
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会通知并自动更新。
观察者模式是比较好理解的也好运用的一种设计模式,分为发布者和订阅者,订阅者可以自由的订阅或者取消而无需改动发布者。
Java 类库案例
Java 提供了观察者模式的现成类库: java.util.Observable,java.util.Observer。有几个地方需要思考:
- 底层观察者列表的存储使用了 Vector,所有的操作都是同步的。
- 观察者通知是同步的,没有加异常处理措施,一个订阅者异常会影响到其他订阅者。
为了缩短通知时的加锁时间,将通知列表暂存到一个数组中。因此会有刚加入订阅者列表没有通知以及刚取消订阅的仍然收到通知。
public void notifyObservers(Object arg) { /* * a temporary array buffer, used as a snapshot of the state of * current Observers. */ Object[] arrLocal; synchronized (this) { /* We don't want the Observer doing callbacks into * arbitrary code while holding its own Monitor. * The code where we extract each Observable from * the Vector and store the state of the Observer * needs synchronization, but notifying observers * does not (should not). The worst result of any * potential race-condition here is that: * 1) a newly-added Observer will miss a * notification in progress * 2) a recently unregistered Observer will be * wrongly notified when it doesn't care */ if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); }
装饰者模式
装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
装饰者模式是将具有本质区别的一些东西与可以装饰这些东西的特性分开,从而简化的设计的复杂性。例如水果店卖西瓜、香蕉、芒果,但是每种水果又细分为:洗净的、切块的、进口的、冰镇的等等。如果采用继承的方式,需要定义洗净的西瓜、洗净的芒果、切块的西瓜、切块的芒果、洗净的切块的西瓜、洗净的切块的芒果等等。需要继承的类有 (m*2^n) 个。但是采用装饰者模式只需要定义 (m+n) 个类,大大减少工作量。
类图
Java 类库案例
由于装饰者需要能替代被装饰者,因此装饰者继承自被装饰者。
工厂模式
工厂模式作用
- 使用工厂模式,对于使用者只需要依赖工厂生产的产品的接口和工厂,无需依赖具体的产品。
- 工厂的实现可以随时修改而不影响到具体的使用者。
- 工厂对所有具体产品集中管理。
工厂模式分类
- 简单工厂:简单工厂不是一个设计模式,但是却很有用。在一个方法中通过条件判断等手段来动态返回不同的产品实现。解耦了使用者和具体的产品,但是违背了对扩展开放,对修改关闭的原则。
- 工厂模式:通常有一个父类定义抽象工厂方法,然后又具体的工厂子类决定如何创建产品,可以方便的扩展工厂和产品。遵循了扩展开放,修改关闭的原则。
- 抽象工厂模式:抽象工厂和工厂模式不同在于,抽象工厂生产的是一类相互关联或依赖的产品,而工厂模式只生产一种产品。他们的联系在于,抽象工厂的子类在实现每类产品时,通常是用工厂模式来实现的。