微信公众号:幼儿园的学霸
观察者模式面向的需求是:A对象(观察者)对B对象(被观察者)的某种变化高度敏感,需要在B变化的一瞬间做出反应。举个例子,新闻里喜闻乐见的警察抓小偷,警察需要在小偷伸手作案的时候实施抓捕。在这个例子里,警察是观察者、小偷是被观察者,警察需要时刻盯着小偷的一举一动,才能保证不会错过任何瞬间。程序里的观察者和这种真正的【观察】略有不同,观察者不需要时刻盯着被观察者(例如A不需要每隔1ms就检查一次B的状态),而是采用注册(Register)或者成为订阅(Subscribe)的方式告诉被观察者:我需要你的某某状态,你要在它变化时通知我。采取这样被动的观察方式,既省去了反复检索状态的资源消耗,也能够得到最高的反馈速度。
The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.
观察者模式(Observer),又叫发布-订阅模式(Publish/Subscribe),定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并自动更新。
该模式属于行为型模式。
发布-订阅模式和观察者模式两者之间能否划上等号,网上的看法分为两极,众说纷纭。
看法一:发布订阅模式里的Publisher,就是观察者模式里的Subject,而Subscriber,就是Observer。Publisher变化时,就主动去通知Subscriber
看法二:在发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识,两者完全不耦合。他们的交流是通过第三者,也就是在消息队列里面的Broker我的看法: 模式区别除了实现外,最重要的是模式的目的性。显然两者都实现了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新,从目的来看,两者是一样的。
有两大类(主题和观察者)一共四个角色
从上面我们可以看到,这里面包含了:
核心: 交互对象之间进行松耦合设计
代码关键:
被观察对象自身应该包含一个容器来存放观察者对象,当被观察者自身发生改变时通知容器内所有的观察者对象自动更新。
观察者对象可以注册到被观察者的中,完成注册后可以检测被观察者的变化,接收被观察者的通知。当然观察者也可以被注销掉,停止对被观察者的监控。
#include <bits/stdc++.h> // //观察者模式 // class Observer; //抽象被观察者 class Subject { public: Subject() : m_nState(0) {} virtual ~Subject() = default; virtual void Attach(const std::shared_ptr<Observer> pObserver) = 0; virtual void Detach(const std::shared_ptr<Observer> pObserver) = 0; virtual void Notify() = 0; virtual int GetState() { return m_nState; } void SetState(int state) { std::cout << "Subject updated !" << std::endl; m_nState = state; } protected: std::list<std::shared_ptr<Observer>> m_pObserver_list; int m_nState; }; //抽象观察者 class Observer { public: virtual ~Observer() = default; Observer(const std::shared_ptr<Subject> pSubject, const std::string &name = "unknown") : m_pSubject(pSubject), m_strName(name) {} virtual void Update() = 0; virtual const std::string &name() { return m_strName; } protected: std::shared_ptr<Subject> m_pSubject; std::string m_strName; }; //具体被观察者 class ConcreteSubject : public Subject { public: void Attach(const std::shared_ptr<Observer> pObserver) override { auto iter = std::find(m_pObserver_list.begin(), m_pObserver_list.end(), pObserver); if (iter == m_pObserver_list.end()) { std::cout << "Attach observer" << pObserver->name() << std::endl; m_pObserver_list.emplace_back(pObserver); } } void Detach(const std::shared_ptr<Observer> pObserver) override { std::cout << "Detach observer" << pObserver->name() << std::endl; m_pObserver_list.remove(pObserver); } //循环通知所有观察者 void Notify() override { auto it = m_pObserver_list.begin(); while (it != m_pObserver_list.end()) { (*it++)->Update(); } } }; //具体观察者1 class Observer1 : public Observer { public: Observer1(const std::shared_ptr<Subject> pSubject, const std::string &name = "unknown") : Observer(pSubject, name) {} void Update() override { std::cout << "Observer1_" << m_strName << " get the update.New state is: " << m_pSubject->GetState() << std::endl; } }; //具体观察者2 class Observer2 : public Observer { public: Observer2(const std::shared_ptr<Subject> pSubject, const std::string &name = "unknown") : Observer(pSubject, name) {} void Update() override { std::cout << "Observer2_" << m_strName << " get the update.New state is: " << m_pSubject->GetState() << std::endl; } }; int main() { std::shared_ptr<Subject> pSubject = std::make_shared<ConcreteSubject>();// 创建被观察者 // 创建观察者 std::shared_ptr<Observer> pObserver1_1 = std::make_shared<Observer1>(pSubject, "1"); std::shared_ptr<Observer> pObserver1_2 = std::make_shared<Observer1>(pSubject, "2"); std::shared_ptr<Observer> pObserver1_3 = std::make_shared<Observer1>(pSubject, "3"); std::shared_ptr<Observer> pObserver2_4 = std::make_shared<Observer2>(pSubject, "4"); std::shared_ptr<Observer> pObserver2_5 = std::make_shared<Observer2>(pSubject, "5"); std::shared_ptr<Observer> pObserver2_6 = std::make_shared<Observer2>(pSubject, "6"); // 注册观察者 pSubject->Attach(pObserver1_1); pSubject->Attach(pObserver1_2); pSubject->Attach(pObserver1_3); pSubject->Attach(pObserver2_4); pSubject->Attach(pObserver2_5); pSubject->Attach(pObserver2_6); pSubject->SetState(2);// 改变状态 pSubject->Notify(); std::cout << std::string(50, '-') << std::endl; // 注销观察者 pSubject->Detach(pObserver1_1); pSubject->Detach(pObserver1_2); pSubject->SetState(3); pSubject->Notify(); return 0; //运行结果如下: //Attach observer1 //Attach observer2 //Attach observer3 //Attach observer4 //Attach observer5 //Attach observer6 //Subject updated ! //Observer1_1 get the update.New state is: 2 //Observer1_2 get the update.New state is: 2 //Observer1_3 get the update.New state is: 2 //Observer2_4 get the update.New state is: 2 //Observer2_5 get the update.New state is: 2 //Observer2_6 get the update.New state is: 2 //-------------------------------------------------- //Detach observer1 //Detach observer2 //Subject updated ! //Observer1_3 get the update.New state is: 3 //Observer2_4 get the update.New state is: 3 //Observer2_5 get the update.New state is: 3 //Observer2_6 get the update.New state is: 3 }
两个模式的意图还是非常相像的:
1.都属于行为型模式
2.都为了处理一对多的关系
3.UML实现基本相同,都有集合管理业务对象的集合,都有循环通知的方法,符合单一职责原则。
but,两者之间区别还是蛮大的:
中介模式中存在Mediator和Colleague两个角色,Mediator一般不会主动发起事件去通知Colleague,而Colleague具有发送和接收消息的两种能力。Mediator一般不会是消息的源头,也不会是消息传输的终点,它充当中转站的角色。而Colleague既可以是消息的发起者,也可以是消息传输的接收者,这意味着消息是双向的。Colleague可以存在多个,中介者(mediator)强调的是同事(colleague)类之间的交互。
反观观察者模式,消息的发起者只有一个,即Subject,所有Observer都关注Subject的消息,Subject只能发消息,Observer只能收消息,即消息的通知是单向的。观察者模式强调的是目标改变后对观察者进行统一的通讯,即被观察者与观察者之间的交互,所有的观察者都是一样的
适用场景
1.一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用
2.一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度
3.一个对象必须通知其他对象,而并不知道这些对象是谁
4.需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制
5.跨系统的消息变换场景,如消息队列的处理机制
应用实例
1.手机丢了,委托别人给其他人发消息通知
2.通知老师/老板来了
3.拍卖,拍卖师观察最高标价,然后通知给其它竞价者竞价
4.猫叫了一声,吓着了老鼠,也惊到了主人,猫是被观察者,老鼠和人是观察者
5.西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水招来一个老乌龟,这个乌龟就是观察者,他观察菩萨洒水这个动作
观察者模式解除了主体和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
1.简说设计模式——观察者模式
2.观察者模式
3.设计模式之观察者模式
4.设计模式专辑——中介模式、观察者模式的比较
下面的是我的公众号二维码图片,按需关注。