Chapter14 观察者模式

观察者模式简介

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生时,会通知所有观察者对象,使得他们能够自动更新自己。

观察者模式的动机:将一个系统分隔成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象之间的一致性。我们不希望为了维护一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。而观察者模式关键主题对象是Subject和观察者observer,一个Subject可以有任意数目的依赖它的Observer,一旦Subject的状态发生了改变,所有的Observer都可以得到通知。Subject发出通知时并不需要知道谁是它的观察者。也就是说,具体观察者是谁,它根本不需要知道。而任何一个具体观察者不知道也不需要知道其他观察者的存在。

当一个对象的改变需要同时改变其他对象的时候,观察者模式就派上了用场。

如果一个抽象模型有两个方面,其中一方面依赖于另一方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。

观察者模式所做的工作其实就是在解耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化。

观察者模式的不足

观察者模式需要每个观察者都实现一个Observer接口。但可能并没有提供Observer接口。或者说,通知者和观察者之间根部就互相不知道。那么由客户端来决定通知谁,就能解决这个问题(事件委托)。

事件委托就是一种引用方法的类型。委托就是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和范围值。委托可以看做是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。并且一个委托可以搭载多了方法,所有方法被依次唤起。更重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类。

委托的前提是委托对象所搭载的所有方法必须具有相同的原型和形式,也就是拥有相同的参数列表和返回值类型。

观察者模式UML类图

C++代码实现

//Observer类,只是一个抽象接口
#ifndef _OBSERVER_HPP
#define _OBSERVER_HPP

using namespace std;

class Observer{
public:
    virtual void update()  = 0;
   
};

#endif
// Subject类,只是一个抽象接口
#ifndef _SUBJECT_HPP
#define _SUBJECT_HPP

#include"observer.hpp"

using namespace std;

class Subject{
public:
    virtual void attach(Observer* obs)=0;
    virtual void detach(Observer* obs) = 0;
    virtual void notify() = 0;
};

#endif
//ConcreteObserver类
#ifndef _CONCRETEOBSERVER_HPP
#define _CONCRETEOBSERVER_HPP
#include<string>
#include"observer.hpp"
#include"concretesubject.hpp"
#include<iostream>
using namespace std;
class ConcreteObserver:public Observer{

public:
    ConcreteObserver(const string& name,ConcreteSubject* conSub)
    :name(name),subject(conSub){

     }
    virtual void update()override{
        observerState = subject->getSubjectState();
        cout <<"name:"<< name <<endl;
        cout << "state:" << observerState<<endl;  
    } 

   bool operator==(const ConcreteObserver& obs){
        return this->name == obs.name; 
    }
private:
    string name; 
    string observerState;        
    ConcreteSubject* subject;

};

#endif
//ConcreteSubject类
#ifndef _CONCRETESUBJECT
#define _CONCRETESUBJECT

#include"subject.hpp"
#include"observer.hpp"
#include<string>
#include<list>

using namespace std;

class ConcreteSubject:public Subject{
public:
    virtual void attach(Observer* obs)override{
        l.push_back(obs);
    }
    virtual void detach(Observer* obs)override{
        l.remove_if([&](Observer*tmp){return tmp == obs;});
    }
    
    virtual void notify()override{
        for(auto i : l){
            i->update();
        }
    }
    string getSubjectState(){
        return subjectstate; 
    }
    void setSubjectState(string str){
        subjectstate = str;
    }
 
private:
    string subjectstate;
    list<Observer*> l;
};

#endif

//客户端程序
#include<iostream>
#include"concretesubject.hpp"
#include"concreteobserver.hpp"
using namespace std;
int main(){
    ConcreteSubject* conSubject = new ConcreteSubject();

    ConcreteObserver* conObs = new ConcreteObserver("xiaoming",conSubject);
    ConcreteObserver* conObs1 = new ConcreteObserver("wanger",conSubject);
    ConcreteObserver* conObs2 = new ConcreteObserver("zhangsan",conSubject);
    
    conSubject->attach(dynamic_cast<Observer*>(conObs));
    conSubject->attach(dynamic_cast<Observer*>(conObs1));
    conSubject->attach(dynamic_cast<Observer*>(conObs2));
    conSubject -> detach(dynamic_cast<Observer*>(conObs1));

    conSubject->setSubjectState("Boss is coming"); 
    conSubject->notify();

    getchar();
    return 0;

运行结果:

 

posted @ 2020-03-23 10:45  yangbofun  阅读(221)  评论(0)    收藏  举报