设计模式(六)命令模式 & 观察者模式
命令模式
应用场景
使用多功能的遥控器打开一个电灯
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" 转载请保留原文链接及作者。