设计模式之观察者模式

1、定义

观察者模式(Observer Pattern)观察者模式又被称为发布订阅模式,它定义了对象间一种一对多的依赖关系,使得每当一个对象改变状态,所有依赖于它的对象都会得到通知并被自动更新

2、形式

观察者模式通用类图如下所示:

在这里插入图片描述
其中,

  • Subject为被观察者,一般是抽象类或实现类,其定义了观察者必须实现的职责,它必须能够动态的增加、取消观察者(管理观察者并通知观察者)。
  • Observer为观察者,观察者接收到消息后,会进行update操作,对消息进行处理。
  • ConcreteSubject为具体的被观察者,定义被观察者的业务逻辑,同时定义对哪些事件进行通知。
  • ConcreteObserver为具体的观察者,定义消息处理逻辑。

对应代码如下:

Subject

public abstract class Subject {
    private Vector<Observer> obsVector = new Vector<Observer>();
    public void add(Observer observer){
        this.obsVector.add(observer);
    }
    public void delete(Observer observer){
        this.obsVector.remove(observer);
    }
    public void notifyObservers(){
        for(Observer o: this.obsVector){
            o.update();
        }
    }
}

Observer

public interface Observer {
    public void update();
}

ConcreteSubject

public class ConcreteSubject extends Subject{
    public void doSomething(){
        /*
        * 业务处理逻辑
        * */
        super.notifyObservers();
    }
}

ConcreteObserver

public class ConcreteObserver implements Observer{
    public void update() {
        System.out.println("接收到消息,进行处理...");
    }
}

Client

public class Client {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        Observer obs = new ConcreteObserver();
        subject.add(obs);
        /*消息被obs观察者接受到*/
        subject.doSomething();
    }
}

3、优缺点

优点

  • 观察者和被观察者之间是抽象耦合,提高了可扩展性
  • 建立了一套触发机制,可以将不同的职责串联形成复杂的逻辑关系

缺点

  • 可能会影响开发效率和运行效率,在存在多个观察者的情况下,一旦某个观察者卡壳可能会影响整体的执行效率(java消息通知默认是顺序执行),在这种情况下,会考虑采用异步的方式。

4、使用场景

  • 关联行为场景,关联行为需要是可拆分的,要与组合关系区别开
  • 事件多级触发场景
  • 跨系统的消息交换场景,例如消息队列的处理机制

使用观察者模式还需要注意下面两个可能存在问题:

广播链的问题

如果一个对象即是观察者又是被观察者,那么就可能会形成一条观察链,但这样会增加代码的复杂性,导致系统的可维护性变差。因此一般控制系统中最多出现一个既是观察者又是被观察者的对象。

异步处理的问题

被观察者发生动作之后观察者要做出回应,如果观察者比较对导致处理时间比较长就可以采用异步处理,但需要考虑线程安全和队列的问题。

5、扩展

1)java中的观察者模式

JDK中提供了一个java.util.Observer接口和Observable实现类。可以通过实现Observer接口来定义一个观察者,该接口中定义了一个update方法,该方法中包含了两个参数供我们处理,如下所示:

public interface Observer {
    /**
     * This method is called whenever the observed object is changed. An
     * application calls an <tt>Observable</tt> object's
     * <code>notifyObservers</code> method to have all the object's
     * observers notified of the change.
     *
     * @param   o     the observable object.
     * @param   arg   an argument passed to the <code>notifyObservers</code>
     *                 method.
     */
    void update(Observable o, Object arg);
}

类似的,被观察者可以通过继承Observable类来实现,该类提供了众多方法供我们调用,这些方法包含增加观察者、删除观察者、通知观察者、获取观察者总数以及关于状态变更的相应方法,具体如下:

在这里插入图片描述
将之前的模板代码修改如下:

ConcreteSubject

/*被观察者*/
public class ConcreteSubject  extends Observable {
    public void haveAction(){
        System.out.println("吃饭了...");
        System.out.println("观察者数量为:" + this.countObservers());
        /*状态发生变更,通知观察者(如果不显式表明状态发生变更,该行为将不会通知给观察者)*/
        super.setChanged();
        super.notifyObservers();
    }
}

ConcreteObserver

/*观察者*/
public class ConcreteObserver implements Observer {
    public void update(Observable o, Object arg) {
        System.out.println("观察到目标活动");
    }
}

Client

public class Client {
    public static void main(String[] args) {
        ConcreteSubject subject = new ConcreteSubject();
        ConcreteObserver obs = new ConcreteObserver();
        subject.addObserver(obs);
        /*消息被obs观察者接受到*/
        subject.haveAction();
    }
}

执行client类后,从结果可以看出被观察者的活动可以被观察者所知晓。

在这里插入图片描述
2)应用时所要考虑的问题

在实际应用中,该模式往往会进行一下几方面的扩展。

  • 观察者和被观察者之间的消息沟通

update的两个参数在实际中一般一个为被观察者,一个是数据传输对象,数据由被观察者产生,由观察者消费。

  • 观察者的响应方式

在多个观察者但只有少量被观察者的条件下,为了保证观察者能够快速响应,往往会采用多线程技术和缓存技术。

  • 被观察者尽量自己做主

为了防止加重观察者的处理逻辑,在设计时可以灵活考虑被观察者的自主性,让被观察者决定是否要将消息传输给观察者。

6、小结

观察者模式是一个被广泛使用的设计模式,主要应用于事物之间的通知关联,应当熟练掌握。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
观察者模式是一种常用的设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,它的所有观察者都会收到通知并更新自己的状态。 在C++中,观察者模式通常由一个抽象主题类和多个具体观察者类组成。抽象主题类中定义了添加、删除和通知观察者的接口,具体观察者类实现了更新自身状态的方法。 以下是一个简单的观察者模式示例: ```c++ #include <iostream> #include <vector> class Observer { public: virtual void update() = 0; }; class Subject { public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { for (auto it = observers.begin(); it != observers.end(); ++it) { if (*it == observer) { observers.erase(it); break; } } } void notify() { for (auto observer : observers) { observer->update(); } } private: std::vector<Observer*> observers; }; class ConcreteObserver1 : public Observer { public: void update() override { std::cout << "ConcreteObserver1 updated" << std::endl; } }; class ConcreteObserver2 : public Observer { public: void update() override { std::cout << "ConcreteObserver2 updated" << std::endl; } }; int main() { Subject subject; ConcreteObserver1 observer1; ConcreteObserver2 observer2; subject.attach(&observer1); subject.attach(&observer2); subject.notify(); subject.detach(&observer1); subject.notify(); return 0; } ``` 在上面的示例中,Subject类是抽象主题类,Observer类是抽象观察者类,ConcreteObserver1和ConcreteObserver2是具体观察者类。当Subject对象状态发生变化时,它会通知所有观察者更新自己的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leo木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值