设计模式之观察者模式(Observer)摘录

2023-11-20

23种GOF设计模式一般分为三大类:创建型模式、结构型模式、行为模式。

创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。创建型模式有两个不断出现的主旋律。第一,它们都将关于该系统使用哪些具体的类的信息封装起来。第二,它们隐藏了这些类的实例是如何被创建和放在一起的。整个系统关于这些对象所知道的是由抽象类所定义的接口。因此,创建型模式在什么被创建,谁创建它,它是怎样被创建的,以及何时创建这些方面给予了很大的灵活性。它们允许用结构和功能差别很大的“产品”对象配置一个系统。配置可以是静态的(即在编译时指定),也可以是动态的(在运行时)。

结构型模式涉及到如何组合类和对象以获得更大的结构。结构型类模式采用继承机制来组合接口或实现。结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态类组合是不可能实现的。

行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻画了在运行时难以跟踪的复杂的控制流。它们将用户的注意力从控制流转移到对象间的联系方式上来。行为类模式使用继承机制在类间分派行为。行为对象模式使用对象复合而不是继承。一些行为对象模式描述了一组对等的对象怎样相互协作以完成其中任一个对象都无法单独完成的任务。

创建型模式包括:1、FactoryMethod(工厂方法模式);2、Abstract Factory(抽象工厂模式);3、Singleton(单例模式);4、Builder(建造者模式、生成器模式);5、Prototype(原型模式).

结构型模式包括:6、Bridge(桥接模式);7、Adapter(适配器模式);8、Decorator(装饰模式);9、Composite(组合模式);10、Flyweight(享元模式);11、Facade(外观模式);12、Proxy(代理模式).

行为模式包括:13、TemplateMethod(模板方法模式);14、Strategy(策略模式);15、State(状态模式);16、Observer(观察者模式);17、Memento(备忘录模式);18、Mediator(中介者模式);19、Command(命令模式);20、Visitor(访问者模式);21、Chain of Responsibility(责任链模式);22、Iterator(迭代器模式);23、Interpreter(解释器模式).

Factory Method:定义一个用于创建对象的接口,让子类决定将哪一个类实例化。Factory Method使一个类的实例化延迟到其子类。

Abstract Factory:提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类。

Singleton:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

Builder:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

Prototype:用原型实例指定创建对象的种类,并且通过拷贝这个原型来创建新的对象。

Bridge:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

Adapter:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

Decorator:动态地给一个对象添加一些额外的职责。就扩展功能而言, Decorator模式比生成子类方式更为灵活。

Composite:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得客户对单个对象和复合对象的使用具有一致性。

Flyweight:运用共享技术有效地支持大量细粒度的对象。

Facade:为子系统中的一组接口提供一个一致的界面, Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

Proxy:为其他对象提供一个代理以控制对这个对象的访问。

Template Method:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

Strategy:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法的变化可独立于使用它的客户。

State:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类。

Observer:定义对象间的一种一对多的依赖关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动刷新。

Memento:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到保存的状态。

Mediator:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

Command:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可取消的操作。

Visitor:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

Chain of Responsibility:为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它。

Iterator:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

Interpreter:给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。

         Observer:(1)、意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

         (2)、适用性:A、当一个抽象模型有两个方面,其中一个方面依赖于另一方面。将这两者封装在独立的对象中以使它们可以各自独立地改变和复用。B、当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。C、当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧密耦合的。

         (3)、优缺点:A、目标和观察者间的抽象耦合:一个目标所知道的仅仅是它有一系列观察者,每个都符合抽象的Observer类的简单接口。目标不知道任何一个观察者属于哪一个具体的类。这样目标和观察者之间的耦合是抽象的和最小的。因为目标和观察者不是紧密耦合的,它们可以属于一个系统中的不同抽象层次。一个处于较低层次的目标对象可与一个处于较高层次的观察者通信并通知它,这样就保持了系统层次的完整。如果目标和观察者混在一块,那么得到的对象要么横贯两个层次(违反了层次性),要么必须放在这两层的某一层中(这可能会损害层次抽象)。B、支持广播通信:不像通常的请求,目标发送的通知不需指定它的接收者。通知被自动广播给所有已向该目标对象登记的有关对象。目标对象并不关心到底有多少对象对自己感兴趣;它唯一的责任就是通知它的各观察者。这给了你在任何时刻增加和删除观察者的自由。处理还是忽略一个通知取决于观察者。C、意外的更新:因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常很难捕捉。简单的更新协议不提供具体细节说明目标中什么被改变了,这就使得上述问题更加严重。如果没有其他协议帮助观察者发现什么发生了改变,它们可能会被迫尽力减少改变。

         (4)、相关模式:A、Mediator:通过封装复杂的更新语义,ChangeManager(当目标和观察者间的依赖关系特别复杂时,可能需要一个维护这些关系的对象。我们称这样的对象为更改管理器。它的目的是尽量减少观察者反映其目标的状态变化所需的工作量) 充当目标和观察者之间的中介者。B、Singleton:ChangeManager可使用Singleton模式来保证它是唯一的并且是可全局访问的。

         (5)、观察者模式:定义了一种一对多的关系,让多个观察对象同时监听一个主题对象,主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。

         (6)、Observer模式要解决的问题为:建立一个一(Subject)对多(Observer)的依赖关系,并且做到当“一”变化的时候,依赖这个”一”的多也能够同步改变。最常见的一个例子就是:对同一组数据进行统计分析的时候,我们希望能够提供多种形式的表示(例如以表格进行统计显示、柱状图统计显示、百分比统计显示等)。这些表示都依赖于同一组数据,我们当然需要当数据改变的时候,所有的统计的显示都能够同时改变。Observer模式就是解决了这一关问题。

示例代码1:

#include <string>
#include <iostream>
#include <vector>

using namespace std;

class Secretary;

//看股票的同事类(观察对象,观察者)
class StockObserver
{
private:
	string name;
	Secretary* sub;
public:
	StockObserver(string strname, Secretary* strsub)
	{
		name = strname;
		sub = strsub;
	}

	void Update();
};

//秘书类(主题对象,通知者)
class Secretary
{
private:
	vector<StockObserver> observers;
public:
	string action;
	void Add(StockObserver ob)
	{
		observers.push_back(ob);
	}

	void Notify()
	{
		vector<StockObserver>::iterator p = observers.begin();
		
		while (p != observers.end())
		{
			(*p).Update();
			p ++;
		}
	}
};

void StockObserver::Update()
{
	cout<<name<<":"<<sub->action<<",不要玩股票了,要开始工作了"<<endl;
}

//客户端
int main()
{
	Secretary* p = new Secretary();//创建通知者

	//观察者
	StockObserver* s1 = new StockObserver("小李", p);
	StockObserver* s2 = new StockObserver("小赵", p);

	//加入通知队列
	p->Add(*s1);
	p->Add(*s2);

	//事件
	p->action = "老板来了";

	//通知
	p->Notify();

	/*result
		小李:老板来了,不要玩股票了,要开始工作了
		小赵:老板来了,不要玩股票了,要开始工作了
	*/
		
	return 0;
}

示例代码2:

#include <string>
#include <iostream>
#include <vector>

using namespace std;

class SecretaryBase;

//抽象观察者
class CObserverBase
{
protected:
	string name;
	SecretaryBase* sub;
public:
	CObserverBase(string strname, SecretaryBase* strsub)
	{
		name = strname;
		sub = strsub;
	}

	virtual void Update() = 0;
};

//具体的观察者,看股票的
class StockObserver : public CObserverBase
{
public:
	StockObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub)
	{

	}

	virtual void Update();
};

//具体观察者,看NBA的
class NBAObserver : public CObserverBase
{
public:
	NBAObserver(string strname, SecretaryBase* strsub) : CObserverBase(strname, strsub)
	{

	}

	virtual void Update();
};

//抽象通知者
class SecretaryBase
{
public:
	string action;
	vector<CObserverBase*> observers;
public:
	virtual void Attach(CObserverBase* observer) = 0;
	virtual void Notify() = 0;
};

//具体通知者
class Secretary : public SecretaryBase
{
public:
	void Attach(CObserverBase* ob)
	{
		observers.push_back(ob);
	}

	void Notify()
	{
		vector<CObserverBase*>::iterator p = observers.begin();

		while (p != observers.end())
		{
			(*p)->Update();
			p ++;
		}
	}
};

void StockObserver::Update()
{
	cout<<name<<":"<<sub->action<<"不要玩股票了,要开始工作了"<<endl;
}

void NBAObserver::Update()
{
	cout<<name<<":"<<sub->action<<"不要看NBA了,老板来了"<<endl;
}

//客户端
int main()
{
	SecretaryBase* p = new Secretary();//创建观察者

	//被观察的对象
	CObserverBase* s1 = new NBAObserver("小李", p);
	CObserverBase* s2 = new StockObserver("小赵", p);
	//加入观察队列
	p->Attach(s1);
	p->Attach(s2);
	//事件
	p->action = "老板来了";
	//通知
	p->Notify();

	/*result
		小李:老板来了不要看NBA了,老板来了
		小赵:老板来了不要玩股票了,要开始工作了
	*/

	return 0;
}

示例代码3:

Subject.h:

#ifndef _SUBJECT_H_
#define _SUBJECT_H_

#include <list>
#include <string>

using namespace std;

typedef string State;

class Observer;

class Subject
{
public:
	virtual ~Subject();
	virtual void Attach(Observer* obv);
	virtual void Detach(Observer* obv);
	virtual void Notify();
	virtual void SetState(const State& st) = 0;
	virtual State GetState() = 0;
protected:
	Subject();
private:
	list<Observer*>* _obvs;
};

class ConcreteSubject : public Subject
{
public:
	ConcreteSubject();
	~ConcreteSubject();
	State GetState();
	void SetState(const State& st);
protected:
private:
	State _st;
};


#endif//~_SUBJECT_H_

Subject.cpp:

#include "Subject.h"
#include "Observer.h"

#include <iostream>
#include <list>

using namespace std;

typedef string state;

Subject::Subject()
{
	//在模板的使用之前一定要new,创建
	_obvs = new list<Observer*>;
}

Subject::~Subject()
{

}

void Subject::Attach(Observer* obv)
{
	_obvs->push_front(obv);
}

void Subject::Detach(Observer* obv)
{
	if (obv != NULL)
		_obvs->remove(obv);
}

void Subject::Notify()
{
	list<Observer*>::iterator it;

	it = _obvs->begin();

	for (; it != _obvs->end(); it ++) 
		//关于模板和iterator的用法
		(*it)->Update(this);
}

ConcreteSubject::ConcreteSubject()
{
	_st = '\0';
}

ConcreteSubject::~ConcreteSubject()
{

}

State ConcreteSubject::GetState()
{
	return _st;
}

void ConcreteSubject::SetState(const State& st)
{
	_st = st;
}

Observer.h:

#ifndef _OBSERVER_H_
#define _OBSERVER_H_

#include "Subject.h"
#include <string>

using namespace std;

typedef string State;

class Observer
{
public:
	virtual ~Observer();
	virtual void Update(Subject* sub) = 0;
	virtual void PrintInfo() = 0;
protected:
	Observer();
	State _st;
private:
};

class ConcreteObserverA : public Observer
{
public:
	virtual Subject* GetSubject();
	ConcreteObserverA(Subject* sub);
	virtual ~ConcreteObserverA();

	//传入Subject作为参数,这样可以让一个View属于多个的Subject
	void Update(Subject* sub);
	void PrintInfo();
protected:
private:
	Subject* _sub;
};

class ConcreteObserverB : public Observer
{
public:
	virtual Subject* GetSubject();
	ConcreteObserverB(Subject* sub);
	virtual ~ConcreteObserverB();
	//传入Subject作为参数,这样可以让一个View属于多个的Subject
	void Update(Subject* sub);
	void PrintInfo();
protected:
private:
	Subject* _sub;
};

#endif//~_OBSERVER_H_

Observer.cpp:

#include "Observer.h"
#include "Subject.h"

#include <iostream>
#include <string>

using namespace std;

Observer::Observer()
{
	_st = '\0';
}

Observer::~Observer()
{

}

ConcreteObserverA::ConcreteObserverA(Subject* sub)
{
	_sub = sub;
	_sub->Attach(this);
}

ConcreteObserverA::~ConcreteObserverA()
{
	_sub->Detach(this);

	if (_sub != 0)
		delete _sub;
}

Subject* ConcreteObserverA::GetSubject()
{
	return _sub;
}

void ConcreteObserverA::PrintInfo()
{
	cout<<"ConcreteObserverA observer ..."<<_sub->GetState()<<endl;
}

void ConcreteObserverA::Update(Subject* sub)
{
	_st = sub->GetState();
	PrintInfo();
}

ConcreteObserverB::ConcreteObserverB(Subject* sub)
{
	_sub = sub;
	_sub->Attach(this);
}

ConcreteObserverB::~ConcreteObserverB()
{
	_sub->Detach(this);

	if (_sub != 0)
		delete _sub;
}

Subject* ConcreteObserverB::GetSubject()
{
	return _sub;
}

void ConcreteObserverB::PrintInfo()
{
	cout<<"ConcreteObserverB observer ..."<<_sub->GetState()<<endl;
}

void ConcreteObserverB::Update(Subject* sub)
{
	_st = sub->GetState();
	PrintInfo();
}

main.cpp:

#include "Subject.h"
#include "Observer.h"

#include <iostream>

using namespace std;

int main()
{
	ConcreteSubject* sub = new ConcreteSubject();
	Observer* o1 = new ConcreteObserverA(sub);
	Observer* o2 = new ConcreteObserverB(sub);
	sub->SetState("old");
	sub->Notify();
	sub->SetState("new");//也可以由Observer调用
	sub->Notify();

	/*result
		ConcreteObserverB observer ...old
		ConcreteObserverA observer ...old
		ConcreteObserverB observer ...new
		ConcreteObserverA observer ...new
	*/

	return 0;
}

观察者模式结构图:


参考文献:

1、《大话设计模式C++》

2、《设计模式精解----GoF23种设计模式解析》

3、《设计模式----可复用面向对象软件的基础》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之观察者模式(Observer)摘录 的相关文章

  • 华为OD机试 - 组装最大可靠性设备(Java )

    题目描述 一个设备由N种类型元器件组成 每种类型元器件只需要一个 类型type编号从0 N 1 每个元器件均有可靠性属性reliability 可靠性越高的器件其价格price越贵 而设备的可靠性由组成设备的所有器件中可靠性最低的器件决定
  • wxwidgets编写多线程程序--wxThread

    细节描述 线程基本上来说是应用程序中一条单独执行的路径 线程有时被称为轻量级进程 但线程与进程的根本不同之处在于不同进程存储空间是相互独立的 而同一进程里的所有线程共享同一地址空间 尽管这使得它更容易共享几个线程间的普通数据 但这也使得它有
  • 企业微信群:机器人实现定时提醒功能

    如果每天都需要 或者经常需要提醒企业微信群里面的人做某一件事情的话 靠人力去实现比较费力 而且偶尔忘记 正好 企业微信群有一个机器人 正可以实现这一功能 1 首先 在企业微信群 添加一个机器人 2 根据企业微信机器人的配置说明 编写程序 这
  • NOSuchKeys: com.aliyun.oss.OSSException: The specified key does not exist.

    出现这个原因就是在指定位置没有找到你想要获取的文件 1 检查你的文件名是否正确 2 你存文件是否带了文件夹 如果带了文件夹 检查文件夹是否正确 本文仅作为笔记
  • List集合的加减操作

    文章目录 一 对List本身有改变 二 对List本身无改变 参考资料 一 对List本身有改变 概述 List1 addAll List2 List1与List2两个集合相加 返回boolean值 原有List1值有变化 List2不变
  • 1-9 人机交互的角度

    操作系统的人机交互部分 OS改善人机界面 为用户使用计算机提供良好的环境 人机交互设备包括传统的终端设备和新型的模式识别设备 OS的人机交互部分用于控制有关设备运行和理解执行设备传来的命令 人机交互功能是决定计算机系统友善性的重要因素 是当

随机推荐

  • 机器学习算法GBDT的面试要点总结-上篇

    1 简介 gbdt全称梯度提升决策树 在传统机器学习算法里面是对真实分布拟合的最好的几种算法之一 在前几年深度学习还没有大行其道之前 gbdt在各种竞赛是大放异彩 原因大概有几个 一是效果确实挺不错 二是即可以用于分类也可以用于回归 三是可
  • "无法找到“XXX.exe”的调试信息,或者调试信息不匹配

    今天调试一C 程序 按下F5 老是弹出一对话框显示信息 debugging information for myproject exe cannot be found or does not match No symbols loaded
  • ros_control学习

    前言 ROS中提供了丰富的机器人应用 SLAM 导航 MoveIt 但是你可能一直有一个疑问 这些功能包到底应该怎么样用到我们的机器人上 也就是说在应用和实际机器人或者机器人仿真器之间 缺少一个连接两者的东西 ros control就是RO
  • MySQL之数据类型

    目录 一 MySQL数据类型分类 二 数值类型 1 整数类型 2 bit类型 3 小数类型 三 字符串类型 1 char 2 varchar 3 char和varchar比较 四 日期和时间类型 五 enum和set 一 MySQL数据类型
  • C#短信接口开发经验及具体开发实现

    一 配置文件app config
  • Unicode编码小结

    Unicode编码 一 ASCLL码 ASCII American Standard Code for Information Interchange 美国信息交换标准代码 是基于拉丁字母的一套电脑编码系统 主要用于显示现代英语和其他西欧语
  • Flutter 扫描插件开发qrscan

    首先在pubspec yaml中集成 dependencies qrscan 0 2 17 在androd清单文件中加入以下权限
  • Ubuntu安装X11

    Qt实现linux无边框界面需要用到Xlib 安装X11命令如下 sudo apt get install libx11 dev libxext dev libxtst dev libxrender dev libxmu dev libxm
  • align-content 设置多行下的子元素排列方式 代码和图片展示

    align content 适用于 换行 多行 的情况下 单行无效 可以设置上对齐 居中拉伸和平均分配剩余空间等属性值 属性值 flex start 默认值 在侧轴头部开始排列 flex end 在侧轴尾部开始排列 center 在侧轴中间
  • 编程练习3-将文件a处理为文件b

    初始文件a txt a b c d e f o p q r s t 处理后文件b txt a b a b c d a b c d e f o p o p q r o p q r s t shell bin bash array1 awk p
  • 虚拟主机的数据库服务器怎么填,虚拟主机的数据库服务器怎么填

    虚拟主机的数据库服务器怎么填 内容精选 换一换 云服务器备份 云服务器备份可以对普通服务器进行整机备份或部分磁盘备份 不适用于部署了数据库等应用的服务器 支持备份弹性云服务器ECS和裸金属服务器BMS 成本相对于VBS较高 适合对需要备份整
  • anaconda 创建虚拟环境

    创建虚拟环境 conda create n 名字 python 版本号 e g conda create n test python 3 10 删除虚拟环境 conda remove n 名字 all e g conda remove n
  • 大数据之hive(数据仓库工具)的分组和分区操作

    注 在对hive的概念 优缺点 安装部署和参数配置在之后再进行总结 本小节主要对hive中的分组和分区进行总结 一 分组 1 group by语句 group by通常和聚合函数一起使用 按照一个或者多个列进行分组 然后对每个组进行聚合操作
  • Visual Studio 将json转换为实体类

    先复制你的json文本然后
  • JDK源码 --

    Object类 一 简介 gt java lang Object 是Java所有类的父类 在你编写一个类的时候 若无指定父类 没有显式extends一个父类 会默认的添加Object为该类的父类 在JDK 6之前是编译器处理 即编译后的zc
  • 【Python中线程和进程详解】

    一 区别 几乎所有的操作系统都支持同时运行多个任务 每个任务通常是一个程序 每一个运行中的程序就是一个进程 即进程是应用程序的执行实例 现代的操作系统几乎都支持多进程并发执行 注意 并发和并行是两个概念 并行指在同一时刻有多条指令在多个处理
  • 配置NFS服务器-debian

    NFS Network Files System 是网络文件系统的英文缩写 由Sun公司于1980年开发 用于在UNIX操作系统间实现磁盘文件共享 在Linux操作系统出现后 NFS被Linux继承 并成为文件服务的一种标准 通过网络 NF
  • 施耐德电气携中国信通院和中国联通共同发布白皮书,共探5G+PLC深度融合应用

    2023年9月20日 全球能源管理和自动化领域的数字化转型专家施耐德电气在第23届中国国际工业博览会首日的9月19日 与中国信息通信研究院 以下简称 中国信通院 及中国联合网络通信集团有限公司 以下简称 中国联通 联手重磅发布 5G PLC
  • 6.SSH框架整合及简单使用示例

    6 SSH框架整合 ssh spring spring mvc hibernate 6 1 整合的场所 web xml 跟 5 ssm框架 整合类似 可以对照学习 通过监听器配置hibernate 通过servlet配置mvc web xm
  • 设计模式之观察者模式(Observer)摘录

    23种GOF设计模式一般分为三大类 创建型模式 结构型模式 行为模式 创建型模式抽象了实例化过程 它们帮助一个系统独立于如何创建 组合和表示它的那些对象 一个类创建型模式使用继承改变被实例化的类 而一个对象创建型模式将实例化委托给另一个对象