设计模式--观察者模式(C++)

一、什么是观察者模式

Observer模式也叫观察者模式,是由GoF提出的23种软件设计模式的一种。Observer模式是行为模式之一,它的作用是当一个对象的状态发生变化时,能够自动通知其他关联对象,自动刷新对象状态。

  观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。

  观察者模式有很多实现方式,从根本上说,该模式必须包含两个角色:观察者和被观察对象。在刚才的例子中,业务数据是被观察对象,用户界面是观察者。观察者和被观察者之间存在“观察”的逻辑关联,当被观察者发生改变的时候,观察者就会观察到这样的变化,并且做出相应的响应。如果在用户界面、业务数据之间使用这样的观察过程,可以确保界面和数据之间划清界限,假定应用程序的需求发生变化,需要修改界面的表现,只需要重新构建一个用户界面,业务数据不需要发生变化。

  “观察”不是“直接调用”

  实现观察者模式的时候要注意,观察者和被观察对象之间的互动关系不能体现成类之间的直接调用,否则就将使观察者和被观察对象之间紧密的耦合起来,从根本上违反面向对象的设计的原则。无论是观察者“观察”观察对象,还是被观察者将自己的改变“通知”观察者,都不应该直接调用。

  实现观察者模式的形式

  实现观察者模式有很多形式,比较直观的一种是使用一种“注册——通知——撤销注册”的形式。

 

  1. /************************************************************************/
  2. /* 观察者模式 */
  3. /************************************************************************/
  4. #include <LIST>
  5. #include <STRING>
  6. #include <iostream>
  7. using namespace std;
  8. /*
  9. 编程要点:观察者接口要有一个更新自身状态的行为
  10. 被观察者(主题):要有一个存放与之相联系的观察者的链表,并有一个通知的行为,当被观察者的状态发生改变时,
  11. 它会通知所有与之相关联地具体观察者,即调用与之关联的观察者的Update方法
  12. */
  13. class Subject;
  14. //观察者接口(抽象)
  15. class Observer{
  16. public:
  17. virtual ~Observer(){};
  18. virtual void Update(Subject *concreteSubject){};//根据被观察者更新自身状态
  19. };
  20. //被观察者(主题)
  21. class Subject
  22. {
  23. private:
  24. list<Observer*> *obvs;
  25. public:
  26. //构造函数
  27. Subject()
  28. {
  29. obvs = new list<Observer*>;
  30. }
  31. void Attach(Observer *observer)
  32. {
  33. obvs->push_front(observer);//向链表中加入一个待通知的观察者
  34. }
  35. void Detach(Observer *observer)
  36. {
  37. obvs->push_back(observer);//删除一个观察者
  38. }
  39. //通知每个观察者
  40. void Notify()
  41. {
  42. list<Observer*>::iterator it;
  43. it = obvs->begin();
  44. for(;it!=obvs->end();it++){
  45. (*it)->Update(this);//每个观察者被通知后更新自己的状态
  46. }
  47. }
  48. public:
  49. virtual char* getState(){return NULL;}
  50. virtual void setState(){}
  51. };
  52. /*具体的主题*/
  53. class ConcreteSubject : public Subject
  54. {
  55. private:
  56. char *state;//被观察者的状态
  57. public:
  58. /*被观察者自身状态的设置与获取*/
  59. char* getState()
  60. {
  61. return state;
  62. }
  63. void setState(char *state)
  64. {
  65. this->state = state;
  66. }
  67. };
  68. //具体的观察者
  69. class ConcreteObserverA : public Observer
  70. {
  71. private:
  72. char *name;//名称
  73. char *state;//状态
  74. public:
  75. ConcreteObserverA(char *name)
  76. {
  77. this->name = name;
  78. }
  79. void Update(Subject *concreteSubject)
  80. {
  81. state = concreteSubject->getState();//更新自身状态
  82. cout<<"观察者:"<<name<<"的新状态是:"<<state<<endl;
  83. }
  84. };
  85. void main()
  86. {
  87. //构造一个主题
  88. ConcreteSubject *concreteSubject = new ConcreteSubject();
  89. //让主题和观察者相联系
  90. concreteSubject->Attach(new ConcreteObserverA("X"));
  91. concreteSubject->Attach(new ConcreteObserverA("Y"));
  92. //主题状态改变,并通知观察者
  93. concreteSubject->setState("老师走了,大家可以玩了,哈哈");
  94. concreteSubject->Notify();
  95. printf("过了一段时间后........................\n");
  96. //主题状态改变,再次通知观察者
  97. concreteSubject->setState("老师来了,大家别说了");
  98. concreteSubject->Notify();
  99. }
/************************************************************************/
/*                            观察者模式                                */
/************************************************************************/

#include <LIST>
#include <STRING>
#include <iostream>


using namespace std;



/*
	编程要点:观察者接口要有一个更新自身状态的行为

	被观察者(主题):要有一个存放与之相联系的观察者的链表,并有一个通知的行为,当被观察者的状态发生改变时,
	它会通知所有与之相关联地具体观察者,即调用与之关联的观察者的Update方法

*/


class Subject;

//观察者接口(抽象)
class Observer{
public:
	virtual ~Observer(){};
	virtual void Update(Subject *concreteSubject){};//根据被观察者更新自身状态
	
};




//被观察者(主题)
class Subject
{
private:
	list<Observer*> *obvs;
	
public:
	//构造函数
	Subject()
	{
		obvs = new list<Observer*>;
	}
	
	void Attach(Observer *observer)
	{
		obvs->push_front(observer);//向链表中加入一个待通知的观察者
	}
	
	void Detach(Observer *observer)
	{
		obvs->push_back(observer);//删除一个观察者
	}
	
	//通知每个观察者
	void Notify()
	{
		list<Observer*>::iterator it;
		it = obvs->begin();
		for(;it!=obvs->end();it++){
			(*it)->Update(this);//每个观察者被通知后更新自己的状态
		}
	}



public:
	virtual char* getState(){return NULL;}

	virtual void setState(){}

};



/*具体的主题*/
class ConcreteSubject : public Subject
{
private:
	char *state;//被观察者的状态
	
public:
	/*被观察者自身状态的设置与获取*/
	char* getState()
	{
		return state;
	}
	
	void setState(char *state)
	{
		this->state = state;
	}
};











//具体的观察者
class ConcreteObserverA : public Observer
{
private:
	char *name;//名称
	char *state;//状态

public:
	ConcreteObserverA(char *name)
	{
		this->name = name;
	}

	void Update(Subject *concreteSubject)
	{
		state = concreteSubject->getState();//更新自身状态
		cout<<"观察者:"<<name<<"的新状态是:"<<state<<endl;
	}
	
};






void main()
{
	//构造一个主题
	ConcreteSubject *concreteSubject = new ConcreteSubject();



	//让主题和观察者相联系
	concreteSubject->Attach(new ConcreteObserverA("X"));
	concreteSubject->Attach(new ConcreteObserverA("Y"));


	//主题状态改变,并通知观察者
	concreteSubject->setState("老师走了,大家可以玩了,哈哈");
	concreteSubject->Notify();


	printf("过了一段时间后........................\n");

	//主题状态改变,再次通知观察者
	concreteSubject->setState("老师来了,大家别说了");
	concreteSubject->Notify();

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
观察者模式(Observer Pattern)是一种行为型设计模式,它允许一个对象(称为主题或可观察者)在状态变化时通知其他多个对象(称为观察者)。这个模式主要用于解耦主题和观察者,使它们能够独立地进行修改和扩展。 在观察者模式中,主题维护一个观察者列表,可以动态地添加或移除观察者。当主题的状态发生变化时,它会遍历观察者列表,并调用每个观察者的更新方法,将状态变化的信息传递给观察者。观察者可以根据接收到的信息做出相应的操作。 以下是一个简单的示例代码,演示了观察者模式的实现: ```c #include <iostream> #include <vector> // 观察者接口 class Observer { public: virtual void update(int data) = 0; }; // 具体观察者 A class ConcreteObserverA : public Observer { public: void update(int data) override { std::cout << "ConcreteObserverA received: " << data << std::endl; } }; // 具体观察者 B class ConcreteObserverB : public Observer { public: void update(int data) override { std::cout << "ConcreteObserverB received: " << data << std::endl; } }; // 主题 class Subject { private: int data; std::vector<Observer*> observers; public: void attach(Observer* observer) { observers.push_back(observer); } void detach(Observer* observer) { // 从观察者列表中删除观察者 // ... } void notify() { for (Observer* observer : observers) { observer->update(data); } } void setData(int value) { data = value; notify(); } }; int main() { Subject subject; ConcreteObserverA observerA; ConcreteObserverB observerB; subject.attach(&observerA); subject.attach(&observerB); subject.setData(42); return 0; } ``` 在上述示例中,`Subject` 是主题类,维护了一个观察者列表。`Observer` 是观察者接口,定义了一个 `update` 方法用于接收主题的通知。`ConcreteObserverA` 和 `ConcreteObserverB` 是具体的观察者类,实现了 `update` 方法。 在 `main` 函数中,我们创建了一个主题对象 `subject` 和两个观察者对象 `observerA` 和 `observerB`。通过调用 `attach` 方法,将观察者对象添加到主题的观察者列表中。然后,通过调用 `setData` 方法改变主题的状态,并自动通知所有观察者。 当 `subject.setData(42)` 被调用时,观察者 `observerA` 和 `observerB` 的 `update` 方法会被依次调用,输出相应的信息。 这就是观察者模式的基本实现。通过使用观察者模式,主题和观察者之间的耦合性降低,可以方便地扩展和修改代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值