【设计模式】观察者模式 Observer Pattern

什么是观察者模式?

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

背景

很多时候, 在应用程序的一部分发生改变时, 需要同时更新应用程序的其他部分。 一种办法是, 让观察者定期反复检查主题对象的状态来进行更新, 但这种办法存在两个主要的问题:

  1. 占用大量的cpu时间来检测新的状态, 造成资源浪费
  2. 依赖于检测更新的时间间隔, 更新没有及时性

观察者模式可以解决这些问题。

如何实现

观察者模式中有如下角色:

  • 抽象主题(Subject ): 被观察的对象, 抽象主题把他所有的观察者都保存在一个集合里(list), 每个主题可以有任意数量的观察者。 抽象主题需要提供添加和删除观察者的接口。抽象主题需要声明通知方法, 如notify(), 用于在自身状态发生改变时通知所有的观察者。
  • 具体主题(ConcreteSubject ):抽象主题的子类,
  • 抽象观察者(Observer): 声明了更新数据的方法, 如update(), 对主题对象的变化做出更新反应。
  • 具体观察者(ConcreteObserver): 抽象观察者的子类, 实现了更新方法。 具体观察者中维护了一个具体主题对象的指针, 用于获取主题对象的信息来更新自己的状态。

c++ 代码

class Observer;

class Subject
{
	public: 
		virtual void attach(Observer*) = 0;
		virtual void detach(Observer*) = 0;
		virtual void notify() = 0;
	protected:
		std::list<Observer*> observerList;
};

class Observer
{
	public:
		virtual Observer(Subject* sub): subject(sub){};
		virtual void update() = 0;
	protected:
		Subject* subject;	
};

class ConcreteSubject: public Subject
{
 	public: 
		void attach(Observer*) ;
		void detach(Observer*) ;
		void notify();
		
		void setStatus(const string&);
		string getStatus();		
		
	private:
		string status;
};

void ConcreteSubject::attach(Observer* observer)
{
	observerList.push_back(observer);
} 

void ConcreteSubject::detach(Observer* observer)
{
	observerList.remove(observer);
}

void ConcreteSubject::notify()
{
	for(auto i : observerList)
	{
		observer->update();
	}
}

void ConcreteSubject::setStatus(const string& s)
{
	status = s;
}

string Concretesubject::getStatus()
{
	return status;
}

class ConcreteObserver
{
	public: 
		ConcreteObserver(Subject* sub):Observer(sub){};
		void update(){
			cout<<"updates: "<<subject->getStatus()<<endl;
			};

};

变形

观察者对象中可以维护一个主题对象的指针, 这样的话, 观察者内部可以调用主题对象的函数获取信息(一个或者多个)来更新自己。 但这不是必须的。

另外一种选择是, 观察者对象不需要维护主题对象。 当主题对象状态发生改变时,主题对象调用notify()函数通知观察者对象, 此时可以将观察者需要的信息以参数的形式传给观察者的update(). 观察者根据参数来更新自己, 不需要拥有或者知道主题对象的存在。

拓展

在现实生活中, 一个观察者有可能同时观察两个或以上对象(两种不同的报纸, 或者一个报纸, 一个杂志), 这些主题对象可能是同一类, 也可能是不同类。 根据不同主题的变化, 观察者所需要更新的内容也不尽相同。 该如何设计?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值