当对象间存在一对多关系时,则使用观察者模式(observer pattern)。比如,当一个对象被修改时,则会自动通知发依赖它的对象。观察者模式属于行为型模式。
Observer模式是应用最多、影响最广的设计模式之一,因为Observer的一个实例Model/View/Control(MVC)结构在系统开发架构设计中有着很重要的地位和意义,MVC实现了业务逻辑和表示层的解耦。在MFC(微软基础类库)中,Doc/View(文档视图结构)提供了实现MVC的框架结构。
在GOF的《设计模式:可复用面向对象软件的基础》一书中对观察者模式是这样定义的:定义对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。当一个对象发生了变化,关注它的对象就会得到通知;这种交互也成为发布-订阅(publish-subscribe)。
MVC框架是模型-视图-控制器的缩写,一种软件设计典范。用一种业务逻辑、数据、显示界面分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能。在一个逻辑的图形化用户界面的结构中MVC分层有助于管理复杂的应用程序,因为可以在一个时间内专注的关注一个方面,可以在不依赖业务逻辑的情况下专注于视图设计,同时也将应用程序的测试更加容易。
意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。
主要解决:一个对象状态改变并给其它对象通知的问题,而且要考虑到易用和低耦合,保证高度的协作。
何时使用:一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知,进行广播通知。
如何解决:使用面向对象技术,可以将这种依赖关系弱化。
关键代码:在抽象类里有一个arrayList存放观察者们。
应用实例:1、拍卖的时候,拍卖师观察最高价格,然后通知给其它竞价者竞价。2、西游记里面悟空请求菩萨降服红孩儿,菩萨洒了一地水找来一个老乌龟,这个老乌龟就是观察者(菩萨是被观察者),他观察菩萨这个动作。
优点:1、观察者和被观察者是抽象耦合的。2、建立一套触发机制。
缺点:1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
注意事项:1、应避免循环引用。2、如果顺序执行,某一观察者错误会导致系统卡壳,一般采用异步方式(多线程)。
对同一组数据进行统计分析的时候,我们希望能够提供多种形式的表示(例如以表格形式进行显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有统计的显示都能同时改变、Observer模式就是解决了这一个问题。
观察者模式按照以下方式进行协作:
代码实现:
#include
#include
using std::cout;
using std::endl;
using std::cin;
class Observer
{
public:
virtual ~Observer() {};
virtual void Update(int) = 0;
};
class Subject
{
public:
virtual ~Subject() {};
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;
};
class ConcreteObserver : public Observer
{
private:
Subject *_pSubject;
public:
ConcreteObserver(Subject* pSubject) :_pSubject(pSubject)
{
//在目标中注册当前观察者(此处的观察者是广义上的观察者,目标并不知道具体谁要观察它,目标只进行广播即可)
this->_pSubject->Attach(this);
cout << "I'm the observer \" 1 \".\n";
}
void Update(int value) override
{
cout << "ConcreteObserver get the update.New State:" << value << endl;
}
};
class ConcreteObserver2 : public Observer
{
private:
Subject *_pSubject;
public:
ConcreteObserver2(Subject* pSubject) :_pSubject(pSubject)
{
//在目标中注册当前观察者(此处的观察者是广义上的观察者,目标并不知道具体谁要观察它,目标只进行广播即可)
this->_pSubject->Attach(this);
cout << "I'm the observer \" 2 \".\n";
}
void Update(int value) override
{
cout << "ConcreteObserver2 get the update.New State:" << value << endl;
}
};
class ConcreteSubject :public Subject
{
private:
std::list<Observer*> _pObserverList;
int _iState;
public:
void SetState(int state)
{
_iState = state;
}
void Attach(Observer* pObserver) override
{
_pObserverList.push_back(pObserver);
}
void Detach(Observer* pObserver) override
{
_pObserverList.remove(pObserver);
}
void Notify() override
{
auto begin = _pObserverList.begin();
auto end = _pObserverList.end();
while (begin != end)
{
(*begin)->Update(_iState);
begin++;
}
}
};
int main()
{
//创建目标
ConcreteSubject *pSubject = new ConcreteSubject();
//创建观察者
Observer *pObserver = new ConcreteObserver(pSubject);
Observer *pObserver2 = new ConcreteObserver2(pSubject);
//改变当前状态
pSubject->SetState(2);
//广播给所有广义上的观察者
pSubject->Notify();
//去除某个观察者
pSubject->Detach(pObserver);
//改变当前状态
pSubject->SetState(3);
//重新广播
pSubject->Notify();
//结束,释放对象
delete pObserver;
delete pObserver2;
delete pSubject;
return 0;
}
输出结果(vs2017):
#include
#include
#include
using std::cout;
using std::endl;
using std::cin;
/*
观察者模式有许多具有类似含有的不同术语,比如主题也成为发布者,观察者通常称为订阅者。
动词“观察”、“倾听”或“跟踪”通常表示相同的意思。
*/
class IObserver
{
public:
virtual ~IObserver() {}
virtual void Update(const std::string &messageFromSubject) = 0;
};
class ISubject
{
public:
virtual ~ISubject() {}
virtual void Attach(IObserver *observer) = 0;
virtual void Detach(IObserver *observer) = 0;
virtual void Notify() = 0;
};
//具体目标拥有一些重要的状态,并在状态更改时通知观察者
class Subject : public ISubject
{
private:
std::list<IObserver *> _listObserver;
std::string _messgae;
public:
virtual ~Subject()
{
cout << "Goodbye,I was the Subject.\n";
}
//定义订阅管理方法
void Attach(IObserver* observer) override
{
_listObserver.push_back(observer);
}
void Detach(IObserver* observer) override
{
_listObserver.remove(observer);
}
void Notify() override
{
std::list<IObserver *>::iterator begin = _listObserver.begin();
HowManyObserver();
while (begin != _listObserver.end())
{
(*begin)->Update(_messgae);
++begin;
}
}
void CreateMessage(std::string message = "Empty")
{
this->_messgae = message;
Notify();
}
void HowManyObserver()
{
cout << "There are " << _listObserver.size() << " observers in the list\n";
}
/*
通常的来说,订阅逻辑知识主题真正能做的事情的一小部分。
主题通常拥有一些重要的业务逻辑,每当重要的事情即将发生(或者发生之后)时触发通知方法。
*/
void SomeBusinessLogic()
{
this->_messgae = "change message message";
Notify();
cout << "I'm about to do some thing important.\n";
}
};
class Observer :public IObserver
{
private:
std::string _messageFromSubject;
Subject &_subject;
static int _staticNumber;
int _number;
public:
Observer(Subject &subject) :_subject(subject)
{
this->_subject.Attach(this);
cout << "Hi,I'm the Observer \"" << ++Observer::_staticNumber << "\".\n";
this->_number = Observer::_staticNumber;
}
~Observer()
{
cout << "Goodbye, I was the Observer \"" << this->_number << "\".\n";
}
void Update(const std::string &messageFromSubject) override
{
this->_messageFromSubject = messageFromSubject;
PrintInfo();
}
void RemoveMeFromTheList()
{
this->_subject.Detach(this);
cout << "Observer \"" << this->_number << "\" removed from the list.\n";
}
void PrintInfo()
{
cout << "Observer \"" << this->_number << "\": a new message is aviilable -->" << this->_messageFromSubject << "\n";
}
};
int Observer::_staticNumber = 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);
observer4->RemoveMeFromTheList();
observer1->RemoveMeFromTheList();
delete observer5;
delete observer4;
delete observer3;
delete observer2;
delete observer1;
delete subject;
}
int main()
{
ClientCode();
return 0;
}
输出结果(vs2017):
https://www.runoob.com/design-pattern/observer-pattern.html
https://www.cnblogs.com/carsonzhu/p/5770253.html