1、观察者模式使用情况
第一、当一个抽象模型有两个方面,其中一个方面的操作依赖于另一个方面的状态变化
第二、如果在更改一个对象的时候,需要同时连带改变其他的对象,而且不知道究竟应该有多少对象需要被连带改变
第三、当一个对象必须通知其他的对象,但是你又不希望这个对象和其他被通知的对象是松散耦合的
3、观察者模式代码结构:
第一、目标接口,定义添加观察者到需要被通知的列表中和将制定的观察者从通知列表中删除的方法,定义状态更新方法
第二、目标接口具体实现类,定义具体的目标状态存储字段,目标状态改变时调用通知方法
第三、观察者接口,定义观察者接收到目标状态更新时做出相应处理的通知方法
第四、观察者接口实现类,实现观察者通知方法,定义观察者名称、接收目标状态的字段、观察者通知时的内容
4、观察者模式推模型和拉模型示例
使用场景:黄明在气象局工作,为女朋友和老妈提供天气状况
推模型:目标对象将更新内容推送给观察者
/**
* 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口
*
*/
public class WeatherSubject {
//用来保存注册的观察者模式对象
List<Observer> observes = new ArrayList<Observer>();
//将观察者添加到观察者对象列表
public void attach(Observer observe){
observes.add(observe);
}
//删除集合中的指定观察者
public void detach(Observer observe){
observes.remove(observe);
}
//通知所有注册的观察者对象,传入需要更新的状态
protected void notifyObserves(String content){
for(Observer observe : observes){
observe.update(content);
}
}
}
/**
* 具体的目标对象,负责把有关状态存入到相应的观察者中
* *
*/
public class ConcreteWeatherSubject extends WeatherSubject{
//目标对象的状态
private String weatherContent;
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
//内容有了,说明天气更新了,通知所有订阅的人
this.notifyObserves(weatherContent);
}
}
/**
* 这是一个观察者接口,定义一个更新的接口给那些在目标状态发生改变时被通知的对象
* *
*/
public interface Observer {
/**
* 更新的接口,更新传递的内容
*/
public void update(String content);
}
/**
*
* 具体的观察者,实现更新的方法,是自己的状态和目标的状态保持一致
*/
public class ConcreteObserver implements Observer{
//观察者的名字,是谁收到了这条信息
private String observerName;
//目标对象通知的内容
private String weatherContent;
//观察者接到通知后做出的提醒
private String remindThing;
/**
* 获取目标对象的状态同步到观察者通知
*/
@Override
public void update(String content) {
weatherContent = content;
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;
}
}
//观察者模式推模型测试
public class ObserverTest {
public static void main(String[] args) {
//创建目标对象
ConcreteWeatherSubject weather = new ConcreteWeatherSubject();
//创建观察者对象
ConcreteObserver observerGirl = new ConcreteObserver();
observerGirl.setObserverName("黄明女朋友");
observerGirl.setRemindThing("这是我们第一次约会,地点街心公园,不见不散");
ConcreteObserver observerMum = new ConcreteObserver();
observerMum.setObserverName("老妈");
observerMum.setRemindThing("是一个购物的好日子,明天去天虹扫货");
//注册观察者
weather.attach(observerGirl);
weather.attach(observerMum);
//目标对象发布更新内容
weather.setWeatherContent("明天天气晴朗,蓝天白云,气温28度");
}
}
拉模型:观察者获取目标对象后自己根据需要获取相应的更新内容
/**
* 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口
*
*/
public class WeatherSubject {
//用来保存注册的观察者模式对象
List<Observer> observes = new ArrayList<Observer>();
//将观察者添加到观察者对象列表
public void attach(Observer observe){
observes.add(observe);
}
//删除集合中的指定观察者
public void detach(Observer observe){
observes.remove(observe);
}
//通知所有注册的观察者对象
protected void notifyObserves(){
for(Observer observe : observes){
observe.update(this);
}
}
}
/**
* 具体的目标对象,负责把有关状态存入到相应的观察者中
* *
*/
public class ConcreteWeatherSubject extends WeatherSubject{
//目标对象的状态
private String weatherContent;
public String getWeatherContent() {
return weatherContent;
}
public void setWeatherContent(String weatherContent) {
this.weatherContent = weatherContent;
//内容有了,说明天气更新了,通知所有订阅的人
this.notifyObserves();
}
}
/**
* 这是一个观察者接口,定义一个更新的接口给那些在目标状态发生改变时被通知的对象
* *
*/
public interface Observer {
/**
* 更新的接口,传入目标对象,方便获取相应的目标对象的状态
*/
public void update(WeatherSubject subject);
}
/**
*
* 具体的观察者,实现更新的方法,是自己的状态和目标的状态保持一致
*/
public class ConcreteObserver implements Observer{
//观察者的名字,是谁收到了这条信息
private String observerName;
//目标对象通知的内容
private String weatherContent;
//观察者接到通知后做出的提醒
private String remindThing;
/**
* 获取目标对象的状态同步到观察者通知
*/
@Override
public void update(WeatherSubject subject) {
// TODO Auto-generated method stub
weatherContent = ((ConcreteWeatherSubject)subject).getWeatherContent();
System.out.println(observerName + "收到了" + weatherContent + "," + remindThing);
}
public String getObserverName() {
return observerName;
}
public void setObserverName(String observerName) {
this.observerName = observerName;
}
2、观察者模式优缺点
优点:观察者模式实现了观察者和目标之间的抽象耦合,观察者模式实现了动态联动,观察者模式支持广播通信
缺点:可能引起无谓的操作