C++学习日记12——设计模式

学习视频链接

黑马程序员2017C++设计模式(已完结)_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1KW411t7FV?p=11&spm_id_from=pageDriver

目录

一、软件建模概述

1.1 什么是建模

1.2 建模原则

1.3 软件建模的实现过程

二、UML

2.1 UML一共有 10 种图

2.2 UML中的关系

三、用例图

3.1 用例之间的关系 —— 泛化关系

3.2 用例之间的关系 —— 包含关系

3.3 用例之间的关系 —— 扩展关系

四、类图

4.1 类的表示法

4.2 类之间的关系 —— 泛化关系

4.3 类之间的关系实现关系

4.4 类之间的关系 —— 依赖关系

4.5 类之间的关系 —— 关联关系

4.6 关联关系的名称

4.7 关联关系的角色

4.8 关联关系的多重性

4.9 类之间的关系关联 —— 聚合

4.10 练习

三、设计模式概述

3.1 设计模式从何而来

3.2 软件设计模式从何而来

3.3 软件设计模式的种类

3.4 软件设计模式有什么用?

3.5 设计模式总览表

四、面向对象设计原则

4.1 面向对象设计原创表

4.2 开闭原则

4.3 迪米特法则

4.4 合成复用原则

4.5 依赖倒转原则

五、创建型设计模式

5.1 简单工厂模式

5.2 工厂方法模式

5.3 抽象工厂模式

5.4 单例模式

六、结构型设计模式

6.1 代理模式

6.2 外观模式

6.3 适配器模式

6.4 装饰模式

七、行为模式

7.1 模板方法模式

7.2 策略模式

7.3 命令模式

7.4 观察者模式


一、软件建模概述

1.1 什么是建模

任何事情都要先想清楚了才能做,软件开发更是如此!软件开发过程不可能一上来就开始盲目写代码,写代码之前必须搞清楚下面一些基本问题:

要做什么?

做成什么样?

怎么去做?

1.2 建模原则

选择建立什么样的模型对如何发现和解决问题具有重要的影响。 正确的模型有助于提高开发者的洞察力。

每个模型可以有多种表达方式。使用者的身份和使用的原因是评判模型好坏的关键。

最好的模型总是能够切合实际。模型是现实的简化,必须保证简化过程不会掩盖任何重要的细节。

1.3 软件建模的实现过程

软件建模的作用是把源于现实世界的问题转化为计算机可以理解和实现的过程。

C++学习日记12——设计模式_第1张图片

二、UML

(1) UML(United Modeling Language,统一建模语言):是一种基于面向对象的可视化建模语言。

(2) UML 采用了一组形象化的图形(如类图)符号作为建模语言,使用这些符号可以形象地描述系统的各个方面

(3) UML 通过建立图形之间的各种关系(如类与类之间的关系)来描述模型

2.1 UML一共有 10 种图

类图、对象图、包图、组件图、部署图、用例图、时序图、协作图、状态图

2.2 UML中的关系

UML中的关系主要包括 4 种:

关联关系 (association)

依赖关系 (dependency)

泛化关系 (generalization)

实现关系 (realization)

三、用例图

(1) 用例图 (Use Case Diagram):也称为用户模型图,是从软件需求分析到最终实现的第一步它是从客户的角度来描述系统功能

(2) 用例图包含 3 个基本组件:

参与者 (Actor):与系统打交道的人或其他系统即使用该系统的人或事物。在 UML 中参与者用人形图标表示

用例 (Use Case):代表系统的某项完整的功能。在 UML 中使用一个椭圆来表示

关系:定义用例之间的关系 —— 泛化关系,扩展关系,包含关系

图片解释:用户可以使用查询,管理员可以使用 add、update

C++学习日记12——设计模式_第2张图片

3.1 用例之间的关系 —— 泛化关系

泛化关系:表示同一业务目的(父用例)的不同技术实现(各个子用例)在 UML 中,用例泛化用一个三角箭头从子用例指向父用例。以下是某购物网站为用户提供不同的支付方式

图片解释:签约用户能使用注册用户的功能

C++学习日记12——设计模式_第3张图片

3.2 用例之间的关系 —— 包含关系

一个用例可以包含其他用例具有的行为,并把它包含的用例行为作为自身行为的一部分。在 UML 中包含关系用虚线箭头加 “<>",箭头指向被包含的用例

图片解释:添加学生信息包含更新数据库

C++学习日记12——设计模式_第4张图片

3.3 用例之间的关系 —— 扩展关系

如果在完成某个功能的时候偶尔会执行另外一个功能,则用扩展关系表示。在UML中扩展关系用虚线箭头加 "<>",箭头指向被扩展的用例

C++学习日记12——设计模式_第5张图片

四、类图

类图是面向对象系统建模中最常用的图。是定义其他图的基础

类图主要是用来显示系统中的类,接口以及它们之间的关系

类图包含的主要元素有类,接口和关系。其中关系有泛化关系,关联关系,依赖关系和实现关系。在类图中也可以包含注释和约束

4.1 类的表示法

1、类是类图的主要组件,由 3 部分组成:类名,属性和方法。在UML中,类用矩形来表示,顶端部分存放类的名称,中间部分存放类的属性,属性的类型及值,底部部分存放类的方法,方法的参数和返回类型。

2、在 UML 中可以根据实际情况有选择的隐藏属性部分或方法部分或两者都隐藏

3、在 UML 中,共有类型有 + 表示,私有类型用 - 表示,保护类型用 # 表示。UML 的工具开发商可以使用自己定义的符号表示不同的可见性

C++学习日记12——设计模式_第6张图片

4.2 类之间的关系 —— 泛化关系

1、在 UML 中,泛化关系用来表示类与类,接口与接口之间的继承关系。泛化关系有时也称为 ”isa kind of“ 关系

2、在 UML 中泛化关系用一条实线空心箭头有子类指向父类.

C++学习日记12——设计模式_第7张图片

4.3 类之间的关系实现关系

在 UML 中,实现关系用来表示类与接口之间的实现关系

在 UML 中实现关系用一条虚线空心箭头由子类指向父类

C++学习日记12——设计模式_第8张图片

4.4 类之间的关系 —— 依赖关系

对于两个相对独立的系统,当一个系统负责构造另一个系统的实例,或者依赖另一个系统的服务时,这两个系统之间体现为依赖关系。例如生产零件的机器和零件,机器负责构造零件对象;充电电池和充电器,充电电池通过充电器来充电;自行车 Bicycle 和打气筒 Pump,自行车通过打气筒来充气。

C++学习日记12——设计模式_第9张图片

class BMW {
public:
    void run() {
        cout << "BWM车开去上班" << endl;
    }
};

class Person {
public:
    void GoWork(BMW *car) {
        car->run();
    }
};

4.5 类之间的关系 —— 关联关系

对于两个相对独立的系统,当一个系统的实例与另一个系统的一些特定实例存在固定的对应关系时,这两个系统之间为关联关系。例如客户和订单,每个订单对应特定的客户,每个客户对应一些特定的订单;公司和员工,每个公司对应一些特定的员工,每个员工对应一特定的公司;自行车和主人,每辆自行车属于特定的主人,每个主人有特定的自行车。而充电电池和充电器之间就不存在固定的对应关系,同样自行车和打气筒之间也不存在固定的对应关系。 

C++学习日记12——设计模式_第10张图片

class BMW {
public:
    void run() {
        cout << "BWM车开去上班" << endl;
    }
};

class Person {
public:
    void GoWork() {
        car->run();
    }
public:
    BMW *car;
};

4.6 关联关系的名称

关联关系的名称:关联关系可以有一个名称,用于描述该关系的性质。此关联名称应该是动词短语,因为它表明源对象正在目标对象上执行动作

C++学习日记12——设计模式_第11张图片

4.7 关联关系的角色

当一个类处于关联的某一端时,该类就在这个关系中扮演一个特定的角色。具体来说,角色就是关联关系中一个类对另一个类所表现的职责。角色名称是名词或名称短语

C++学习日记12——设计模式_第12张图片

4.8 关联关系的多重性

关联关系的多重性是指有多少对象可以参与该关联,多重性可以用来表达一个取值范围,特定值,无限定的范围

C++学习日记12——设计模式_第13张图片

 图片解释:一个人可以拥有 n 辆车,一辆车只能被一人拥有

C++学习日记12——设计模式_第14张图片

4.9 类之间的关系关联 —— 聚合

1、聚合关系是关联关系的一种,是更强的关联关系

2、聚合是整体和部分之间的关系例如汽车由引擎、轮胎以及其它零件组成

3、聚合关系也是通过成员变量来实现的。但是, 关联关系所涉及的两个类处在同一个层次上,而聚合关系中,两个类处于不同的层次上,一个代表整体,一个代表部分。

C++学习日记12——设计模式_第15张图片

4.10 练习

汽车和自行车都是交通工具 (vehicle),一辆自行车 (bicycle) 只归一个人 (person) 所有,但一辆汽车 (auto) 可归一个人或两个人所有。一个人可能没有自行车或汽车,也可能有多辆自行车或汽车。人分为男人 (male) 和女人 (female)。每个人都有年龄 (age) 和名字 (name)。每辆交通工具都有自己的颜色 (color) 和商标 (brand)。每辆汽车都只有两个前灯 (headlight) 和一台发动机 (motor)

C++学习日记12——设计模式_第16张图片

三、设计模式概述

如果把修习软件开发当做武功修炼的话,那么可以分为招式和内功。

招式:Java、C#、C+ + 等编程语言;

Eclipse、Visual Studio 等开发工具;

JSP、ASP.net 等开发技术;

Struts、Hibernate、JBPM 等框架技术;

内功:数据结构、算法、设计模式、重构、软件工程

3.1 设计模式从何而来

Christopher Alexander(克里斯托弗.亚历山大)—— 哈佛大学建筑学博士、美国加州大学伯克利分校建筑学教授、加州大学伯克利分校环境结构研究所所长、美国艺术和科学院院士。

他提出,“每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心,通过这种方式,我们可以无数次地重用那些已有的成功的解决方案,无须再重复相同的工作。”

设计模式的定义:“设计模式是在特定环境下人们解决某类重复出现问题的一套成功或有效的解决方案。”

3.2 软件设计模式从何而来

四人组 (Gang of Four),简称 GoF

Ralph Johnson , Richard Helm , Erich Gamma , John Vlissides

GoF 将模式的概念引入软件工程领域,这标志着软件模式的诞生。软件模式 (Software Patterns) 是将模式的一般概念应用于软件开发领域,即软件开发的总体指导思路或参照样板。软件模式并非仅限于设计模式, 还包括架构模式、分析模式和过程模式等,实际上,在软件开发生命周期的每一个阶段都存在着一些被认同的模式。

软件模式与具体的应用领域无关,也就是说无论你从事的是移动应用开发、桌面应用开发、Web应用开发还是嵌入式软件的开发,都可以使用软件模式。

无论你是使用 Java、C#、Objective-C、VB.net、Smalltalk 等纯面向对象编程语言,还是使用C++、PHP、Delphi、JavaScript 等可支持面向对象编程的语言,你都需要了解软件设计模式!

3.3 软件设计模式的种类

GoF 提出的设计模式有23个,包括:

创建型 (Creational) 模式:如何创建对象;

结构型 (Structural) 模式:如何实现类或对象的组合;

行为型 (Behavioral) 模式:类或对象怎样交互以及怎样分配职责。

有一个 “简单工厂模式” 不属于 GoF23 种设计模式,但大部分的设计模式书籍都会对它进行专门的介绍。

设计模式目前种类:GoF的 23 种 + “简单工厂模式” = 24 种

3.4 软件设计模式有什么用?

1、如何将代码分散在几个不同的类中?

2、为什么要有 "接口”?

3、何谓针对抽象编程?

4、何时不应该使用继承?

5、如果不修改源代码增加新功能?

6、更好地阅读和理解现有类库与其他系统中的源代码。

3.5 设计模式总览表

C++学习日记12——设计模式_第17张图片

 C++学习日记12——设计模式_第18张图片

 C++学习日记12——设计模式_第19张图片

四、面向对象设计原则

对于面向对象软件系统的设计而言,在支持可维护性的同时,提高系统的可复用性是一个至关重要的问题,如何同时提高一个软件系统的可维护性和可复用性是面向对象设计需要解决的核心问题之一。在面向对象设计中,可维护性的复用是以设计原则为基础的。每一个原则都蕴含一些面向对象设计的思想,可以从不同的角度提升一个软件结构的设计水平。

面向对象设计原则为支持可维护性复用而诞生,这些原则蕴含在很多设计模式中,它们是从许多设计方案中总结出的指导性原则。面向对象设计原则也是我们用于评价一个设计模式的使用效果的重要指标之一。

原则的目的:高内聚(一个类一个函数只做一件事), 低耦合(降低类和类之间的关系)

4.1 面向对象设计原创表

C++学习日记12——设计模式_第20张图片

 C++学习日记12——设计模式_第21张图片

C++学习日记12——设计模式_第22张图片

C++学习日记12——设计模式_第23张图片

C++学习日记12——设计模式_第24张图片

4.2 开闭原则

开闭原则:对拓展开放,对修改关闭,增加功能是通过增加代码来实现,而不是去修改源代码

#include 
#include 
using namespace std;

//写一个抽象类
class AbstractCaculator {
public:
	virtual int getResult() = 0;
	virtual void setOperatorNumber(int a, int b) = 0;
};

// 加法计算器类
class PlusCaculator : public AbstractCaculator{
public:
	virtual void setOperatorNumber(int a, int b) {
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult() {
		return mA + mB;
	}
public:
	int mA;
	int mB;
};

// 减法计算器类
class MinuteCaculator : public AbstractCaculator {
public:
	virtual void setOperatorNumber(int a, int b) {
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult() {
		return mA - mB;
	}
public:
	int mA;
	int mB;
};

// 乘法计算器类
class MultiplyCaculator : public AbstractCaculator {
public:
	virtual void setOperatorNumber(int a, int b) {
		this->mA = a;
		this->mB = b;
	}
	virtual int getResult() {
		return mA * mB;
	}
public:
	int mA;
	int mB;
};

int main(void) 
{
	AbstractCaculator* caculator = new PlusCaculator;
	caculator->setOperatorNumber(10, 20);
	cout << caculator->getResult() << endl;

	delete caculator;

	caculator = new MinuteCaculator;
	caculator->setOperatorNumber(10, 20);
	cout << caculator->getResult() << endl;

	return 0;
}

4.3 迪米特法则

迪米特法则:最少知识原则,不要把所有的细节都暴露

1、正常的写法

#include 
#include 
using namespace std;

//写一个抽象类
class AbstractBuilding {
public:
	virtual void sale() = 0;
};

class BuildingA : public AbstractBuilding{
public:
	BuildingA() {
		mQulity = "高品质";
	}
	virtual void sale() {
		cout << "楼盘A:" << mQulity << "被售卖" << endl;
	}
public:
	string mQulity;
};

class BuildingB : public AbstractBuilding {
public:
	BuildingB() {
		mQulity = "低品质";
	}
	virtual void sale() {
		cout << "楼盘B" << mQulity << "被售卖" << endl;
	}
public:
	string mQulity;
};

void test1()
{
	BuildingA* ba = new BuildingA;
	if (ba->mQulity == "高品质") {
		ba->sale();
	}

	BuildingB* bb = new BuildingB;
	if (bb->mQulity == "高品质") {
		bb->sale();
	}
}

int main(void) 
{
	test1();

	return 0;
}

2、增加一个中间类

#include 
#include 
#include 
using namespace std;

//写一个抽象类
class AbstractBuilding {
public:
	virtual void sale() = 0;
	virtual string getQulity() = 0;
};

class BuildingA : public AbstractBuilding{
public:
	BuildingA() {
		mQulity = "高品质";
	}
	virtual void sale() {
		cout << "楼盘A:" << mQulity << "被售卖" << endl;
	}
	virtual string getQulity() {
		return mQulity;
	}
public:
	string mQulity;
};

class BuildingB : public AbstractBuilding {
public:
	BuildingB() {
		mQulity = "低品质";
	}
	virtual void sale() {
		cout << "楼盘B" << mQulity << "被售卖" << endl;
	}
	virtual string getQulity() {
		return mQulity;
	}
public:
	string mQulity;
};

// 售楼部
class Mediator {
public:
	Mediator() {
		AbstractBuilding* bu = new BuildingA;
		vBuilding.push_back(bu);
		bu = new BuildingB;
		vBuilding.push_back(bu);
	}

	// 对外提供接口
	AbstractBuilding* findMyBuilding(string quality) {
		for (vector::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {
			if ((*it)->getQulity() == quality) {
				return* it;
			}
		}
		return NULL;
	}

	~Mediator() {
		for (vector::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {
			if (*it != NULL) {
				delete* it;
			}
		}
	}
public:
	vector vBuilding;
};

void test1()
{
	BuildingA* ba = new BuildingA;
	if (ba->mQulity == "高品质") {
		ba->sale();
	}

	BuildingB* bb = new BuildingB;
	if (bb->mQulity == "高品质") {
		bb->sale();
	}
}

void test2()
{
	Mediator* mediator = new Mediator;
	AbstractBuilding* building = mediator->findMyBuilding("高品质");
	if (building != NULL) {
		building->sale();
	}
	else
	{
		cout << "没有找到符合您条件的房子" << endl;
	}
}

int main(void) 
{
	test2();

	return 0;
}

C++学习日记12——设计模式_第25张图片

4.4 合成复用原则

继承和组合优先使用组合

#include 
#include 
using namespace std;

// 抽象车
class AbstractCar {
public:
	virtual void run() = 0;
};

class Dazhong : public AbstractCar {
public:
	virtual void run() {
		cout << "大众车启动 ..." << endl;
	}
};

class Tuolaji : public AbstractCar {
public:
	virtual void run() {
		cout << "拖拉机启动 ..." << endl;
	}
};

// 针对具体类 不使用继承
#if 0
class Person1 : public Tuolaji {
public:
	void Doufeng() {
		run();
	}
};

class Person2 : public Dazhong {
public:
	void Doufeng() {
		run();
	}
};
#endif

// 可以使用组合
class Person {
public:
	void setCar(AbstractCar* car) {
		this->car = car;
	}

	void Doufeng() {
		this->car->run();
		if (this->car != NULL) {
			delete this->car;
			this->car = NULL;
		}
	}

	~Person() {
		if (this->car != NULL) {
			delete this->car;
		}
	}

public:
	AbstractCar* car;
};

int main(void) 
{
	Person *p = new Person;
	p->setCar(new Dazhong);
	p->Doufeng();

	p->setCar(new Tuolaji);
	p->Doufeng();

    delete p;

	return 0;
}

4.5 依赖倒转原则

C++学习日记12——设计模式_第26张图片

传统的过程式设计倾向于使高层次的模块依赖于低层次的模块,抽象层依赖于具体的层次

C++学习日记12——设计模式_第27张图片

1、原来的写法

#include 
#include 
using namespace std;

// 银行工作人员
class BankWorker {
public:
	void saveService() {
		cout << "办理存款业务 ... " << endl;
	}
	void payService() {
		cout << "办理支付业务 ... " << endl;
	}
	void tranferService() {
		cout << "办理转账业务 ... " << endl;
	}
};


// 中层模块
void doSaveBussiness(BankWorker* worker) 
{
	worker->saveService();
}

void doPayBussiness(BankWorker* worker) 
{
	worker->payService();
}

void doTranferBussiness(BankWorker* worker) 
{
	worker->tranferService();
}


// 业务模块
void test() 
{
	BankWorker* worker = new BankWorker;
	doSaveBussiness(worker);    // 办理存款业务
	doPayBussiness(worker);     // 办理支付业务
	doTranferBussiness(worker); // 办理转账业务
}


int main(void) 
{
	test();

	return 0;
}

2、改进后的写法

#include 
#include 
using namespace std;

// 银行工作人员
class AbstractWorker {
public:
	virtual void doBusiness() = 0;
};

// 专门负责办理存款业务
class SaveBankWorker : public AbstractWorker {
public:
	virtual void doBusiness() {
		cout << "办理存款业务 ... " << endl;
	}
};

// 专门负责办理支付业务
class PayBankWorker : public AbstractWorker {
public:
	virtual void doBusiness() {
		cout << "办理支付业务 ... " << endl;
	}
};

// 专门负责办理转账业务
class TranferBankWorker : public AbstractWorker {
public:
	virtual void doBusiness() {
		cout << "办理转账业务 ... " << endl;
	}
};


// 中层业务模块
void doNewBussiness(AbstractWorker* worker)
{
	worker->doBusiness();
}


// 业务模块
void test() 
{
	AbstractWorker* transfer = new TranferBankWorker;
	doNewBussiness(transfer);
}


int main(void) 
{
	test();

	return 0;
}

五、创建型设计模式

5.1 简单工厂模式

1、作用

自己在你写的业务函数或者类创建对象不想创建,只想拿来用

2、优点

(1) 客户端和具体实现类解耦

(2) 对于某些对象创建过程比较复杂情况,我们不用考虑这些了

3、缺点

(1) 简单工厂模式,增加新的功能是通过修改源代码实现,不符合开闭原则

(2) 这个类职责过重,这个类发生问题,会影响很多实用这个工厂的模块

4、类图

C++学习日记12——设计模式_第28张图片

5、代码

#include 
#include 
using namespace std;

class AbstractFruit {
public:
	virtual void showName() = 0;
};

// 苹果
class Apple : public AbstractFruit {
public:
	virtual void showName() {
		cout << "我是苹果" << endl;
	}
};

// 香蕉
class Banana : public AbstractFruit {
public:
	virtual void showName() {
		cout << "我是香蕉" << endl;
	}
};

// 梨
class Pear : public AbstractFruit {
public:
	virtual void showName() {
		cout << "我是梨" << endl;
	}
};

// 水果工厂
class FruitFactory {
public:
	static AbstractFruit* CreateFruit(string flag) {
		if (flag == "apple") {
			return new Apple;
		}
		else if (flag == "banana") {
			return new Banana;
		}
		else if (flag == "pear") {
			return new Pear;
		}
		else {
			return NULL;
		}
	}
};

int main(void) 
{
	FruitFactory* factory = new FruitFactory;
	AbstractFruit* fruit = factory->CreateFruit("apple");
	fruit->showName();
	delete fruit;

	fruit = factory->CreateFruit("banana");
	fruit->showName();
	delete fruit;

	fruit = factory->CreateFruit("pear");
	fruit->showName();
	delete fruit;

	return 0;
}

6、适用场景

(1) 工厂类负责创建的对象比较少,由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂

(2) 客户端只知道传入工厂类的参数,对于如何创建对象并不关心

5.2 工厂方法模式

1、图示

C++学习日记12——设计模式_第29张图片

2、优点

符合开闭原则

3、缺点

类的个数成倍增加,导致类越来越多,增加维护成本

4、代码

#include 
#include 
using namespace std;

class AbstractFruit {
public:
	virtual void showName() = 0;
};

// 苹果
class Apple : public AbstractFruit {
public:
	virtual void showName() {
		cout << "我是苹果" << endl;
	}
};

// 香蕉
class Banana : public AbstractFruit {
public:
	virtual void showName() {
		cout << "我是香蕉" << endl;
	}
};

// 梨
class Pear : public AbstractFruit {
public:
	virtual void showName() {
		cout << "我是梨" << endl;
	}
};

// 抽象工厂
class AbstractFruitFactory {
public:
	virtual AbstractFruit* CreateFruit() = 0;
};

// 苹果工厂
class AppleFactory : public AbstractFruitFactory {
public:
	virtual AbstractFruit* CreateFruit() {
		return new Apple;
	}
};

// 香蕉工厂
class BananaFactory : public AbstractFruitFactory {
public:
	virtual AbstractFruit* CreateFruit() {
		return new Banana;
	}
};

// 梨工厂
class PearFactory : public AbstractFruitFactory {
public:
	virtual AbstractFruit* CreateFruit() {
		return new Pear;
	}
};


int main(void) 
{
	AbstractFruitFactory* factory = NULL;
	AbstractFruit* fruit = NULL;

	factory = new AppleFactory;
	fruit = factory->CreateFruit();
	fruit->showName();
	delete fruit;
	delete factory;

	factory = new BananaFactory;
	fruit = factory->CreateFruit();
	fruit->showName();
	delete fruit;
	delete factory;

	factory = new PearFactory;
	fruit = factory->CreateFruit();
	fruit->showName();
	delete fruit;
	delete factory;

	return 0;
}

5、适用场景

(1) 客户端不知道它所需要的对象的类

(2) 抽象工厂类通过其子类来指定创建哪个对象

5.3 抽象工厂模式

1、概念

工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个 “产品族”,由同一个工厂来统一生产

C++学习日记12——设计模式_第30张图片

2、代码

#include 
#include 
using namespace std;

class AbstractApple {
public:
	virtual void showName() = 0;
};

// 美国苹果
class ChinaApple : public AbstractApple {
public:
	virtual void showName() {
		cout << "中国的苹果" << endl;
	}
};

// 美国苹果
class UsaApple : public AbstractApple {
public:
	virtual void showName() {
		cout << "美国苹果" << endl;
	}
};

// 俄罗斯苹果
class RussiaApple : public AbstractApple {
public:
	virtual void showName() {
		cout << "俄罗斯苹果" << endl;
	}
};

// 抽象香蕉
class AbstractBanana {
public:
	virtual void showName() = 0;
};

// 中国香蕉
class ChinaBanana : public AbstractBanana {
public:
	virtual void showName() {
		cout << "中国香蕉" << endl;
	}
};

// 美国香蕉
class UsaBanana : public AbstractBanana {
public:
	virtual void showName() {
		cout << "美国香蕉" << endl;
	}
};

// 俄罗斯香蕉
class RussiaBanana : public AbstractBanana {
public:
	virtual void showName() {
		cout << "俄罗斯香蕉" << endl;
	}
};

// 抽象梨
class AbstractPear {
public:
	virtual void showName() = 0;
};

// 中国梨
class ChinaPear : public AbstractPear {
public:
	virtual void showName() {
		cout << "中国梨" << endl;
	}
};

// 美国梨
class UsaPear : public AbstractPear {
public:
	virtual void showName() {
		cout << "美国梨" << endl;
	}
};

// 俄罗斯梨
class RussiaPear : public AbstractPear {
public:
	virtual void showName() {
		cout << "俄罗斯梨" << endl;
	}
};

// 抽象工厂针对产品族
class AbstractFactory {
public:
	virtual AbstractApple* CreateApple() = 0;
	virtual AbstractBanana* CreateBanana() = 0;
	virtual AbstractPear* CreatePear() = 0;
};

// 中国工厂
class ChinaFactory : public AbstractFactory {
public:
	virtual AbstractApple* CreateApple() {
		return new ChinaApple;
	}
	virtual AbstractBanana* CreateBanana() {
		return new ChinaBanana;
	}
	virtual AbstractPear* CreatePear() {
		return new ChinaPear;
	}
};

// 美国工厂
class UsaFactory : public AbstractFactory {
public:
	virtual AbstractApple* CreateApple() {
		return new UsaApple;
	}
	virtual AbstractBanana* CreateBanana() {
		return new UsaBanana;
	}
	virtual AbstractPear* CreatePear() {
		return new UsaPear;
	}
};

// 俄罗斯工厂
class RussiaFactory : public AbstractFactory {
public:
	virtual AbstractApple* CreateApple() {
		return new RussiaApple;
	}
	virtual AbstractBanana* CreateBanana() {
		return new RussiaBanana;
	}
	virtual AbstractPear* CreatePear() {
		return new RussiaPear;
	}
};


int main(void) 
{
	AbstractFactory* factory = NULL;
	AbstractApple* apple = NULL;
	AbstractBanana* banana = NULL;
	AbstractPear* pear = NULL;

	// 中国工厂
	factory = new ChinaFactory;
	apple = factory->CreateApple();
	banana = factory->CreateBanana();
	pear = factory->CreatePear();

	apple->showName();
	banana->showName();
	pear->showName();

	delete pear;
	delete banana;
	delete apple;
	delete factory;

	return 0;
}

5.4 单例模式

1、概念

这个系统中只能有一个A类型的对象

控制这个 A 类型的对象个数,单例模式。系统只有一个对象

2、代码

#include 
#include 
using namespace std;

// 实现单例步骤
// 1、构造函数私有化
// 2、增加静态私有的当前类的指针变量
// 3、提供静态对外接口,可以让用户获得单例对象

// 单例:懒汉式
class Singleton_lazy {
private:
	Singleton_lazy() {
		cout << "单例懒汉式的构造函数" << endl;
	}
public:
	static Singleton_lazy* getInstance() {
		if (pSingleton == NULL) {
			pSingleton = new Singleton_lazy;
		}
		return pSingleton;
	}
private:
	static Singleton_lazy* pSingleton;
};

// 类外初始化
Singleton_lazy* Singleton_lazy::pSingleton = NULL;

// 单例:饿汉式
class Singleton_hungry {
private:
	Singleton_hungry() {
		cout << "单例饿汉式的构造函数" << endl;
	}
public:
	static Singleton_hungry* getInstance() {
		return pSingleton;
	}
private:
	static Singleton_hungry* pSingleton;
};

// 类外初始化
Singleton_hungry* Singleton_hungry::pSingleton = new Singleton_hungry;

int main(void) 
{
	cout << "main函数开始执行" << endl;

	return 0;
}

C++学习日记12——设计模式_第31张图片

添加一些内容

#include 
#include 
using namespace std;

// 实现单例步骤
// 1、构造函数私有化
// 2、增加静态私有的当前类的指针变量
// 3、提供静态对外接口,可以让用户获得单例对象

// 单例:懒汉式
class Singleton_lazy {
private:
	Singleton_lazy() {
		cout << "单例懒汉式的构造函数" << endl;
	}
public:
	static Singleton_lazy* getInstance() {
		if (pSingleton == NULL) {
			pSingleton = new Singleton_lazy;
		}
		return pSingleton;
	}
private:
	static Singleton_lazy* pSingleton;
};

// 类外初始化
Singleton_lazy* Singleton_lazy::pSingleton = NULL;

// 单例:饿汉式
class Singleton_hungry {
private:
	Singleton_hungry() {
		cout << "单例饿汉式的构造函数" << endl;
	}
public:
	static Singleton_hungry* getInstance() {
		return pSingleton;
	}
	// 不能提供这个方法,太危险了
#if 0
	static void freeSpace() {
		if (pSingleton != NULL) {
			delete pSingleton;
		}
	}
#endif
	// 嵌套类,析构的时候释放 pSingleton 内存空间
	class Garbo {
		~Garbo() {
			if (pSingleton != NULL) {
				delete pSingleton;
			}
		}
	};
private:
	static Singleton_hungry* pSingleton;
	static Garbo garbo;
};

// 类外初始化
Singleton_hungry* Singleton_hungry::pSingleton = new Singleton_hungry;

int main(void) 
{
	cout << "main函数开始执行" << endl;

	Singleton_lazy* p1 = Singleton_lazy::getInstance();
	Singleton_lazy* p2 = Singleton_lazy::getInstance();
	if (p1 == p2) {
		cout << "p1、p2 两个指针指向同一块内存空间,是单例" << endl;
	}
	else {
		cout << "p1、p2 两个指针指向同不同内存空间,不是单例" << endl;
	}

	Singleton_hungry* p3 = Singleton_hungry::getInstance();
	Singleton_hungry* p4 = Singleton_hungry::getInstance();
	if (p3 == p4) {
		cout << "p3、p4 两个指针指向同一块内存空间,是单例" << endl;
	}
	else {
		cout << "p3、p4 两个指针指向同不同内存空间,不是单例" << endl;
	}

	return 0;
}

C++学习日记12——设计模式_第32张图片

3、单例模式遇到了多线程

懒汉式的不是很安全,可能会创建两个单例,因此需要加锁解锁,所以很麻烦。直接使用饿汉式的比较好

4、优缺点

(1) 饿汉式

优点 :

线程安全

在类加载的同时已经创建好一个静态对象,调用时反应速度快

缺点 :

资源效率不高,可能 getInstance() 永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化

(2) 懒汉式

优点:

资源利用率高,不执行 getInstance() 就不会被实例,可以执行该类的其他静态方法

缺点:

第一次加载时不够快,多线程使用不必要的同步开销大

六、结构型设计模式

6.1 代理模式

1、定义

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

2、代码

#include 
#include 
using namespace std;

// 抽象的系统
class AbstractCommonInterface {
public:
	virtual void run() = 0;
};

// 写好的系统
class MySystem : public AbstractCommonInterface {
public:
	virtual void run() {
		cout << "系统启动..." << endl;
	}
};

// 代理:权限验证
class MySystemProxy : public AbstractCommonInterface {
public:
	MySystemProxy(string username, string password) {
		this->mUsername = username;
		this->mPassword = password;
		pSystem = new MySystem;
	}
	bool checkUsernameAndPassword() {
		if (mUsername == "admin" && mPassword == "admin") {
			return true;
		}
		return false;
	}
	virtual void run() {
		if (checkUsernameAndPassword()) {
			cout << "用户名和密码正确,验证通过" << endl;
			this->pSystem->run();
		}
		else {
			cout << "用户名或密码错误,重新输入" << endl;
		}
	}
	~MySystemProxy() {
		if (pSystem != NULL) {
			delete pSystem;
		}
	}
public:
	MySystem* pSystem;
	string mUsername;
	string mPassword;
};


int main()
{
	MySystemProxy* proxy = new MySystemProxy("admin", "admin");
	proxy->run();
	return 0;
}

3、应用

访问国外服务器前的代理服务器

访问web服务器前的缓冲服务器

6.2 外观模式

1、案例

根据类图,实现家庭影院外观模式应用。

实现KTV模式:电视打开,灯关掉,音响打开,麦克风打开,dvd 打开;

实现游戏模式:电视打开,音响打开,游戏机打开。

C++学习日记12——设计模式_第33张图片

C++学习日记12——设计模式_第34张图片

#include 
#include 
using namespace std;

class Television {
public:
	void On() {
		cout << "电视机打开" << endl;
	}
	void Off() {
		cout << " 电视机关闭" << endl;
	}
};

class Television {
public:
	void On() {
		cout << "电视机打开" << endl;
	}
	void Off() {
		cout << "电视机关闭" << endl;
	}
};

class Light {
public:
	void On() {
		cout << "电灯打开" << endl;
	}
	void Off() {
		cout << "电灯关闭" << endl;
	}
};

class Audio {
public:
	void On() {
		cout << "音响打开" << endl;
	}
	void Off() {
		cout << "音响关闭" << endl;
	}
};

class Mircophone {
public:
	void On() {
		cout << "麦克风打开" << endl;
	}
	void Off() {
		cout << "麦克风关闭" << endl;
	}
};

class DVDPlayer {
public:
	void On() {
		cout << "DVD播放器打开" << endl;
	}
	void Off() {
		cout << "DVD播放器关闭" << endl;
	}
};

class Gamemachine {
public:
	void On() {
		cout << "游戏机打开" << endl;
	}
	void Off() {
		cout << "游戏机关闭" << endl;
	}
};

class KTVMode {
public:
	KTVMode() {
		pTv = new Television;
		pLight = new Light;
		pAudio = new Audio;
		pMicrophone = new Mircophone;
		pDvd = new DVDPlayer;
	}
	void runKtv() {
		pTv->On();
		pLight->Off();
		pAudio->On();
		pMicrophone->On();
		pDvd->On();
	}
	void offKtv() {
		pTv->Off();
		pLight->On();
		pAudio->Off();
		pMicrophone->Off();
		pDvd->Off();
	}
	~KTVMode() {
		delete pTv;
		delete pLight;
		delete pAudio;
		delete pMicrophone;
		delete pDvd;
	}
public:
	Television* pTv;
	Light* pLight;
	Audio* pAudio;
	Mircophone* pMicrophone;
	DVDPlayer* pDvd;
};

int main(void)
{
	KTVMode* ktv = new KTVMode;
	ktv->runKtv();
	return 0;
}

6.3 适配器模式

1、案例

#include 
#include 
#include 
using namespace std;

struct MyPrint
{
	void operator()(int v1, int v2) {
		cout << v1 + v2 << endl;
	}
};

// 定义接口
class Target {
public:
	virtual void operator()(int v) = 0;
};

// 写适配器
class Adapter : public Target {
public:
	virtual void operator()(int v) {
		print(v, 100);
	}
public:
	MyPrint print;
};

int main(void)
{
	vector v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), Adapter());

	return 0;
}

C++学习日记12——设计模式_第35张图片

2、不把100写死的改进

#include 
#include 
#include 
using namespace std;

struct MyPrint
{
	void operator()(int v1, int v2) {
		cout << v1 + v2 << endl;
	}
};

// 定义接口
class Target {
public:
	virtual void operator()(int v) = 0;
};

// 写适配器
class Adapter : public Target {
public:
	Adapter(int param) {
		this->param = param;
	}
	virtual void operator()(int v) {
		print(v, param);
	}
public:
	MyPrint print;
	int param;
};

Adapter MyBind2nd(int v) {
	return  Adapter(v);
}

int main(void)
{
	vector v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), MyBind2nd(10));

	return 0;
}

6.4 装饰模式

观察者模式是用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展

C++学习日记12——设计模式_第36张图片

 

#include 
#include 
using namespace std;

// 抽象的英雄
class AbstractHero {
public:
	virtual void ShowStatus() = 0;
public:
	int mHp;
	int mMp;
	int mAt;
	int mDf;
};

// 英雄A
class HeroA : public AbstractHero {
public:
	HeroA() {
		mHp = 0;
		mMp = 0;
		mAt = 0;
		mDf = 0;
	}

	virtual void ShowStatus() {
		cout << "血量: " << mHp << endl;
		cout << "魔法: " << mMp << endl;
		cout << "攻击: " << mAt << endl;
		cout << "防御: " << mDf << endl;
	}
};

// 英雄穿上某个装饰物,那么他还是个英雄
class AbstractEquipment : public AbstractHero {
public:
	AbstractEquipment(AbstractHero* hero) 
	{
		this->pHero = hero;
	}
	virtual void ShowStatus() { }

public:
	AbstractHero* pHero;
};

// 狂徒铠甲
class KuangtuEquipment : public AbstractEquipment {
public:
	KuangtuEquipment(AbstractHero* hero) : AbstractEquipment(hero) {}
	// 增加额外功能
	void AddKuangtu() {
		cout << "英雄穿上狂徒以后......" << endl;
		this->mHp = this->pHero->mHp;
		this->mMp = this->pHero->mMp;
		this->mAt = this->pHero->mAt;
		this->mDf = this->pHero->mDf + 30;

		delete this->pHero;
	}
	virtual void ShowStatus() { 
		AddKuangtu();
		cout << "血量: " << mHp << endl;
		cout << "魔法: " << mMp << endl;
		cout << "攻击: " << mAt << endl;
		cout << "防御: " << mDf << endl;
	}
};

// 无尽之刃
class WuJingEquipment : public AbstractEquipment {
public:
	WuJingEquipment(AbstractHero* hero) : AbstractEquipment(hero) {}
	// 增加额外功能
	void AddWuJing() {
		cout << "英雄拿上无尽以后......" << endl;
		this->mHp = this->pHero->mHp;
		this->mMp = this->pHero->mMp;
		this->mAt = this->pHero->mAt + 80;
		this->mDf = this->pHero->mDf;

		delete this->pHero;
	}
	virtual void ShowStatus() {
		AddWuJing();
		cout << "血量: " << mHp << endl;
		cout << "魔法: " << mMp << endl;
		cout << "攻击: " << mAt << endl;
		cout << "防御: " << mDf << endl;
	}
};

void test01()
{
	AbstractHero* hero = new HeroA;
	hero->ShowStatus();

	cout << "------------------" << endl;
	
	// 给裸奔的英雄穿装备
	hero = new KuangtuEquipment(hero);
	hero->ShowStatus();

	cout << "------------------" << endl;

	// 给英雄装备武器
	hero = new WuJingEquipment(hero);
	hero->ShowStatus();
}

int main(void)
{
	test01();
	return 0;
}

C++学习日记12——设计模式_第37张图片

 

七、行为模式

7.1 模板方法模式

1、定义

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

2、代码

C++学习日记12——设计模式_第38张图片

#include 
using namespace std;

class DrinkTemplate
{
public:
	// 煮水
	virtual void BoildWater() = 0;
	// 冲泡
	virtual void Brew() = 0;
	// 倒入杯中
	virtual void PourInCup() = 0;
	// 加辅助料
	virtual void AddSomething() = 0;

	// 模板方法
	void Meke() {
		BoildWater();
		Brew();
		PourInCup();
		AddSomething();
	}
};

// 冲泡咖啡
class Coffee : public DrinkTemplate {
public:
	// 煮水
	virtual void BoildWater() {
		cout << "煮水泉水" << endl;
	}
	// 冲泡
	virtual void Brew() {
		cout << "冲泡咖啡" << endl;
	}
	// 倒入杯中
	virtual void PourInCup() {
		cout << "咖啡倒入杯中" << endl;
	}
	// 加辅助料
	virtual void AddSomething() {
		cout << "加糖,加牛奶" << endl;
	}
};

// 冲泡咖啡
class Tea : public DrinkTemplate {
public:
	// 煮水
	virtual void BoildWater() {
		cout << "煮自来水" << endl;
	}
	// 冲泡
	virtual void Brew() {
		cout << "冲泡茶叶" << endl;
	}
	// 倒入杯中
	virtual void PourInCup() {
		cout << "茶水倒入杯中" << endl;
	}
	// 加辅助料
	virtual void AddSomething() {
		cout << "加蜂蜜,加柠檬" << endl;
	}
};

int main(void)
{
	Tea* tea = new Tea;
	tea->Meke();

	cout << endl;

	Coffee* coffee = new Coffee;
	coffee->Meke();

	return 0;
}

C++学习日记12——设计模式_第39张图片

7.2 策略模式

1、定义

篥略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化

2、代码

C++学习日记12——设计模式_第40张图片

#include 
using namespace std;

class WeaponStrategy
{
public:
	virtual void UseWeapon() = 0;
};

class Knife : public WeaponStrategy {
public:
	virtual void UseWeapon() {
		cout << "使用刀" << endl;
	}
};

class AK47 : public WeaponStrategy {
public:
	virtual void UseWeapon() {
		cout << "使用AK47" << endl;
	}
};

class Character {
public:
	void setWeapon(WeaponStrategy* weapon) {
		this->pWeapon = weapon;
	}
	void ThrowWeapon() {
		this->pWeapon->UseWeapon();
	}
public:
	WeaponStrategy* pWeapon;
};
int main(void)
{
	Character* character = new Character;

	WeaponStrategy* knife = new Knife;
	WeaponStrategy* ak47 = new AK47;

	character->setWeapon(knife);
	character->ThrowWeapon();

	character->setWeapon(ak47);
	character->ThrowWeapon();

	delete ak47;
	delete knife;
	delete character;

	return 0;
}

7.3 命令模式

        将一个请求封装为一个对象,从而让我们可用不同的请求对客户进行参数化;对请求排队或者记录请求日志,以及支持可撤销的操作。命令模式是一种对象行为型模式,其别名为动作 (Action) 模式或事务 (Transaction) 模式。

        命令模式可以将请求发送者和接收者完全解耦,发送者与接收者之间没有直接引用关系,发送请求的对象只需要知道如何发送请求,而不必知道如何完成请求。(传输协议等可以用用这个)

#include 
#include 
#include 
using namespace std;

// 协议处理类
// 通过客户端传来的协议的编号调用某个函数(协议类处理请求)
class handle_client_protocol {
public:
	// 处理增加金币的协议
	void AddMoney() 
	{
		cout << "给玩家增加金币!" << endl;
	}

	// 处理增加钻石
	void AddDiamond() 
	{
		cout << "给玩家增加钻石!" << endl;
	}

	// 处理玩家装备
	void AddEquipment() 
	{
		cout << "给玩家穿装备!" << endl;
	}

	void AddLevel()
	{
		cout << "给玩家升级!" << endl;
	}
};


// 命令接口
class abstractCommand {
public:
	virtual void handle() = 0;  // 处理客户端请求的接口
};

// 处理增加金币的请求
class add_money_command : public abstractCommand {
public:
	add_money_command(handle_client_protocol* protocol) {
		this->pProtocol = pProtocol;
	}
	virtual void handle() {
		this->pProtocol->AddMoney();
	}
public:
	handle_client_protocol* pProtocol;
};

// 处理增加钻石的请求
class add_diamond_command : public abstractCommand {
public:
	add_diamond_command(handle_client_protocol* protocol) {
		this->pProtocol = pProtocol;
	}
	virtual void handle() {
		this->pProtocol->AddDiamond();
	}
public:
	handle_client_protocol* pProtocol;
};

// 处理玩家穿装备的请求
class add_equipment_command : public abstractCommand {
public:
	add_equipment_command(handle_client_protocol* protocol) {
		this->pProtocol = pProtocol;
	}
	virtual void handle() {
		this->pProtocol->AddEquipment();
	}
public:
	handle_client_protocol* pProtocol;
};

// 处理玩家升级的请求
class add_level_command : public abstractCommand {
public:
	add_level_command(handle_client_protocol* protocol) {
		this->pProtocol = pProtocol;
	}
	virtual void handle() {
		this->pProtocol->AddLevel();
	}
public:
	handle_client_protocol* pProtocol;
};

// 服务器程序
class Server {
public:
	void addRequest(abstractCommand* command) 
	{
		mCommand.push(command);
	}

	void startHandle() 
	{
		while (!mCommand.empty()) {
			Sleep(2000);
			abstractCommand* command = mCommand.front();
			command->handle();
			mCommand.pop();
		}
	}
public:
	queue mCommand;
};

void test01() {
	handle_client_protocol* protocol = new handle_client_protocol;

	// 客户端增加金币的请求
	abstractCommand* addmoney = new add_money_command(protocol);
	// 客户端增加钻石的请求
	abstractCommand* adddiamond = new add_diamond_command(protocol);
	// 客户端穿装备的请求
	abstractCommand* addequpment = new add_equipment_command(protocol);
	// 客户端升级请求
	abstractCommand* addlevel = new add_level_command(protocol);

	Server* server = new Server;
	
	// 把客户端请求加入到处理的队列中
	server->addRequest(addmoney);
	server->addRequest(adddiamond);
	server->addRequest(addequpment);
	server->addRequest(addlevel);

	// 服务器开始处理请求
	server->startHandle();
}

int main(void)
{
	test01();
	return 0;
}

7.4 观察者模式

随着交通信号灯的变化,汽车的行为也将随之而变化,一盏交通信号灯可以指挥多辆汽车。

观察者模式是用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应。在观察者模式中,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应

C++学习日记12——设计模式_第41张图片

#include 
#include 
#include 
using namespace std;

// 抽象的英雄
class AbstractHero {
public:
	virtual void Update() = 0;
};

// 具体的英雄
class HeroA : public AbstractHero {
public:
	HeroA() {
		cout << "英雄A正在打Boss" << endl;
	}
	virtual void Update() {
		cout << "英雄A停止打Boss" << endl;
	}
};

class HeroB : public AbstractHero {
public:
	HeroB() {
		cout << "英雄B正在打Boss" << endl;
	}
	virtual void Update() {
		cout << "英雄B停止打Boss" << endl;
	}
};

class HeroC : public AbstractHero {
public:
	HeroC() {
		cout << "英雄C正在打Boss" << endl;
	}
	virtual void Update() {
		cout << "英雄C停止打Boss" << endl;
	}
};

// 观察目标对象
class AbstractBoss {
public:
	// 添加观察者
	virtual void addHero(AbstractHero* hero) = 0;
	// 删除观察者
	virtual void deleteHero(AbstractHero* hero) = 0;
	// 通知观察者
	virtual void notify() = 0;
};

// 具体的观察者
class BOSSA : public AbstractBoss {
public:
	virtual void addHero(AbstractHero* hero) {
		pHeroList.push_back(hero);
	}

	virtual void deleteHero(AbstractHero* hero) {
		pHeroList.remove(hero);
	}

	virtual void notify() {
		for (list::iterator it = pHeroList.begin(); it != pHeroList.end(); it++) {
			(*it)->Update();
		}
	}
public:
	list pHeroList;
};

int main(void)
{
	// 创建观察者
	AbstractHero* heroA = new HeroA;
	AbstractHero* heroB = new HeroB;
	AbstractHero* heroC = new HeroC;

	// 创建观察目标
	AbstractBoss* bossA = new BOSSA;
	bossA->addHero(heroA);
	bossA->addHero(heroB);
	bossA->addHero(heroC);

	cout << "hero阵亡..." << endl;
	bossA->deleteHero(heroC);

	cout << "Boss死了...通知其他英雄停止攻击、抢装备" << endl;
	bossA->notify();

	return 0;
}

你可能感兴趣的:(C++,c++)