装饰者模式是JDK中另一个使用较多的设计模式,上一个是观察者模式(在Swing中大量使用),业内好的API设计无一离不开常见的设计模式,通常我们所说要阅读源码,也是为了学习大牛们的设计思路。————题记
设计模式
观察者模式:定义了对象之间一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会受到通知并自动更新。
装饰者模式:动态地将责任附加到对象上。若要扩展功能,装饰者提供比继承者更有弹性的替代方案。
设计原则
(1)封装变化。
(2)多用组合,少用继承。
(3)针对接口编程,而不是针对实现编程。
(4)为了交互对象之间的松耦合设计努力。
对象之间的像话依赖降到了最低,有助于简历有弹性的OO系统,能够应对变化。
(5)类应该对扩展开发,对修改关闭。
目标是允许类容易扩展,在不修改现有代码的情况下,就可以搭配出新的行为。
要点
观察者模式定义了对象之间一对多的关系。
使用观察者模式时,可以从被观察者出推或拉数据。
观察者模式中,会改变的是主题的状态,以及观察者的数量和类型。用这个模式,你可以改变依赖于主题状态的对象,却不必改变主题。
继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式。
组合和委托可用于运行时动态加上新的行为。
装饰者可以在被装饰者的行为前面与或后面加上自己的行为,甚至取代,达到特有的目的。
装饰者会导致设计中出现许多小对象,如果过度使用,会让小程序变得复杂。
Java内置的观察者模式:Obverser接口与Obversable类。
缺点:
(1)Obversable是一个类,必须设计一个类继承他。如果想同时具有Obversable类和另一个超类的行为,就会陷入两难,因为Java不支持多重继承。Obversable没有接口,无法建立自己的实现。
(2)Obversable将setChange()方法保护起来了。这样一来,除非继承,否则无法创建Obversable实例并组合到自己的对象中来。
真实世界的装饰者
java.io包内的类太多了,简直是排山倒海。下面是一个典型的对象集合,用装饰者来将功能结合起来,以读取文件数据:
超类:InputStream
组件:FileInputStream、StringBufferInputStream、ByteArrayInputStream
抽象装饰者:FilterInputStream
具体装饰者:PushBackInputStream、BufferedInputStream、DataInputStream、LineNumberInputStream
观察者模式:
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update(float temp, float humidity, float pressure);
}
public interface DispalyElement {
public void dispaly();
}
public class WeatherData implements Subject {
private ArrayList observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
//通知每一个观察者
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
//测试代码
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay =
new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80,65,30.4f);
}
}
装饰者模式:
//抽象类
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
//CondimentDecorator必须能取代Beverage,所以将CondimentDecorator必须能取代Beverage,所以将扩展成Beverage类扩展成Beverage类
public abstract class CondimentDecorator extends Beverage {
//所有调料装饰者必须重新实现getDescription()方法
public abstract String getDescription();
}
//饮料代码扩展自Beverage
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
//装饰者
public class Soy extends CondimentDecorator {
Beverage beverage;//记录被装饰者
public Soy(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + ", Soy";
}
public double cost() {
return .15 + beverage.cost();
}
}
//测试代码
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso();
System.out.println(beverage.getDescription()
+ " $" + beverage.cost());
Beverage beverage2 = new DarkRoast();
beverage2 = new Mocha(beverage2);//层层装饰
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
System.out.println(beverage2.getDescription()
+ " $" + beverage2.cost());
Beverage beverage3 = new HouseBlend();
beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
System.out.println(beverage3.getDescription()
+ " $" + beverage3.cost());
}
}