简介
观察者模式又叫发布-订阅模式,定义了对象之间的一对多依赖,多个观察者对象可同时监听某一主题对象,当该主题对象状态发生变化时,相应的所有观察者对象都可收到通知。典型的场景,比如我们关注某个微信公众号,当公众号有新的内容发布,那么所有关注了该公众号的用户都将收到最新的内容,当我们觉得这个公众号的内容不好不想在接收到这个公众号推送的内容,那么只需要取消关注即可,当这个公众号有新的内容发布也就不会再推送给我们
实现
UML类图
角色
- 主题,主题信息抽象,一般使用接口表示,如上Subject
- 具体主题,具体的主题信息,如上ConcreteSubject
- 观察者,订阅主题信息的实体,如上Observer
- 具体观察者,具体订阅主题的个体,如上ConcreteObserver
当多个观察者同时订阅一个主题,那么主题和这些观察者就建立了一对多的关系,一旦主题有任何变化,会通知到所有这些订阅主题的观察者
代码示例
主题
package com.huawei.design.observer;
/**
* @author: xuqiangnj@163.com
* @date: 2019/5/5 23:23
* @description: 主题接口
*/
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
具体主题
package com.huawei.design.observer;
import java.util.ArrayList;
import java.util.List;
/**
* @author: xuqiangnj@163.com
* @date: 2019/5/5 23:28
* @description: 具体主体
*/
public class ConcreteSubject implements Subject {
private List<Observer> observerList;
public ConcreteSubject(){
observerList = new ArrayList<>();
}
@Override
public void registerObserver(Observer observer) {
observerList.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observerList.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observerList) {
observer.update("send notify message");
}
}
}
观察者
package com.huawei.design.observer;
/**
* @author: xuqiangnj@163.com
* @date: 2019/5/5 23:24
* @description: 观察者
*/
public interface Observer {
void update(String message);
}
具体观察者1
package com.huawei.design.observer;
/**
* @author: xuqiangnj@163.com
* @date: 2019/5/5 23:31
* @description: 具体观察者1
*/
public class ConcreteObserver1 implements Observer {
@Override
public void update(String message) {
System.out.println("ConcreteObserver1 receive : " + message);
}
}
具体观察者2
package com.huawei.design.observer;
/**
* @author: xuqiangnj@163.com
* @date: 2019/5/5 23:32
* @description: 具体观察者2
*/
public class ConcreteObserver2 implements Observer{
@Override
public void update(String message) {
System.out.println("ConcreteObserver2 receive : " + message);
}
}
测试类
package com.huawei.design.observer;
/**
* @author: xuqiangnj@163.com
* @date: 2019/5/5 23:38
* @description: 测试类
*/
public class TestObserver {
public static void main(String[] args) {
Observer observer1 = new ConcreteObserver1();
Observer observer2 = new ConcreteObserver2();
Subject subject = new ConcreteSubject();
subject.registerObserver(observer1);
subject.registerObserver(observer2);
subject.notifyObservers();
System.out.println("==============remove observer1===============");
subject.removeObserver(observer1);
subject.notifyObservers();
}
}
运行结果
ConcreteObserver1 receive : send notify message
ConcreteObserver2 receive : send notify message
==============remove observer1===============
ConcreteObserver2 receive : send notify message
Process finished with exit code 0
观察者模式优点
- 抽象主题只依赖于抽象观察者
- 观察者模式支持广播通信
- 观察者模式使信息产生层和响应层分离
观察者模式缺点
- 如一个主题被大量观察者注册,则通知所有观察者会花费较高代价
- 如果某些观察者的响应方法被阻塞,整个通知过程即被阻塞,其它观察者不能及时被通知
总结
观察者模式提供了一种对象设计,让主题和观察者之间耦合度降得很低,关于观察者的一切,主题只知道观察者实现了Observer接口,并不需要观察者具体的类是谁,做了什么或者其他细节,观察者和主题之间松耦合,改变主题或者观察者其中一方,并不会影响另一方,只要他们之间的接口仍被遵守,这也面向接口带来的好处,同样也是面设对象设计的一个非常重要的原则。
(转载请注明出处)