观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
其UML图如下:
下面以在工作中同事摸鱼,当老板回来时,前台通知同事停止摸鱼,继续工作为例子来说明观察者模式。
涉及的角色:
- 抽象通知者
- 具体通知者(主题)
- 抽象观察者
- 具体观察者(订阅者)
抽象通知者:
/**
* 主体类或者抽象通知者
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public abstract class Subject {
// 通知者名称
protected String name;
// 通知者状态
protected String subjectState;
// 通知的内容
protected String content;
// 新增
public abstract void addObserver(Observer observer);
// 移除
public abstract void removeObserver(Observer observer);
// 通知行为
public abstract void notifyMsg();
}
具体通知者:
/**
* 具体通知者(前台)
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class ConcreteSubject extends Subject{
// 观察者列表
private List<Observer> observers = new ArrayList<>();
public ConcreteSubject(String name, String subjecState, String content){
super.name = name;
super.subjectState = subjecState;
super.content = content;
}
// 新增
@Override
public void addObserver(Observer observer){
observers.add(observer);
}
// 移除
@Override
public void removeObserver(Observer observer){
observers.remove(observer);
}
// 通知行为
@Override
public void notifyMsg(){
for (Observer observer : observers) {
observer.update();
}
}
}
抽象观察者:
/**
* 抽象观察者
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public abstract class Observer {
//观察者名称
protected String name;
//通知者
protected Subject subject;
// 观察者的行为
public abstract void update();
// 移除使用
@Override
public boolean equals(Object obj) {
return obj.equals(name);
}
}
具体观察者1号:
/**
* 具体观察者1号 在摸鱼看直播
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class ConcreteObserver01 extends Observer{
public ConcreteObserver01(String name, Subject subject) {
super.name = name;
super.subject = subject;
}
@Override
public void update() {
System.out.println(subject.name + " " + subject.subjectState + " " + subject.content + " " + super.name + " 停止观看NBA直播,继续工作!");
}
}
具体观察者2号:
/**
* 具体观察者2号 在摸鱼看股票
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class ConcreteObserver02 extends Observer{
public ConcreteObserver02(String name, Subject subject) {
super.name = name;
super.subject = subject;
}
@Override
public void update() {
System.out.println(subject.name + " " + subject.subjectState + " " + subject.content + " " + super.name + " 停止观看股票,继续工作!");
}
}
测试:
/**
* @author Linging
* @version 1.0.0
* @since 1.0
*/
public class Main {
/**
* 观察者模式
* 1.抽象通知者 Subject
* 2.具体通知者 ConcreteSubject
* 3.抽象观察者 Observer
* 4.具体观察者 ConcreteObserver01、ConcreteObserver02....
*
* 同事摸鱼,老板回来,前台通知同事停止摸鱼,继续工作
* @param args
*/
public static void main(String[] args) {
// 具体通知者|主题 前台
Subject subject = new ConcreteSubject("前台", "高度警惕", "boss回来了");
// 具体观察者|订阅者
Observer observer01 = new ConcreteObserver01("张三", subject);
Observer observer02 = new ConcreteObserver02("李四", subject);
subject.addObserver(observer01);
subject.addObserver(observer02);
// 由于李四跟前台的关系不好,所以前台把李四从观察者列表剔除,导致李四没有收到通知,哈哈
subject.removeObserver(observer02);
// 通知
subject.notifyMsg();
}
}
观察者模式总结:
优点:
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。符合依赖倒置原则。
- 目标与观察者之间建立了一套触发机制。
缺点:
- 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
- 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。