观察者模式

一、观察者模式

观察者模式又叫发布-订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时会通知所有的观察者对象,使它们能够自动地更新自己。当一个对象的改变需要改变其他的对象的时候就可以用观察者模式。

二、结构图

Subject类是抽象的主题对象,也是抽象通知者,可以从Observer观察者对象引用的聚集里面添加或者删除;

Observer类是抽象观察者,在得到主题的通知时更新自己。

三、示例

import java.util.ArrayList;
import java.util.List;

//抽象通知者
abstract class Subject{
    List<Observer> observers=new ArrayList<>();
    //增加观察者
    protected void attach(Observer observer){
        observers.add(observer);
    }
    //移除观察者
    protected void detach(Observer observer){
        observers.remove(observer);
    }
    //进行通知
    protected void notifying(){
        for (Observer o :observers) {
            o.update();
        }
    }
}
//抽象观察者
abstract class Observer{
    abstract void update();
}

//具体通知者,将有关状态存入具体观察者对象,
// 在具体主题的内部状态改变时,给所有登记过的观察者发出通知。
class ConcreteSubject extends Subject{
    private String subjectState;
    //具体被观察者状态

    public String getSubjectState() {
        return subjectState;
    }

    public void setSubjectState(String subjectState) {
        this.subjectState = subjectState;
    }
}

//具体观察者
class ConcreteObserver extends Observer{
    private String name;
    private String observerState;
    private ConcreteSubject subject;
    
    public ConcreteObserver(ConcreteSubject subject,String name){
        this.subject=subject;
        this.name=name;
    }
    
    @Override
    void update() {
        observerState=subject.getSubjectState();
        System.out.println("观察者"+name+"的状态:"+observerState);
    }
}


public class ObserverPattern {
    public static void main(String[] args) {
        ConcreteSubject s=new ConcreteSubject();
        s.attach(new ConcreteObserver(s,"one"));
        s.attach(new ConcreteObserver(s,"two"));
        s.attach(new ConcreteObserver(s,"three"));
    
        s.setSubjectState("ABC");
        s.notifying();
    }
}

输出结果:

四、观察者模式的不足

可以从上面的梳理中发现一些问题,

首先,抽象的观察者和抽象的通知者还是耦合的,那如果缺少通知者或者观察者的抽象类,那就无法完成工作了呀;

另外,观察者可能不一定是是更新状态这些抽象类中统一的操作,可能还会进行一些其他的操作,

这些是需要改进的问题。

如果可以使客户端来决定谁通知谁,那就可以优化上面的问题,

那么可以去掉抽象观察者类,将各个具体的观察者的更新操作设置不同的方法名,

通知者也不在依赖抽象观察者,添加与删除观察者也没必要了,但是那有如何处理具体通知者对观察者的通知呢?

在.NET中可以通过委托来处理,

但是,java当中没有委托啊。

五、委托

委托?什么是委托?怎么委托呢?

可以这样说,在之前,我们是以通知者的通知来调用观察者的相应的更新方法的,

但是委托就相当于把通知者的方法倒挂于通知者身上,相当于把不同的方法委托给通知者来更新了,

只要通知者更新,就会使观察者更新。

java当中没有对委托进行封装,但是通过反射还是能够实现实现事件委托,

可以参考:https://blog.csdn.net/yanshujun/article/details/6494447#commentBox

菜甜二的学习笔记and总结啊。。。总会遇到挫折,可是还是要保持开阔的心态才能开心的学习啊,坚持吧。
原文地址:https://www.cnblogs.com/chen-ying/p/11258386.html