首页 > 代码库 > 《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式

《Head First 设计模式》学习笔记——观察者模式 + 装饰者模式

装饰者模式是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 = http://www.mamicode.com/new WeatherData();>


装饰者模式:
//抽象类
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());
	}
}