什么是观察者模式
观察者模式又称作发布-订阅模式,定义了一对多的依赖关系,让多个者对象同时监听某一个主题对象。这个主题对象发生变化时,会通知所有的观察者对象,使他们能够自动更新自己;
简单解释
声明一个被观察者(发布),由其它被观察者注册到被观察者中,当被观察者状态发生变化时,通知到所有的观察者,并由每个观察者做出的处理,从而达到解耦的目的;
UML类图
优点
1、观察者和被观察者是抽象耦合的。
2、建立一套触发机制。
缺点
1、如果一个被观察者的直接或间接的观察者对象有很多,那么将观察者通知完会花费很多时间;
2、如果观察者与观察者目标之间有相互依赖的话,观察者会触发它们之间的循环调用,会导致系统崩溃;
3、观察者模式没有机制让所有的观察者知道目标是如何发生变化的,仅仅知道目标发生了变化;
代码解释
以下雨天收衣服为例,妈妈发现下雨了,通知老大、老二、小明去收衣服、拖地、关窗户,但是未通知到小明,导致没有拖地;
- 声明一个被观察者接口
/**
* 定义一个抽象通知类
* @author ws
* @version 1.0
*/
public interface Subject {
public void Add(Observer obj);
public void Remove(Observer obj);
public void Notify();
public String SubjectState();
}
- 声明一个老妈,观察是否下雨
import java.util.ArrayList;
import java.util.List;
public class LaoMaSubject implements Subject {
List<Observer> observers=new ArrayList<>();
@Override
public void Add(Observer obj) {
observers.add(obj);
}
@Override
public void Remove(Observer obj) {
observers.remove(obj);
}
@Override
public void Notify() {
for (Observer obj:observers) {
obj.Update();
}
}
@Override
public String SubjectState() {
return "下雨了";
}
}
- 声明一个观察者抽象类,定义更新方法
/**
* 抽象观察者
* @author ws
* @version 1.0
*/
public abstract class Observer {
protected String name;
protected Subject sub;
public Observer(String name,Subject sub){
this.name=name;
this.sub=sub;
}
public abstract void Update();
}
- 声明相应的观察者实体类
public class GuanCHObj extends Observer {
public GuanCHObj(String name, Subject sub) {
super(name, sub);
}
@Override
public void Update() {
System.out.println(String.format("%s,%s去把窗户关了",sub.SubjectState(),name));
}
}
public class ShouYiFuObj extends Observer {
public ShouYiFuObj(String name, Subject sub) {
super(name, sub);
}
@Override
public void Update() {
System.out.println(String.format("%s,%s去把衣服收了",sub.SubjectState(),name));
}
}
public class TuoDiObj extends Observer {
public TuoDiObj(String name, Subject sub) {
super(name, sub);
}
@Override
public void Update() {
System.out.println(String.format("%s,%s去把衣服收了",sub.SubjectState(),name));
}
}
- 测试输出
public static void main(String[] args) {
Subject laoma=new LaoMaSubject();
Observer syf=new ShouYiFuObj("老大",laoma);
Observer gch=new GuanCHObj("老二",laoma);
Observer td=new TuoDiObj("小明",laoma);
laoma.Add(syf);
laoma.Add(gch);
laoma.Add(td);
laoma.Remove(td);
laoma.Notify();
}
------输出结果--------
下雨了,老大去把衣服收了
下雨了,老二去把窗户关了