观察者模式(Observer)
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
设计原则
- 为了交互对象之间的松耦合设计而努力
实例
自己实现
WeatherData的布告板
- WeatherData主题
public class WeatherData implements Subject {
/**
* WeatherData实现了Subject接口
* registerObserver、removeObserver和notifyObservers
* ArrayList记录观察者
*/
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);
}
}
/**
* 观察者实现update
*/
public void notifyObservers() {
for(int i = 0; i < observers.size(); i++) {
Observer observer = (Observer)observer.get(i);
observer.update(temperature, humidity, pressure);
}
}
/**
* 气象站更新->观察者更新
*/
public void measurementsChanged() {
notifyObsservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
//WeatherData的其他方法
}
- 布告板
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
使用Java内置类
- Observable
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
/**
* 不需要再建立队列了
*/
public WeatherData() {}
public void measurementsChanged() {
setChanged();
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;
}
}
- Observable
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionsDisplay implements Observer, DisplayElement {
Observer observer;
private float temperature;
private float humidity;
public CurrentConditionsDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
public void update(Observable obs, Object arg) {
if(obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
public void display() {
System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
}
}
装饰者模式
继承 vs 扩展
- 利用继承设计子类的行为,是在编译时静态决定的
- 利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展 动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
设计原则
- 类应该对扩展开放,对修改关闭
装饰者模式的特点
- 装饰者和被装饰对象有相同的超类型
- 可以用一个或多个装饰者包装一个对象
- 既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它
- 装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的
- 对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象。
实例
Beverage类
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return description;
}
public abstract double cost();
}
Condiment类 也是抽象类
public abstract class CondimentDecorator extends Beverage {
public abstract String getDescription();
}
- 饮料类 意式浓缩:
public class Espresso extends Beverage {
public Espresso() {
description = "Espresso";
}
public double cost() {
return 1.99;
}
}
每日咖啡
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend Coffee";
}
public double cost() {
return .89;
}
}
摩卡
public class Mocha extends CondimentDecorator {
Beverage beverage;
public Mocha(Beverage beverage) {
this.beverage = beverage;
}
public String getDescription() {
return beverage.getDescription() + "Mocha";
}
public double cost() {
return .20 + 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());
}
}
装饰者模式——java内置I/O
public class LowerCaseInputStream extends FilterInputStream {
public LowerCaseInputStream(InputStream in) {
super(in);
}
public int read() throws IOException {
int c = super.read();
return (c == -1 ? c : Character.toLowerCase((char)c));
}
public int read(byte[] b, int offset, int len) throws IOException {
int result = super.read(b, offset, len);
for(int i = offset; i < offset + result; i++) {
b[i] = (byte)Character.toLowerCase((char)b[i]);
}
return result;
}
}