漫画设计模式:每周一篇设计模式之观察者模式
如下图,产品经理接到老板通知,需要临时新增需求,万能的产品经理,立刻通知所有程序员去实现该需求。
小安用程序的形式实现上图的过程,代码如下:
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 老板
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Boss {
public void sendOrder(){
ProductManager productManager = new ProductManager();
productManager.demandChanged();
}
}
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 产品经理
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class ProductManager {
public void demandChanged(){
Programmer programmer1 = new Programmer();
Programmer programmer2 = new Programmer();
Programmer programmer3 = new Programmer();
programmer1.updateCode();
programmer2.updateCode();
programmer3.updateCode();
}
}
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 程序员
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer {
public void updateCode(){
//苦逼的完成需求
}
}
观察者模式:
定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖着都会受到通知并自动更新。
官方定义不太好理解,我翻译一下,在观察者模式中,对象之间有一对多的依赖关系,比如一个产品经理对多个程序员,当产品经理有需求变更时,他的所有依赖的程序员都会收到需求变更通知,并修改自己的程序完成该需求。
采用观察者模式的UML图:
继承Subject的类:就是观察者模式中的“被观察者”,它会把所有观察者保存在一个集合中。
实现Observer的类:就是观察者模式中的“观察者”,它会把自己注册进被观察者中的集合中,从而使被观察者发生改变时,通知自己;也可以把自己从被观察者集合中删除,从而不接受观察者发来的通知。
被观察者父类:
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 抽象者父类
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Subject {
//观察者对象列表
private List<Observer> observers = new ArrayList<Observer>();
/**
* 注册观察者对象
* @param observer
*/
public void registerObserver(Observer observer){
if(!observers.contains(observer)) {
observers.add(observer);
}
}
/**
* 解绑观察者对象
*/
public void unRegisterObserver(Observer observer){
if(!observers.contains(observer)) {
observers.remove(observer);
}
}
//通知所有注册的观察者执行对应操作
public void notifyObservers(){
for (Observer observer : observers) {
observer.updateCode();
}
}
}
具体的被观察者:
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 具体的被观察者(产品经理)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class ProductManager extends Subject{
private static class ProductManagerSingletonHolder {
private static final ProductManager INSTANCE = new ProductManager();
}
private ProductManager (){}
public static final ProductManager getInstance() {
return ProductManagerSingletonHolder.INSTANCE;
}
//需求变更,通知观察者
public void demandChanged(){
notifyObservers();
}
}
观察者公共接口:
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 抽象的观察者,所有的观察者都实现该接口
* 当被观察者有变化需要通知时,有了一个共同的接口。
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public interface Observer {
void updateCode();
}
具体观察者对象:
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 观察者(程序员1)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer1 implements Observer{
public Programmer1() {
ProductManager.getInstance().registerObserver(this);
}
@Override
public void updateCode() {
//苦逼的完成需求
}
}
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 观察者(程序员2)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer2 implements Observer{
public Programmer2() {
ProductManager.getInstance().registerObserver(this);
}
@Override
public void updateCode() {
//苦逼的完成需求
}
}
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 观察者(程序员3)
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Programmer3 implements Observer{
public Programmer3() {
ProductManager.getInstance().registerObserver(this);
}
@Override
public void updateCode() {
//苦逼的完成需求
}
}
触发条件:
/**
* @Author: 欢迎关注公众号:程序员小安
* @description: 触发条件:老板
* @CreateDate: 2019/10/30
* @Version: 1.0
*/
public class Boss {
public void sendOrder(){
ProductManager.getInstance().demandChanged();
}
}
采用观察者模式后,观察者跟被观察者之间完全松耦合,当需要新增一个新的观察者时,因为被观察者唯一依赖的是一个实现Observer接口的列表,所以我们可以不修改原有被观察者的代码,随时增加观察者。同理,也可以随时删除某个观察者。
另一方面,主要注册的观察者,一定会收到通知,不存在通知遗漏的情况。
观察者模式的优点:
(1)具体被观察者和具体观察者是松耦合关系。
(2)观察者模式满足“开-闭原则”。
观察者模式的缺点:
(1)如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
(2)如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
(3)观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
观察者模式的应用场景:
(1) 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
(2)对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
如有错误欢迎指出来,一起学习。