学习视频链接

黑马程序员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 软件建模的实现过程

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

二、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

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

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

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

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

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

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

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

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

四、类图

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

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

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

4.1 类的表示法

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

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

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

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

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

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

4.3 类之间的关系实现关系

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

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

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

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

class BMW {
public:void run() {cout << "BWM车开去上班" << endl;}
};class Person {
public:void GoWork(BMW *car) {car->run();}
};

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

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

class BMW {
public:void run() {cout << "BWM车开去上班" << endl;}
};class Person {
public:void GoWork() {car->run();}
public:BMW *car;
};

4.6 关联关系的名称

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

4.7 关联关系的角色

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

4.8 关联关系的多重性

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

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

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

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

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

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

4.10 练习

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

三、设计模式概述

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

招式: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 设计模式总览表

四、面向对象设计原则

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

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

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

4.1 面向对象设计原创表

4.2 开闭原则

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

#include <iostream>
#include <string>
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 <iostream>
#include <string>
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 <iostream>
#include <string>
#include <vector>
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<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {if ((*it)->getQulity() == quality) {return* it;}}return NULL;}~Mediator() {for (vector<AbstractBuilding*>::iterator it = vBuilding.begin(); it != vBuilding.end(); it++) {if (*it != NULL) {delete* it;}}}
public:vector<AbstractBuilding*> 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;
}

4.4 合成复用原则

继承和组合优先使用组合

#include <iostream>
#include <string>
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 依赖倒转原则

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

1、原来的写法

#include <iostream>
#include <string>
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 <iostream>
#include <string>
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、类图

5、代码

#include <iostream>
#include <string>
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、图示

2、优点

符合开闭原则

3、缺点

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

4、代码

#include <iostream>
#include <string>
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、概念

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

2、代码

#include <iostream>
#include <string>
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 <iostream>
#include <string>
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;
}

添加一些内容

#include <iostream>
#include <string>
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 0static 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;
}

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

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

4、优缺点

(1) 饿汉式

优点 :

线程安全

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

缺点 :

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

(2) 懒汉式

优点:

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

缺点:

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

六、结构型设计模式

6.1 代理模式

1、定义

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

2、代码

#include <iostream>
#include <string>
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 打开;

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

#include <iostream>
#include <string>
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 <iostream>
#include <vector>
#include <algorithm>
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<int> v;for (int i = 0; i < 10; i++) {v.push_back(i);}for_each(v.begin(), v.end(), Adapter());return 0;
}

2、不把100写死的改进

#include <iostream>
#include <vector>
#include <algorithm>
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<int> v;for (int i = 0; i < 10; i++) {v.push_back(i);}for_each(v.begin(), v.end(), MyBind2nd(10));return 0;
}

6.4 装饰模式

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

#include <iostream>
#include <list>
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;
}

七、行为模式

7.1 模板方法模式

1、定义

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

2、代码

#include <iostream>
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;
}

7.2 策略模式

1、定义

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

2、代码

#include <iostream>
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 <iostream>
#include <queue>
#include <Windows.h>
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<abstractCommand*> 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 观察者模式

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

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

#include <iostream>
#include <list>
#include <Windows.h>
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<AbstractHero*>::iterator it = pHeroList.begin(); it != pHeroList.end(); it++) {(*it)->Update();}}
public:list<AbstractHero*> 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++学习日记12——设计模式相关推荐

  1. 蓝桥直通车学习日记12.13

    蓝桥直通车学习日记(12.13) 添加注释的方法 添加注释的方法有两种 单行注释 多行注释 // 这是一个单行注释 /*这是一个多行注释*/ 现代模式, "use script" ...

  2. 学习日记12/29,好日子呀好日子

    今天没有别的东西全是dfs,刚学嘛多搞点练一下呗 题目描述 由数字 00 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 11 构成,围圈时只走上下左右 44 个方向.现要求把闭合圈内的所有空间都填写 ...

  3. Web安全 学习日记12 - 文件包含(File Inclusion)

    文章目录 文件包含(File Inclusion) 什么是文件包含漏洞? 常用的文件包含函数有哪些? 文件包含漏洞的分类? 文件包含漏洞有哪些防护措施? DVWA靶场下的文件包含漏洞 Low Medi ...

  4. (学习日记)2023.4.12

    写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈. 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈. 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录, ...

  5. GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考

    GPU(CUDA)学习日记(十一)------ 深入理解CUDA线程层次以及关于设置线程数的思考 标签: cuda存储线程结构网格 2012-12-07 16:30 6298人阅读 评论(4)收藏 举 ...

  6. GPU(CUDA)学习日记(九)------ CUDA存储器模型

    GPU(CUDA)学习日记(九)------ CUDA存储器模型 标签: cuda存储bindingcache编程api 2012-09-27 10:53 1677人阅读 评论(1) 收藏 举报 分类 ...

  7. 分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(12月12日-12月18日)

    分享Silverlight/WPF/Windows Phone/HTML5一周学习导读(12月12日-12月18日) 本周Silverlight学习资源更新 Silverlight学习小记 阿里山地方 ...

  8. FireBird Embedded学习日记

    FireBird Embedded学习日记   FireBird简介 Firebird是一个真正的关系数据库,支持存储过程.视图.触发器.事务等大型关系数据库的所有特性:不用考虑授权费用(免费),不用 ...

  9. 爬虫学习日记1-豆瓣top250电影信息爬取

    @ 爬虫学习日记1-豆瓣top250电影信息爬去 学习任务:结合requests.re两者的内容爬取https://movie.douban.com/top250里的内容, 要求抓取名次.影片名称.年 ...

最新文章

  1. JAVA中流水账的实现_流水账式java基础Summary
  2. php代码规范的书籍,php基本代码规范——PSR-1
  3. 解决 Let’s Encrypt SSL 证书配置错误
  4. 教表弟用Python写了个“飞机大战”游戏!表弟:可以拜你为师吗?
  5. Python基础之:Python中的模块
  6. java 线程组作用_Java线程组(ThreadGroup)使用
  7. linux网络编程函数——地址复用setsockopt()
  8. android 换到iphone,从安卓换到苹果到底是什么感受?最后一个让我彻底放弃了iPhone!...
  9. oracle虚拟机配置,虚拟机安装和配置Oracle PDF 下载
  10. python discover()没有加载测试用例_Python系统学习 - Unittest
  11. Redis进程异常退出排查
  12. autojs识别数字ocr
  13. 简单游戏(easygame)
  14. 灰度思维,黑白决策(上)
  15. android 短信拦截删除,无需安装任何App!教你一招杜绝垃圾电话短信
  16. 代码随想录第十一天 LeetCode 20、1047、150(栈)
  17. excel日期怎么间隔填充_系列或相同日期的自动填充Excel日期
  18. SQL查询学生表中每课大于85分的同学名称
  19. HC-SR04超声波模块的使用(stm32f103c8t6/HAL)(超详细)
  20. 软件测试周刊(第59期):觉得自己生活的很好吗?为什么视而不见?

热门文章

  1. YOLO算法之YOLOv3精讲
  2. 经济学入门概念及原理-1
  3. 快乐地打牢基础(5)——割点和桥
  4. 大连民族大学计算机毕业论文范文,大连民族大学本科毕业设计论文.doc
  5. 一些有用的安全工具和链接
  6. 前端计算色系渐变颜色
  7. 将钱从余额宝转入股市恐成炮灰
  8. 4am永远 鼠标按键设置_PEL常规赛落幕,4AM挺进决赛,不愧是韦神的战队人人玩雷...
  9. CAD软件问题处理方法
  10. vimplus git clone 速度慢 失败