观察者模式是一种行为型模式
优点:
- 松散耦合:观察者模式提供了一种松散耦合的设计,使得当一个对象的状态发生变化时,它不需要知道其他对象是如何使用这些信息的。这使得系统更容易扩展和维护。
- 动态关联:观察者模式允许在运行时动态地添加或删除观察者,而无需修改主题或其他观察者的代码。
- 抽象耦合:由于主题和观察者之间仅通过抽象接口进行通信,因此它们之间的耦合是抽象的,而不是具体的。
缺点:
- 可能导致意外的更新:如果一个观察者在接收到通知后执行了一些操作,这些操作又导致了主题状态的变化,那么就可能会导致意外的更新。
- 可能导致性能问题:如果有大量的观察者需要更新,那么通知所有观察者可能会导致性能问题。
- 可能增加复杂性:如果没有正确实现,观察者模式可能会增加系统的复杂性。
满足的设计原则:
- 单一职责原则(SRP):观察者模式允许将观察者和被观察者分离,使它们能够独立更改和复用。这样,每个类都只需要关注自己的职责,而不需要关心其他类的实现细节。
- 开放封闭原则(OCP):观察者模式允许在不修改现有代码的情况下添加新的观察者。这样,系统可以在不影响现有功能的情况下扩展。
- 依赖倒置原则(DIP):观察者模式中,主题和观察者之间仅通过抽象接口进行通信,而不是直接依赖于具体实现。
- 这样,高层模块(被观察者)不依赖于低层模块(观察者),而是依赖于抽象接口。
常用实例:
- 当一个对象的状态发生变化时,需要通知其他对象。例如,在文本编辑器中,当用户在文本框中输入文本时,文本框会通知其他组件(如字数统计器或拼写检查器)更新其状态。
- 当一个对象的状态发生变化时,需要执行一些动作。例如,在电子商务网站中,当用户将商品添加到购物车时,购物车会通知库存管理系统更新库存。
- 当需要在多个对象之间实现松散耦合的设计时。例如,在MVC架构中,模型(Model)会通知视图(View)更新其显示内容,但模型并不需要知道视图是如何使用这些信息的。
类图:
代码:
#include "iostream"
#include "string"
#include <list>
using namespace std;
class Observer;
//抽象被观察者
class Subject
{
public:
Subject():m_nState(0){}
virtual ~Subject()=default;
//增加观察者
virtual void Attach(Observer* pObserver)=0;
//移除观察者
virtual void Detach(Observer* observer)=0;
//通知
virtual void Notify()=0;
virtual int GetState()
{
return m_nState;
}
void SetState(int state)
{
cout<<"Subjeceet updated!"<<endl;
m_nState =state;
}
list<Observer*> m_pObserver_list;
int m_nState;
};
//抽象观察者
/*
*/
class Observer
{
public:
virtual ~Observer()=default;
Observer( Subject* pSubject,const string &name="unknown"):m_pSubject(pSubject),m_strName(name){}
virtual void Update()=0;
virtual const string& name()
{
return m_strName;
}
protected:
Subject *m_pSubject;
string m_strName;
};
//具体被观察者
class ConcreteSubject :public Subject
{
public:
void Attach(Observer* pObserver)
{
cout<<"Attach observer"<<pObserver->name()<<endl;
m_pObserver_list.push_back(pObserver);
};
void Detach(Observer* pObserver)
{
cout<<"Detach observer"<<pObserver->name()<<endl;
m_pObserver_list.remove(pObserver);
};
void Notify()
{
for (list<Observer*>::iterator iter = m_pObserver_list.begin(); iter != m_pObserver_list.end(); ++iter)
{
(*iter)->Update();
}
}
};
//具体观察者1
class Observer1 :public Observer
{
public:
Observer1(Subject*pSubject,const string& name="unknown"):Observer(pSubject,name){}
void Update()
{
cout<<"Observer1_"<<m_strName<<"get the upda.new state is:"<<m_pSubject->GetState()<<endl;
};
};
//具体观察者2
class Observer2 :public Observer
{
public:
Observer2(Subject* pSubject, const string& name = "unknown") :Observer(pSubject, name) {}
void Update()
{
cout << "Observer2_" << m_strName << "get the upda.new state is:" << m_pSubject->GetState() << endl;
};
};
int main()
{
Subject *pSubject=new ConcreteSubject;
Observer *pObserver_1=new Observer1(pSubject,"1");
Observer *pObserver_2=new Observer1(pSubject,"2");
Observer* pObserver_3 = new Observer2(pSubject, "3");
Observer* pObserver_4 = new Observer2(pSubject, "4");
//注册观察者
pSubject->Attach(pObserver_1);
pSubject->Attach(pObserver_2);
pSubject->Attach(pObserver_3);
pSubject->Attach(pObserver_4);
//pSubject->SetState(3);
pSubject->Notify();
return 0;
}