观察者模式
首先看一下他的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
然后看一下菜鸟教程的有缺点
优点: 1、观察者和被观察者是抽象耦合的。 2、建立一套触发机制。
缺点: 1、如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。 2、如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。 3、观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
使用场景:
一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这些方面封装在独立的对象中使它们可以各自独立地改变和复用。
一个对象的改变将导致其他一个或多个对象也发生改变,而不知道具体有多少对象将发生改变,可以降低对象之间的耦合度。
一个对象必须通知其他对象,而并不知道这些对象是谁。
需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象……,可以使用观察者模式创建一种链式触发机制。
观察者模式的主要角色如下。
抽象主题
(Subject)角色:也叫抽象目标类,它提供了一个用于保存观察者对象的聚集类和增加、删除观察者对象的方法,以及通知所有观察者的抽象方法。
具体主题
(Concrete Subject)角色:也叫具体目标类,它实现抽象目标中的通知方法,当具体主题的内部状态发生改变时,通知所有注册过的观察者对象。
抽象观察者
(Observer)角色:它是一个抽象类或接口,它包含了一个更新自己的抽象方法,当接到具体主题的更改通知时被调用。
具体观察者
(Concrete Observer)角色:实现抽象观察者中定义的抽象方法,以便在得到目标的更改通知时更新自身的状态。
简单实现
#include <iostream>
#include <string>
#include <list>
using namespace std;
class IObserver
{
public:
virtual ~IObserver() {}
int num;
IObserver(string name){this->num = 0;this->name = name;}
string name;
virtual void up() = 0;
};
class Observer:public IObserver
{
public:
Observer(string name):IObserver(name){}
void up(){this->num++;}
};
class ISubject
{
public:
list<IObserver *> observers;
virtual void register_observer(IObserver *) = 0;
virtual void remove_observer(IObserver *) = 0;
virtual void clear_observer() = 0;
virtual void test() = 0;
virtual ~ISubject()
{
while (!observers.empty()) {
cout<<"delete "<<observers.front()->name<<endl;
IObserver *temp = observers.front();
observers.pop_front();
delete temp;
}
}
};
class Subject:public ISubject
{
public:
void register_observer(IObserver *observer){this->observers.push_back(observer);}
void remove_observer(IObserver *observer){this->observers.remove(observer);}
void clear_observer(){this->observers.clear();}
void test()
{
list<IObserver *>::iterator temp;
for (temp = this->observers.begin() ; temp != observers.end(); ++temp) {
(*temp)->up();
cout<<(*temp)->name<<":"<<(*temp)->num<<endl;
}
}
};
int main(int argc, const char * argv[]) {
Subject subject;
IObserver *observer = new Observer("A");
subject.register_observer(observer);
observer->up();
subject.register_observer(new Observer("B"));
subject.register_observer(new Observer("C"));
subject.test();
return 0;
}
A:2
B:1
C:1
delete A
delete B
delete C
Program ended with exit code: 0