C++设计模式 --1.工厂模式和单例模式

2024-01-09

1.工厂模式

简单工厂模式

抽象产品类

//定义一个抽象水果类 --抽象产品角色
class AbstractFruit
{
public:
	virtual void showFruitName()=0;//抽取出产品的公共行为, 纯虚函数
    virtual ~AbstractFruit(){};//虚析构函数  -- 做为顶层基类,一定要显示定义虚析构函数,防止内存溢出
};

具体产品类

//苹果类 -- 具体产品角色
class Apple : public AbstractFruit
{
public:
	virtual void showFruitName() override {
		cout << "this is an apple" <<endl;
	}
};

//鸭梨类 -- 具体产品角色
class Pear : public AbstractFruit
{
public:
	virtual void showFruitName() override {
		cout << "this is a pear" <<endl;
	}
};

//香蕉类 -- 具体产品角色
class Banana : public AbstractFruit
{
public:
	virtual void showFruitName() override {
		cout << "create bananas" <<endl;
	}
};

工厂

//工厂类 --工厂角色
/*
	1.内含一个生成具体产品对象的静态方法,根据传入的参数判断要生成的哪种产品,并返回对象指针
	2.通过抽象产品类类型指针来接收具体产品的堆内存地址,达到多态目的。
*/
class FruitFactory
{
public:
	static AbstractFruit* makeFruit(string fruitType){
		if(fruitType == "apple"){
			return new Apple;
		}else if(fruitType == "pear") {
			return new Pear;
		}else if(fruitType == "banana") {
			return new Banana;
		}else {
			return nullptr;
		}
	}
};

客户端

//客户端
/*
  1.通过工厂类调用其创建产品的静态方法,并根据传入的参数 生成具体的产品对象
*/
int main(int argc, char *argv[])
{
	AbstractFruit* fruit = FruitFactory::makeFruit("apple");
	if(fruit != nullptr)
		fruit->showFruitName();
	delete fruit;
	cout << "==============" <<endl;
	fruit = FruitFactory::makeFruit("banana");
	if (fruit != nullptr)
		fruit->showFruitName();
	delete fruit;
	return 0;
}

在这里插入图片描述
简单工厂模式 不属于 GoF的23种设计模式。
简单工厂模式 有以下三种角色:
抽象产品角色 :简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
具体产品角色 :简单工厂模式所创建的具体实例对象。
工厂角色 :简单工厂模式的核心,它负责创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需的产品对象。

优点
1.实现客户端和具体实现类解耦;不需要关注对象的创建细节;
2.通过客户端 传入参数 让工厂知道应该创建什么类型对象。
缺点
1.当每增加新类型的具体产品时,需要修改工厂类的中if…else 源代码,不符合开闭原则。
2.这个类过重(很多if…else,及负责生成所有产品),将各种产品对象的初始化集中在一个类中实现,违反了 单一职责原则;
3.并且这个类发生问题,会影响很多使用这个工厂的模块。

简单工厂模式 UML类图:
在这里插入图片描述

工厂方法模式

工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工厂方法模式可以使系统不修改具体工厂角色的情况下引进新的产品。

工厂方法模式是 简单工厂模式 + 开闭原则 +单一职责原则。
工厂方法模式有以下四个角色:
1.抽象工厂角色 :工厂方法模式的核心,负责定义公共接口,任何具体工厂类都必须实现这个接口。
2.具体工厂角色 :具体工厂是抽象工厂的一个实现,负责实例化产品对象。
3.抽象产品角色 :工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
4.具体产品角色 :工厂方法模式所创建的具体实例对象。
工厂方法模式的优点:

  1. 符合开闭原则,即抽象工厂中的公共接口是闭的,针对新种类产品,可以通过增加具体工厂来生产,这个是开的,实现可扩展。
  2. 符合单一职责原则,即每个具体工厂只负责生产某一种类的产品。而不像简单工厂模式中在 工厂类中负责生成所有种类产品。
    工厂方法模式的缺点:
  3. 类的成本个数增加,导致类越来越多,增加维护成本。

代码案例:
抽象工厂

//抽象水果工厂
class AbstractFruitFactory
{
public:
	virtual AbstractFruit* makeFruit() = 0;//生产水果的纯虚函数(也叫接口)
	virtual ~AbstractFruitFactory(){};
};

具体工厂

//负责具体生产苹果的苹果工厂
class AppleFactory : public AbstractFruitFactory
{
public:
	AbstractFruit* makeFruit() //实现接口
	{
		return new Apple;
	}
};
//负责具体生产鸭梨的鸭梨工厂
class PearFactory : public AbstractFruitFactory
{
public:
	AbstractFruit* makeFruit() //实现接口
	{
		return new Pear;
	}
};

//负责具体生产香蕉的香蕉工厂
class BananaFactory : public AbstractFruitFactory
{
public:
	AbstractFruit* makeFruit() //实现接口
	{
		return new Banana;
	}
};

抽象产品

//抽象产品
class AbstractFruit
{
public:
	virtual void showFruitName()=0;
    virtual ~AbstractFruit(){};
};

具体产品

//苹果类
class Apple : public AbstractFruit
{
public:
	void showFruitName()
	{
		cout << "this is an apple" << endl;
	}
};
//鸭梨类
class Pear : public AbstractFruit
{
public:
	void showFruitName()
	{
		cout << "this is a pear" << endl;
	}
};
//香蕉类
class Banana : public AbstractFruit
{
public:
	void showFruitName()
	{
		cout << "this is a banana" << endl;
	}
};

客户端调用:

//客户端 --调用
int main(int argc, char *argv[])
{	
	//创建一个抽象工厂类型指针变量
	AbstractFruitFactory* abstractFruitFactory = nullptr;
	//创建一个抽象产品类型指针变量
	AbstractFruit* abstractFruit = nullptr;
	
	//创建生产具体某种产品的工厂类(苹果类),让抽象工厂类型指针指向具体工厂类的对象,从而实现多态
	abstractFruitFactory = new AppleFactory;
	abstractFruit = abstractFruitFactory->makeFruit();

	abstractFruit->showFruitName();

	delete abstractFruitFactory;
	delete abstractFruit;

	cout << "=====================" << endl;
	
	//创建生产具体某种产品的工厂类(鸭梨类),让抽象工厂类型指针指向具体工厂类的对象,从而实现多态
	abstractFruitFactory = new PearFactory;
	abstractFruit = abstractFruitFactory->makeFruit();

	abstractFruit->showFruitName();
	
	delete abstractFruitFactory;
	delete abstractFruit;

	cout << "=====================" << endl;

	//创建生产具体某种产品的工厂类(香蕉类),让抽象工厂类型指针指向具体工厂类的对象,从而实现多态
	abstractFruitFactory = new BananaFactory;
	abstractFruit = abstractFruitFactory->makeFruit();

	abstractFruit->showFruitName();

	delete abstractFruitFactory;
	delete abstractFruit;
	
	return 0;
}

在这里插入图片描述
工厂方法模式UML类图:
在这里插入图片描述

抽象工厂模式

抽象工厂针对的是产品族,而不是产品等级结构。
在这里插入图片描述
抽象工厂模式和工厂方法模式一样也有以下四个角色:
1.抽象工厂角色 :抽象工厂模式的核心,负责定义公共接口,任何具体工厂类都必须实现这个接口。
2.具体工厂角色 :具体工厂是抽象工厂的一个实现,负责实例化同一产品族的对象。
3.抽象产品角色 :抽象工厂模式所创建的相同产品等级对象的父类,它负责描述所有相同产品等级实例所共有的公共接口。
4.具体产品角色 :抽象工厂模式所创建的具体实例对象。

可以说 抽象工厂模式是工厂方法模式的升级版。抽象工厂模式指针的是产品族符合开闭原则,而工厂方法模式针对的是多个系列产品符合开闭原则。

代码演示实例:
抽象产品

//抽象苹果类
class AbstractApple
{
public:
	virtual void showName() = 0;
	virtual ~AbstractApple(){};
};

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

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

具体产品`:

//中国苹果
class ChinaApple : public AbstractApple
{
public:
	void showName()
	{
		cout << "this is a ChinaApple" << endl;	
	}
};

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

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


//美国苹果
class AmericaApple : public AbstractApple
{
public:
	void showName()
	{
		cout << "this is an AmericaApple" << endl;
	}
};


//美国鸭梨
class AmericaPear : public AbstractPear
{
public:
	void showName()
	{
		cout << "this is an AmericaPear" << endl;	
	}
};

//美国香蕉
class AmericaBanana : public AbstractBanana
{
public:
	void showName()
	{
		cout << "this is an AmericaBanana" << endl;
	}
};

//日本苹果
class JapanApple : public AbstractApple
{
public:
	void showName()
	{
		cout << "this is a JapanApple" << endl;
	}
};

//日本鸭梨
class JapanPear : public AbstractPear
{
public:
	void showName()
	{
		cout << "this is a JapanPear" << endl;
	}
};

//日本香蕉
class JapanBanana : public AbstractBanana
{
public:
	void showName()
	{
		cout << "this is a JapanBanana" << endl;
	}
};

抽象工厂 :

//抽象工厂类
class AbstractFruitFactory
{
public:
	virtual AbstractApple * createApple() = 0;
	virtual AbstractPear * createPear() = 0;
	virtual AbstractBanana * createBanana() = 0;
	virtual ~AbstractFruitFactory(){};
};

具体工厂 :

//中国工厂
class ChinaFruitFactory : public AbstractFruitFactory
{
public:
	AbstractApple * createApple()
	{
		return new ChinaApple;
	};

	AbstractPear * createPear()
	{
		return new ChinaPear;
	};

	AbstractBanana* createBanana()
	{
		return new ChinaBanana;
	};
};

//美国工厂
class AmericaFruitFactory  : public AbstractFruitFactory
{
public:
	AbstractApple * createApple()
	{
		return new AmericaApple;
	};

	AbstractPear * createPear()
	{
		return new AmericaPear;
	};

	AbstractBanana* createBanana()
	{
		return new AmericaBanana;
	};
};

//日本工厂
class JapanFruitFactory : public AbstractFruitFactory
{
public:
	AbstractApple* createApple()
	{
		return new JapanApple;
	};

	AbstractPear* createPear()
	{
		return new JapanPear;
	};

	AbstractBanana* createBanana()
	{
		return new JapanBanana;
	};
};

封装的测试函数:

void testAbstractFactory() {
	AbstractFruitFactory* abstractFruitFactory = nullptr;
	AbstractApple* apple = nullptr;
	AbstractPear* pear = nullptr;
	AbstractBanana* banana = nullptr;

	abstractFruitFactory = new ChinaFruitFactory;
	apple = abstractFruitFactory->createApple();
	apple->showName();
	pear = abstractFruitFactory->createPear();
	pear->showName();
	banana = abstractFruitFactory->createBanana();
	banana->showName();

	delete abstractFruitFactory;
	delete apple;
	delete pear;

	cout << "=======================" << endl;

	abstractFruitFactory = new AmericaFruitFactory;
	apple = abstractFruitFactory->createApple();
	apple->showName();
	pear = abstractFruitFactory->createPear();
	pear->showName();
	banana = abstractFruitFactory->createBanana();
	banana->showName();

	delete abstractFruitFactory;
	delete apple;
	delete pear;

	cout << "=======================" << endl;

	abstractFruitFactory = new JapanFruitFactory;
	apple = abstractFruitFactory->createApple();
	apple->showName();
	pear = abstractFruitFactory->createPear();
	pear->showName();
	banana = abstractFruitFactory->createBanana();
	banana->showName();

	delete abstractFruitFactory;
	delete apple;
	delete pear;
}

客户端--调用

int main(int argc, char *argv[])
{
	testAbstractFactory();
	return 0;
}

在这里插入图片描述
抽象工厂模式UML类图:
在这里插入图片描述

2.单例模式

懒汉式

代码示例如下:

LazySingleton类

//懒汉式
#include <iostream>
using namespace std;

class LazySingleton
{
private:
	LazySingleton(){cout << "LazySingleton constructor" << endl;};//私有化构造函数
	~LazySingleton(){};//私有化析构函数
public:
	static LazySingleton* getSingleton()
	{
		if(singleton == nullptr)
		{
			cout << "生成单例对象" << endl;
			singleton = new LazySingleton;
		}
		return singleton;
	}

private:
	static LazySingleton* singleton;//声明
};

//定义静态成员变量
LazySingleton*  LazySingleton::singleton = nullptr; //在main函数执行前会进行静态成员的初始化

测试调用

void testLazySingleton()
{
	//LazySingleton lazySingleton;			//编译不过,构造函数私有化不能在类定义的外部创建类的实例
	//LazySingleton* p1 = new LazySingleton;//编译不过,因为右值要触发在堆上创建类的实例对象,并调用构造函数初始化
	//LazySingleton* p2;//可以,因为它并不会创建类的对象,只是定义了一个类类型的指针变量

	LazySingleton* f1 = LazySingleton::getSingleton();
	LazySingleton* f2 = LazySingleton::getSingleton();
	if(f1 == f2)
	{
		cout << "f1 和 f2 指向的内存地址相同" << endl;
	}else {
		cout << "f1 和 f2 指向的内存地址不相同" << endl;
	}
}
int main(int argc, char *argv[])
{
	cout << "main function ...." << endl;
	testLazySingleton();
	return 0;
}

编译命令 :g++ -std=c++11 singleton.cpp -o singleton
打印输出
在这里插入图片描述

饿汉式

代码示例如下:

HungrySingleton类

#include <iostream>
using namespace std;
class HungrySingleton
{
private:
	HungrySingleton(){ cout << "HungrySingleton constructor" << endl;};//保证构造函数私有
	~HungrySingleton(){};//析构函数私有
public:
	static HungrySingleton* getSingleton()
	{
		return singleton;
	}
private:
	static HungrySingleton* singleton;//声明
};

//定义静态成员变量
HungrySingleton*  HungrySingleton::singleton = new HungrySingleton;//在main函数执行前会进行静态成员的初始化,会调用HungryFactory类的私有构造函数初始化对象
//上面这一句,右值为啥可以写new HungryFactory,因为这句静态成员变量的定义,相当于它仍然在类的作用域范围内。可以访问到私有构造函数。

测试调用

void testHungrySingleton()
{
	//HungrySingleton hungrySingleton;//编译不过,构造函数私有化不能在类定义的外部创建类的实例
	//HungrySingleton* p3 = new HungrySingleton;//编译不过,同上
	//HungrySingleton* p4;//可以,因为它并不会创建类的对象,只是定义了一个类类型的指针变量

	HungrySingleton* f3 = HungrySingleton::getSingleton();
	HungrySingleton* f4 = HungrySingleton::getSingleton();
	if(f3 == f4)
	{
		cout << "f3 和 f4 指向的内存地址相同" << endl;
	}else {
		cout << "f3 和 f4 指向的内存地址不相同" << endl;
	}
}

int main(int argc, char *argv[])
{
	cout << "main function ...." << endl;
	testHungrySingleton();
	return 0;
}

编译命令 :g++ -std=c++11 singleton.cpp -o singleton
打印输出
在这里插入图片描述
懒汉式的特点:
1.私有化构造函数和析构函数。
2.定义一个单例对象的类类型指针的静态成员变量,并指向空地址。
3.提供静态获取单例对象的函数
饿汉式的特点:
1.私有化构造函数和析构函数。
2.定义一个单例对象的类类型指针的静态成员变量,并初始化为单例对象。
3.提供静态获取单例对象的函数。

两者的不同点:
懒汉式 是在程序中首次需要时才进行单例对象的生成,生成的时期是在main函数执行后。
饿汉式 是在程序加载时进行的静态成员变量的初始化生成的,生成的时期是在main函数执行前。
懒汉式 是线性不安全的,而饿汉式是线程安全的。

关于单例对象的内存释放问题:
由于整个程序运行期间 都是公用这个类的一个实例对象。私有化析构函数的目的就是防止人为手动删除单例对象,以至于
别人获取时出现失败。故而不提供公用的析构函数,那么堆内的这个单例对象,只有在程序结束时,由操作系统进行单例
对象内存回收,不用担心会发生内存泄漏,因为这个类的实例对象 自始至终只有一份,占不了多大内存。因为内存泄漏的
发生原因是指的堆中非单例对象,不断地创建新对象,程序不再使用时,也没有手动干预进行堆内存释放。导致日积月
累,堆内存被占用完毕,进而发生堆内存泄漏。
内存泄漏 只发生于 堆内存。这里所说的内存泄漏 都是指的堆内存泄漏。

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

C++设计模式 --1.工厂模式和单例模式 的相关文章

随机推荐

  • SQL 解析与执行流程

    一 前言 在先前的技术博客中 我们已经详细介绍过数据库的 parser 模块与执行流程 用户输入的 SQL 语句通过词法解析器生成 token 再通过语法分析器生成抽象语法树 AST 经过 AST 生成对应的 planNode 最后执行 p
  • DreadHunger恐惧饥荒海上狼人杀服务器搭建架设教程windows系统

    DreadHunger 恐惧饥荒海上狼人杀服务器搭建架设教程windows系统 大家好我是艾西 在11月底我有发文 DreadHunger 恐惧饥荒海上狼人杀官方停服的消息 当时在官方的公告模版中公布了在2024年一月一日会将服务端公开让喜
  • 基于PI控制器的光伏并网逆变器系统simulink建模与仿真

    目录 1 算法仿真效果 2 MATLAB源码 3 算法概述 4 部分参考文献 1 算法仿真效果 matlab2022a仿真结果如下
  • 智慧工业之智慧物流解决方案-新导物联

    新导物联智慧物流解决方案是一种基于智能技术和物联网的创新解决方案 旨在提升工业物流运作的效率和可视化管理能力 为企业提供更智能化 高效化的物流服务 方案背景 传统的工业物流流程通常面临着诸多问题 如物料管理不规范 信息流不畅 运输效率低下等
  • 软件测试开发/全日制/测试管理丨性能测试

    性能测试是软件测试中的一项重要活动 旨在评估系统在不同条件下的性能 稳定性和可伸缩性 通过模拟实际用户负载 性能测试有助于发现潜在的性能瓶颈和优化空间 确保系统能够在各种情况下高效运行 性能测试的主要类型 负载测试 通过逐渐增加用户负载 测
  • 【网络安全】web漏洞-xml外部实体注入(XXE)

    web漏洞 xml外部实体注入 XXE 目录 web漏洞 xml外部实体注入 XXE 概念 危害 检测方法 利用方法 漏洞利用 xxe lab 有回显情况 无回显情况 pikachu靶场
  • 盘点那些年我们一起玩过的网络安全工具

    大家好 我是IT共享者 这篇文章给大家盘点那些年 我们一起玩过的网络安全工具 一 反恶意代码软件 1 Malwarebytes 这是一个检测和删除恶意的软件 包括蠕虫 后门 流氓 拨号器 间谍软件等等 快如闪电的扫描速度 具有隔离功能 并让
  • 软件测试开发/全日制/测试管理丨用户端 Web 自动化测试

    随着Web应用的普及和不断发展 用户端Web自动化测试成为确保Web应用质量的重要手段 这种测试方法不仅提高了测试效率 也帮助团队及时发现和解决潜在问题 确保用户体验的连贯性和稳定性 工具选择 用户端Web自动化测试的第一步是选择适当的工具
  • macOS系统记录matplotli报错及安装处理

    报错如下 mac 系统 matplatlib ImportError dlopen 解决方法 1 pip3 uninstall matplatlib 2 强制安装 先升级最新版本pip pip3 install force reinstal
  • 新导物联智慧文物库房管理系统

    该新导文物库房管理系统应用了多种技术来实现高效 安全和智能化的文物库房管理 以下是其中一些重要的技术 射频识别 RFID 技术 RFID技术用于对文物进行标识和跟踪 每件文物都被附加有RFID标签 这样系统可以通过读取标签上的信息来追踪文物
  • 半导体洁净车间洁净区装修要点

    随着科技的飞速发展 半导体行业作为电子产业的核心领域 其生产环境的洁净度要求越来越高 半导体洁净车间的装修设计不仅关乎产品的质量和性能 还直接影响到生产效率和成本控制 因此 S ICOLAB喜格 在洁净区装修过程中 必须遵循一系列严格的要点
  • 如何用GPT给论文降重

    大家好 今天来聊聊如何用GPT给论文降重 希望能给大家提供一点参考 以下是针对论文重复率高的情况 提供一些修改建议和技巧 可以借助此类工具 如何用GPT给论文降重 一 引言 随着人工智能技术的不断发展 GPT等自然语言处理模型在论文降重领域
  • 成为一个黑客,就按照这个路线来!

    前几天一个同学在聊天中提到毕业后想要从事网络安全方向的工作 虽然他本身也是学计算机的 但是又怕心有余而力不足 因为 从事网络安全方面的工作向来起点都比较高 大学里少有开设这类课程的 在学校能够学到的知识比较有限 网上的关于这方面课程的质量又
  • Commander One for Mac:强大的双窗格文件管理器,让你的工作效率倍增!

    Commander One for Mac是一款功能强大的文件管理工具 具有以下主要功能 双窗格设计 主界面分为两个窗格 用户可以在左侧窗格中导航和浏览文件系统的目录结构 在右侧窗格中查看文件和文件夹的内容 文件操作 用户可以通过简单的点击
  • 鉴源论坛 · 观模丨浅谈Web渗透之信息收集(下)

    作者 林海文 上海控安可信软件创新研究院汽车网络安全组 版块 鉴源论坛 观模 社群 添加微信号 TICPShanghai 加入 上海控安51fusa安全社区 信息收集在渗透测试过程中是最重要的一环 浅谈web渗透之信息收集 将通过上下两篇
  • python大作业有哪些题目,500行代码python大作业

    大家好 本文将围绕python大作业有哪些题目展开说明 500行代码python大作业是一个很多人都想弄明白的事情 想搞清楚python大作业100行代码需要先了解以下几个事情 Source code download 本文相关源码 完整项
  • 真的干不过,00后整顿职场已经给我卷麻了,想离职了...

    在程序员职场上 什么样的人最让人反感呢 是技术不好的人吗 并不是 技术不好的同事 我们可以帮他 是技术太强的人吗 也不是 技术很强的同事 可遇不可求 向他学习还来不及呢 真正让人反感的 是技术平平 却急于表现自己的人 每天加班到12点 在老
  • 【C++之单例模式】

    C 之单例模式 前言 介绍 1 单例模式是什么 1 1 实现单例模式的三个要点 1 2 单例模式分类 2 懒汉式 2 1 懒汉实现
  • 智能数据分析系统:揭秘最强AI助力企业腾飞的秘密武器

    现代企业离不开数据 而数据的分析与应用更是成为企业走向成功的关键之一 然而 随着数据量的不断增长 传统的数据分析方法已经无法满足企业的需求 这时 智能数据分析系统应运而生 成为企业决策的得力助手 那么 智能数据分析系统究竟是如何帮助企业实现
  • C++设计模式 --1.工厂模式和单例模式

    文章目录 1 工厂模式 简单工厂模式 工厂方法模式 抽象工厂模式 2 单例模式 懒汉式 饿汉式 1 工厂模式 简单工厂模式