设计模式

学习笔记之C++设计模式——创建型模式 📑 [【设计模式】[【设计模式】结构型模式|结构型模式

📑 [【设计模式】[【设计模式】行为型模式|行为型模式

一、工厂模式

简单工厂模式

代码

#include <iostream>
#include "main.h"
using namespace std;
/*
	定义一个水果抽象类。供具体水果实现,和工厂使用
*/
class Fruit {
public:
	virtual void getName() = 0;
 
};
class APPLe : public Fruit{
public:
	virtual void getName() {
		cout << "我是苹果" << endl;
	}
};
class Banana : public Fruit {
public:
	virtual void getName(){
		cout << "我是香蕉" << endl;
	}
};
 
//抽象的工厂类
class AbstractFactory
{
public:
	virtual Fruit  * createFruit() = 0;
 
};
//通过具体的某一产品的工厂生产某种产品
class AppleFactory : public AbstractFactory 
{
public:
	virtual Fruit * createFruit() {
		return new Apple;
	}
};
class BananaFactory : public AbstractFactory
{
public:
	virtual Fruit * createFruit() {
		return new Banana;
	}
};
int main()
{
	//来一个香蕉工厂
	AbstractFactory * bananaFactory = new BananaFactory;
	//给我来一个水果
	Fruit * banana = bananaFactory->createFruit();
	banana->getName();
 
	delete bananaFactory;
	delete banana;
 
	AbstractFactory * appleFactory = new AppleFactory;
	Fruit * apple = appleFactory->createFruit;
	apple->getName(); 
 
 
	system("pause");
	return 0;
}

类图

工厂模式

工厂模式的优缺点

优点

  1. 不需要记住具体类名,甚至连具体参数都不用记忆。
  2. 实现了对象创建和使用的分离。
  3. 系统的可扩展性也就变得个非常好,无需修改接口和原类。

缺点

  1. 增加系统中类的个数,复杂度和理解度增加。

  2. 增加了系统的抽象性和理解难度。

二、抽象工厂模式

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

图例

抽象工厂模式

代码

#include <iostream>
#include "main.h"
using namespace std;
//抽象产品类 供具体产地产品实现
class AbstractApple {
public:
	virtual void getName() = 0;
};
class AbstractBanana {
public:
	virtual void getName() = 0;
};
class AbstractPear {
public:
	virtual void getName() = 0;
};
 
class USAApple : public AbstractApple {
public:
	virtual void getName() {
		cout << "美国苹果" << endl;
	}
};
class ChinaApple : public AbstractApple {
public:
	virtual void getName() {
		cout << "中国苹果" << endl;
	}
};
class JapanApple : public AbstractApple {
public:
	virtual void getName() {
		cout << "日本苹果" << endl;
	}
};
class USABanana : public AbstractBanana {
public:
	virtual void getName() {
		cout << "美国香蕉" << endl;
	}
};
class ChinaBanana : public AbstractBanana {
public:
	virtual void getName() {
		cout << "中国香蕉" << endl;
	}
};
class JapanBanana : public AbstractBanana {
public:
	virtual void getName() {
		cout << "日本香蕉" << endl;
	}
};
class USAPear : public AbstractPear {
public:
	virtual void getName() {
		cout << "美国鸭梨" << endl;
	}
};
class ChinaPear : public AbstractPear {
public:
	virtual void getName() {
		cout << "中国鸭梨" << endl;
	}
};
class JapanPear : public AbstractPear {
public:
	virtual void getName() {
		cout << "日本鸭梨" << endl;
	}
};
//抽象的工厂类,供具体产品族的实现
class AbstractFactory {
public:
	virtual AbstractApple * creatApple() = 0;
	virtual AbstractBanana * creatBanana() = 0;
	virtual AbstractPear * creatPear() = 0;
};
//具体的工厂
class USAFactory : public AbstractFactory {
public:
	virtual AbstractApple * creatApple() {
		return new USAApple;
	}
	virtual AbstractBanana * creatBanana() {
		return new USABanana;
	}
	virtual AbstractPear * creatPear() {
		return new USAPear;
	}
};
class ChinaFactory : public AbstractFactory {
public:
	virtual AbstractApple * creatApple() {
		return new ChinaApple;
	}
	virtual AbstractBanana * creatBanana() {
		return new ChinaBanana;
	}
	virtual AbstractPear * creatPear() {
		return new ChinaPear;
	}
};
class JapanFactory : public AbstractFactory {
public:
	virtual AbstractApple * creatApple() {
		return new JapanApple;
	}
	virtual AbstractBanana * creatBanana() {
		return new JapanBanana;
	}
	virtual AbstractPear * creatPear() {
		return new JapanPear;
	}
};
 
 
int main()
{
	//现在要准备一个 中国的苹果,中国的香蕉
	AbstractApple *AA = NULL;
	AbstractBanana *AB = NULL;
	AbstractPear *AP = NULL;
 
	AbstractFactory *factory = NULL;
	factory = new ChinaFactory;
	//中国的苹果
	AA = factory->creatApple();
	//中国的香蕉
	AB = factory->creatBanana();
	AP = factory->creatPear();
    
	AA->getName();
	AB->getName();
	AP->getName();
 
	delete AA;
	delete AB;
	delete AP;
    delete factory;
 
	system("pause");
	return 0;
}

抽象工厂模式不符合“开闭原则”

抽象工厂模式的优缺点

优点:

  1. 拥有工厂方法模式的优点
  2. 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象
  3. 增加新的产品族很方便,无需修改已有系统,符合“开闭原则”。

缺点:

  1. 增加新的产品结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,带来较大的不便,违背了“开闭原则”。

抽象模式的应用:可以自己写一个计算机产品相关

简单工厂模式 + “开闭原则” = 工厂方法模式

工厂方法模式 + “产品族” = 抽象工厂模式

简单工厂模式(规模较小的模型)

工厂方法模式(中等)

抽象工厂模式(复杂的)

借鉴了《Easy搞定设计模式》

三 单例模式

保证一个类、只有一个实例存在,同时提供能对该实例加以访问的的全局访问方法。

三个要点:

一是某个类只能有一个实例;

二是它必须自行创建这个实例;

三是它必须自行向整个系统提供这个实例。

image-20201119180254196

角色和职责

Singleton(单例):在单例类的内部实现只生成一个实例,同时是他提供一个静态的getInstance()方法,让客户可以访问他的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

单例模式的使用步骤

  1. 构造函数私有化
  2. 提供一个全局的静态方法(全局访问点) 来获取单例对象。
  3. 在类中定义一个静态指针,指向本类的变量的静态变量指针

饿汉模式

理解

主要就是为了只让类只有一个实例而把构造函数私有化。定义一个全局的静态实例。

代码

#include <iostream>
using namespace std;
/*
三个步骤:
	1.构造函数私有化(为了不让在类的外部再创建多余的实例)
	2.提供一个全局的静态类指针指向唯一实例
	3.提供一个全局的静态函数获取实例
*/
class Singleton {
public:
	// 静态类函数 返回静态实例
	static Singleton * getInstance() {
		return instance;
	}
 
private:
	//不让类的外部创建实例
	Singleton() {
		Singleton *single = getInstance();
	}
 
	Singleton getsingle() {
 
	}
	static Singleton * instance; //指向本类的唯一实例指针
};
//静态类变量在类外初始化
Singleton*Singleton::instance = new Singleton;
 
int main()
{
	//通过getInstance()获取实例
	Singleton * s1 = Singleton::getInstance();
	system("pause");
	return 0;
}

懒汉模式

在程序执行期间再去判断是否需要实例。

class Singleton1 {
public:
	//提供一个返回实例的方法
	static Singleton1 * getInstance() {
        // 不确定程序在编译期间是否需要实例
        // 如果是多线程下,需要在这里加锁
		if (instance1 == NULL) {
			instance1 = new Singleton1;
		}
        // 释放锁
		cout << "Singleton1" << endl;
		return instance1;
	}
private:
	Singleton1() {
	}
	static Singleton1 *instance1;
};
//懒汉式的初始化方式 饿汉式在初始化时已经指向了singleton
Singleton1 * Singleton1::instance1 = NULL;

针对单例模式去判断是否是同一实例

Singleton *s1 = Singleton::getinstace();
Singleton *s2 = Singleton::getinstace();
if (s1 == s2 )
    cout << "s1 == s2" << endl;
else
    cout << "s1 != s2" << endl;

单例模式的应用——打印机

用单例模式实现一个打印机程序,用以记录打印的次数和内容

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Printer {
public:
	static Printer * getinstance() {
		return instance;
	}
	void print(string text) {
		cout << "打印的内容为:" << text << endl;
		sequence++;
		cout << "打印机今天使用了" << sequence << "次" << endl;
	}
	static int getSequence() {
		return sequence;
	}
private:
    // 定义一个类去析构单例
	class Garbo {
	private:
		~Garbo() {
			if (instance != NULL) {
				delete instance;
			}
		}
	};
	static Garbo garbo; // 在静态区域开辟一个对象,Garbo
	static int sequence;
	static Printer * instance;
};
int Printer::sequence = 0;
Printer *Printer::instance = new Printer;
Printer::Garbo Printer::garbo;
 
int main()
{
	//三个peple使用打印机
	Printer * p1 = Printer::getinstance();
	p1->print("亿封简历");
 
	Printer *p2 = Printer::getinstance();
	p2->print("一份工作汇报");
 
	Printer *p3 = Printer::getinstance();
	p3->print("离职申请");
 
	system("pause");
	return 0;
}

以上就是几种常见的创建型设计模式。