3.6 观察者 Event-Subscriber、Listener、Observer 怼烎@ 2022-12-25 14:55 114阅读 0赞 **专业描述** 观察者模式是一种行为设计模式, 允许你定义一种订阅机制, 可在对象事件发生时通知多个 “观察” 该对象的其他对象。 **真实世界类比** 如果你订阅了一份杂志或报纸, 那就不需要再去报摊查询新出版的刊物了。 出版社 (即应用中的 “发布者”) 会在刊物出版后 (甚至提前) 直接将最新一期寄送至你的邮箱中。 出版社负责维护订阅者列表, 了解订阅者对哪些刊物感兴趣。 当订阅者希望出版社停止寄送新一期的杂志时, 他们可随时从该列表中退出。 **观察者模式结构** ![在这里插入图片描述][20201202143841369.png_pic_center] 1. **发布者 (Publisher)** 会向其他对象发送值得关注的事件。 事件会在发布者自身状态改变或执行特定行为后发生。 发布者中包含一个允许新订阅者加入和当前订阅者离开列表的订阅构架。 2. 当新事件发生时, 发送者会遍历订阅列表并调用每个订阅者对象的通知方法。 该方法是在订阅者接口中声明的。 3. **订阅者 (Subscriber)** 接口声明了通知接口。 在绝大多数情况下, 该接口仅包含一个 **update更新方**法。 该方法可以拥有多个参数, 使发布者能在更新时传递事件的详细信息。 4. **具体订阅者 (Concrete Subscribers)** 可以执行一些操作来回应发布者的通知。 所有具体订阅者类都实现了同样的接口, 因此发布者不需要与具体类相耦合。 5. 订阅者通常需要一些上下文信息来正确地处理更新。 因此, 发布者通常会将一些上下文数据作为通知方法的参数进行传递。 发布者也可将自身作为参数进行传递, 使订阅者直接获取所需的数据。 6. **客户端 (Client)** 会分别创建发布者和订阅者对象, 然后为订阅者注册发布者更新。 **观察者模式适合应用场景** * 当一个对象状态的改变需要改变其他对象, 或实际对象是事先未知的或动态变化的时, 可使用观察者模式。 * 当应用中的一些对象必须观察其他对象时, 可使用该模式。 但仅能在有限时间内或特定情况下使用。 **实现方式** 1. 仔细检查你的业务逻辑, 试着将其拆分为两个部分: 独立于其他代码的核心功能将作为发布者; 其他代码则将转化为一组订阅类。 2. 声明订阅者接口。 该接口至少应声明一个 **update**方法。 3. 声明发布者接口并定义一些接口来在列表中添加和删除订阅对象。 记住发布者必须仅通过订阅者接口与它们进行交互。 4. 确定存放实际订阅列表的位置并实现订阅方法。 通常所有类型的发布者代码看上去都一样, 因此将列表放置在直接扩展自发布者接口的抽象类中是显而易见的。 具体发布者会扩展该类从而继承所有的订阅行为。 但是, 如果你需要在现有的类层次结构中应用该模式, 则可以考虑使用组合的方式: 将订阅逻辑放入一个独立的对象, 然后让所有实际订阅者使用该对象。 5. 创建具体发布者类。 每次发布者发生了重要事件时都必须通知所有的订阅者。 6. 在具体订阅者类中实现通知更新的方法。 绝大部分订阅者需要一些与事件相关的上下文数据。 这些数据可作为通知方法的参数来传递。 但还有另一种选择。 订阅者接收到通知后直接从通知中获取所有数据。 在这种情况下, 发布者必须通过更新方法将自身传递出去。 另一种不太灵活的方式是通过构造函数将发布者与订阅者永久性地连接起来。 7. 客户端必须生成所需的全部订阅者, 并在相应的发布者处完成注册工作。 **C++ 中使用示例:** /** * Observer Design Pattern * * Intent: Lets you define a subscription mechanism to notify multiple objects * about any events that happen to the object they're observing. * * Note that there's a lot of different terms with similar meaning associated * with this pattern. Just remember that the Subject is also called the * Publisher and the Observer is often called the Subscriber and vice versa. * Also the verbs "observe", "listen" or "track" usually mean the same thing. */ #include <iostream> #include <list> #include <string> class IObserver { public: virtual ~IObserver(){ }; virtual void Update(const std::string &message_from_subject) = 0; }; class ISubject { public: virtual ~ISubject(){ }; virtual void Attach(IObserver *observer) = 0; virtual void Detach(IObserver *observer) = 0; virtual void Notify() = 0; }; /** * The Subject owns some important state and notifies observers when the state * changes. */ class Subject : public ISubject { public: virtual ~Subject() { std::cout << "Goodbye, I was the Subject.\n"; } /** * The subscription management methods. */ void Attach(IObserver *observer) override { list_observer_.push_back(observer); } void Detach(IObserver *observer) override { list_observer_.remove(observer); } void Notify() override { std::list<IObserver *>::iterator iterator = list_observer_.begin(); HowManyObserver(); while (iterator != list_observer_.end()) { (*iterator)->Update(message_); ++iterator; } } void CreateMessage(std::string message = "Empty") { this->message_ = message; Notify(); } void HowManyObserver() { std::cout << "There are " << list_observer_.size() << " observers in the list.\n"; } /** * Usually, the subscription logic is only a fraction of what a Subject can * really do. Subjects commonly hold some important business logic, that * triggers a notification method whenever something important is about to * happen (or after it). */ void SomeBusinessLogic() { this->message_ = "change message message"; Notify(); std::cout << "I'm about to do some thing important\n"; } private: std::list<IObserver *> list_observer_; std::string message_; }; class Observer : public IObserver { public: Observer(Subject &subject) : subject_(subject) { this->subject_.Attach(this); std::cout << "Hi, I'm the Observer \"" << ++Observer::static_number_ << "\".\n"; this->number_ = Observer::static_number_; } virtual ~Observer() { std::cout << "Goodbye, I was the Observer \"" << this->number_ << "\".\n"; } void Update(const std::string &message_from_subject) override { message_from_subject_ = message_from_subject; PrintInfo(); } void RemoveMeFromTheList() { subject_.Detach(this); std::cout << "Observer \"" << number_ << "\" removed from the list.\n"; } void PrintInfo() { std::cout << "Observer \"" << this->number_ << "\": a new message is available --> " << this->message_from_subject_ << "\n"; } private: std::string message_from_subject_; Subject &subject_; static int static_number_; int number_; }; int Observer::static_number_ = 0; void ClientCode() { Subject *subject = new Subject; Observer *observer1 = new Observer(*subject); Observer *observer2 = new Observer(*subject); Observer *observer3 = new Observer(*subject); Observer *observer4; Observer *observer5; subject->CreateMessage("Hello World! :D"); observer3->RemoveMeFromTheList(); subject->CreateMessage("The weather is hot today! :p"); observer4 = new Observer(*subject); observer2->RemoveMeFromTheList(); observer5 = new Observer(*subject); subject->CreateMessage("My new car is great! ;)"); observer5->RemoveMeFromTheList(); observer4->RemoveMeFromTheList(); observer1->RemoveMeFromTheList(); delete observer5; delete observer4; delete observer3; delete observer2; delete observer1; delete subject; } int main() { ClientCode(); return 0; } output: Hi, I'm the Observer "1". Hi, I'm the Observer "2". Hi, I'm the Observer "3". There are 3 observers in the list. Observer "1": a new message is available --> Hello World! :D Observer "2": a new message is available --> Hello World! :D Observer "3": a new message is available --> Hello World! :D Observer "3" removed from the list. There are 2 observers in the list. Observer "1": a new message is available --> The weather is hot today! :p Observer "2": a new message is available --> The weather is hot today! :p Hi, I'm the Observer "4". Observer "2" removed from the list. Hi, I'm the Observer "5". There are 3 observers in the list. Observer "1": a new message is available --> My new car is great! ;) Observer "4": a new message is available --> My new car is great! ;) Observer "5": a new message is available --> My new car is great! ;) Observer "5" removed from the list. Observer "4" removed from the list. Observer "1" removed from the list. Goodbye, I was the Observer "5". Goodbye, I was the Observer "4". Goodbye, I was the Observer "3". Goodbye, I was the Observer "2". Goodbye, I was the Observer "1". Goodbye, I was the Subject. **C++示例二:** class Observer { public: Observer() { } virtual ~Observer() { } virtual void Update() { } }; class Subject { public: Subject() { } virtual ~Subject() { } void AttachObserver(Observer *observer) { m_observer.push_back(observer); } void RemoveObserver(Observer *observer) { m_observer.remove(observer); } void NotifyObserver() // 通知观察者 { for (auto iter = m_observer.begin(); iter != m_observer.end(); iter++) { *iter->Update(); } } virtual void SetStatus(string s) { m_status = s;} virtual string GetStatus() { return m_status;} protected: string m_status; private: list<Observer*> m_observer; }; class Newspaper : public Subject { public: Newspaper(string name) : m_name(name) { } ~Newspaper() override { } void SetStatus(string s) override { m_status = "Newspaper notify :" + m_name + s; } string GetStatus() override { return m_status; } private: string m_name; }; class Reader : public Observer { public: Reader(string name, Subject *subject) : m_name(name), m_subject(subject) { } ~Reader() override { } void Update() override { string status = m_subject->GetStatus(); cout << m_name << "------" << status << endl; } private: string m_name; // 观察者名称 Subject *m_subject; // 观察的新闻 }; // test demo int main() { Subject *newspaper = new Newspaper("fox"); Observer *observer1 = new Reader("tom", newspaper) newspaper->AttachObserver(observer1); newspaper->SetStatus("say trump is a joke !"); newspaper->NotifyObserver(); delete newspaper; delete observer1; return 0; } [20201202143841369.png_pic_center]: /images/20221120/6016a4397eab4ff99bbed002f363e6ac.png
相关 观察者改变被观察者的状态_调整观察者大小 观察者改变被观察者的状态 Creating websites that are reactive and responsive used to be considered a 我不是女神ヾ/ 2023年02月21日 14:29/ 0 赞/ 25 阅读
相关 java 观察者模型_Java-观察者模式 观察者模式(有时又被称为模型(Model)-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于 以你之姓@/ 2022年11月11日 14:53/ 0 赞/ 232 阅读
相关 观察者模式 观察者模式 Observer 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态上发生变化时,会通知所有观察者对 梦里梦外;/ 2022年08月03日 08:20/ 0 赞/ 47 阅读
相关 观察者模式 什么是观察者模式 有人这么说 > 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 > > 这个主题对象在状态上发生变化时,会通知所有观 梦里梦外;/ 2022年07月20日 12:05/ 0 赞/ 303 阅读
相关 观察者模式 场景描述: 一个气象站应用,可以实时获取温度、湿度和气压信息,气象站提供一个封装好的类WeatherData,该类有最新的气象信息,当这些信息发生变动的时候,类中的meas 叁歲伎倆/ 2022年06月14日 10:24/ 0 赞/ 197 阅读
相关 观察者模式 观察者模式:定义了对象之间的一对多的依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新。 观察者模式图: ![输入图片说明][13105107_Mf 旧城等待,/ 2022年06月03日 02:41/ 0 赞/ 300 阅读
相关 观察者模式 什么是观察者模式? 简单的来说,观察者模式=出版者+订阅者。用比较书面的话来说的话是:定义了对象之间的一对多依赖,当一所对应的对象状态改变时,它的所有依赖者都会收到通知并 你的名字/ 2022年02月01日 13:53/ 0 赞/ 427 阅读
相关 观察者模式 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 意图:定义对象 系统管理员/ 2021年09月17日 01:36/ 0 赞/ 513 阅读
相关 观察者模式 对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。观察者模式属于行为型模式。 介绍 ... 小灰灰/ 2020年06月13日 05:42/ 0 赞/ 607 阅读
还没有评论,来说两句吧...