实现观察者模式通用步骤
- 目标对象的定义
- 具体的目标对象定义
- 观察者接口的定义
- 观察者接口的具体实现
/**目标对象.它知道观察它的观察者, 并提供注册和删除观察者的接口
*/
public class Subject {
//用来保存注册的观察者对象
private List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer observer) {
observers.add(observer);
}
/*
* 删除集合中的制定观察者
* @param observer
* */
public void detach(Observer observer){
observers.remove(observer);
}
/*
通知所有注册的观察者对象
* */
protected void notifyObservers(){
for(Observer observer: observers){
observer.update(this);
}
}
}
public class ConcreteSubject extends Subject {
private String subjectState;
public String getSubjectState() {
return subjectState;
}
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;
this.notifyObservers();
}
}
/**这是一个观察者接口,定义一个更新的接口给那些在目标发生改变的时候通知的对象
*/
public interface Observer {
/*
* 更新接口
* @param subject 传入目标对象,方便获取相应的目标对象的状态
* */
public void update(Subject subject);
}
/**具体的观察者对象,实现更新的方法, 使自身的状态和目标的状态保持一致
*/
public class ConcreteObserver implements Observer {
//观察者的状态
private String observerState;
@Override
public void update(Subject subject) {
observerState = ((ConcreteSubject)subject).getSubjectState();
}
}
观察者案例(天气通知)
package com.test.WeatherObserverPattern;
import java.util.ArrayList;
import java.util.List;
/**目标对象.它知道观察它的观察者, 并提供注册和删除观察者的接口
*/
public class WeatherSubject {
//用来保存注册的观察者对象
private List<Observer> observers = new ArrayList<Observer>();
//把订阅天气的人添加到订阅者列表中
public void attach(Observer observer) {
observers.add(observer);
}
/*
* 删除集合中的制定订阅天气的人
* @param observer
* */
public void detach(Observer observer){
observers.remove(observer);
}
/*
通知所有已经订阅天气的人
* */
protected void notifyObservers(){
for(Observer observer: observers){
observer.update(this);
}
}
}
package com.test.WeatherObserverPattern;
public class ConcreteWeatherSubject extends WeatherSubject {
//获取天气的内容
private String weatherContent;
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
//内容有了, 说明天气更新了, 通知所有订阅的人
this.notifyObservers();
}
}
package com.test.WeatherObserverPattern;
/**具体的观察者对象,实现更新的方法, 使自身的状态和目标的状态保持一致
* Created by yangshuangpeng on 17-1-25.
*/
public class ConcreteObserver implements Observer {
//观察者的名字,是谁收到了这个讯息
private String observerName;
//天气内容的情况,这个消息从目标出获取
private String weatherContent;
//提醒的内容
private String remindThing;
/*
*获取目标类的状态同步至观察者的状态中
* */
@Override
public void update(WeatherSubject subject) {
weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent();
System.out.println(observerName+"收到了"+ weatherContent + "," + remindThing);
}
public String getObserverName() {
return observerName;
}
public void setObserverName(String observerName) {
this.observerName = observerName;
}
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
}
public String getRemindThing() {
return remindThing;
}
public void setRemindThing(String remindThing) {
this.remindThing = remindThing;
}
}
package com.test.WeatherObserverPattern;
/**这是一个观察者接口,定义一个更新的接口给那些在目标发生改变的时候通知的对象
*/
public interface Observer {
/*
* 更新接口
* @param subject 传入目标对象,方便获取相应的目标对象的状态
* */
public void update(WeatherSubject subject);
}
测试类
package com.test.WeatherObserverPattern;
/**
*/
public class client {
public static void main(String[] args)
{
//1.创建目标
ConcreteWeatherSubject weather = new ConcreteWeatherSubject();
//2.创建观察者
ConcreteObserver observer = new ConcreteObserver();
observer.setObserverName("李明");
observer.setRemindThing("适合出去玩");
ConcreteObserver observer1 = new ConcreteObserver();
observer1.setObserverName("李华");
observer1.setRemindThing("适合散步");
//3.注册观察者
weather.attach(observer);
weather.attach(observer1);
//4.目标发布天气
weather.setWeatherContent("明天天气晴朗, 蓝天白云");
}
}
认识观察者模式
- 目标与观察者之间的关系
- 单向依赖
- 命名建议
- 触发通知时机
- 观察者模式的调用顺序图
- 通知的顺序
命名建议
目标接口的定义,建议在名称后面跟Subject
观察者接口的定义,建议在名称后面跟Observer
观察者接口更新的方法,建议名称为update
观察者模式实现的两种方式
- 推模型(目标对象主动向观察者推送目标的详细信息,通送的信息通常是目标对象的全部或部分数据)
- 拉模型(目标对象在通知观察者对象的时候,值传递少量的信息,如果观察者需要更具体的信息,由观察者主动到目标对象中获取,相当于是观察者从目标对象中拉数据)