设计模式(六)命令模式 & 观察者模式
命令模式
应用场景
使用多功能的遥控器打开一个电灯
public interface Command {
    public void execute();
}
public class LightOnCommand implements Command {
    Light light;
    public LigitOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
}
public class SimpleRemoteControl {
    Command slot;
    public SimpleRemoteControl() { }
    public void setCommand(Command command) {
        slot = command;
    }
    public void buttonWasPressed() {
        slot.execute();
    }
}
public class RemoteControlTest {
    public static void main(String[] args) {
        SimpleRemoteControl remote = new SimpleRemoteControl();
        Light light = new Light();
        LightOnCommand lightOn = new LightOnCommand(light);
        remote.setCommand(lightOn);
        remote.buttonWasPressed();
    }
}遥控器是调用者,电灯是接收者。创建一个命令并将接收者传给命令,然后将命令传给调用者。这样,将发出请求的对象和执行请求的对象解耦,通过命令对象沟通。
一个命令对象通过在特定接收者上绑定一组动作来封装一个请求,其它对象不知道究竟哪个接收者进行了哪些动作,只知道调用execute方法,请求的目的就能达到。
总结
命令模式将“请求”封装成对象,以便使用不同的请求、队列或者日志来参数化其它对象,命令模式也支持可撤销的操作。
观察者模式
应用场景
气象站将数据传输到显示装置上显示
方案一
错误的示范
public class WeatherData1 {
    public void measurementsChanged() {
        float temp = getTemperature();
        float pressure = getPressure();
        displayer1.update(temp, pressure);
        displayer2.update(temp, pressure);
    }
}这样就耦合了具体的对象displayer1和displayer2了
方案二
应用观察者
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 pressure);
}
public interface DisplayElement {
    public void display();
}
public class WeatherData2 implements Subject {
    private ArrayList observers;
    private float temperature;
    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, pressure);
        }
    }
    public void measurementsChanged() {
        notifyObservers();
    }
    public void setMeasurements(float temperature, float pressure) {
        this.temperature = temperature;
        this.pressure = pressure;
        measurementsChanged();
    }
}
public class Displayer1 implements Observer, DisplayElement {
    private float temperature;
    private Subject weatherData;
    public Displayer1(Subject weatherData) {
        this.weatherData = weatherData;
        weatherData.registerObserver(this);
    }
    public void update(float temperature, float pressure) {
        this.temperature = temperature;
        display();
    }
    public void display() {
        //... 显示的实现
    }
}方案三
还可以利用系统内置观察方式实现
import java.util.Observable;
import java.util.Observer;
public class WeatherData3 implements Observable {
    private float temperature;
    private float pressure;
    public WeatherData() { } //不再需要记住观察者的数据结构
    public void measurementsChanged() {
        setChanged(); //通知观察者前先标记状态改变了(系统API)
        notifyObservers(); //通知观察者(系统API)
    }
    public void setMeasurements(float temperature, float pressure) {
        this.temperature = temperature;
        this.pressure = pressure;
        measurementsChanged();
    }
}
public class Displayer2 implements Observer, DisplayElement {
    private float temperature;
    Observable observable;
    public Displayer1(Observable observable) {
        this.observable = observable;
        observable.addObserver(this);
    }
    public void update(Observer obs, Object arg) {
        if (obs instanceof WeatherData3) {
            WeatherData3 weatherData = (WeatherData3)obs;
            this.temperature = weatherData.getTemperature();
            display();
        }
    }
    public void display() {
        //... 显示的实现
    }
}可见系统内置的观察方式,已经帮我们定义了注册观察者、通知观察者及其触发的更新方法。只是特别需要注意setChanged()这个方法需要在状态改变后先调用,后再调用notifyObservers()。
总结
观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 mingfungliu@gmail.com
文章标题:设计模式(六)命令模式 & 观察者模式
文章字数:847
本文作者:Mingfung
发布时间:2019-02-12, 14:28:00
最后更新:2019-02-12, 14:34:39
原始链接:http://blog.ifungfay.com/设计模式/设计模式(六)命令模式 & 观察者模式/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。
 
            