抽象工厂模式-C++实现

抽象工厂模式是一种创建型设计模式,它提供了一种在不指定具体产品类的情况下创建一系列相关或依赖对象的方法。

抽象工厂模式分为四个角色:抽象工厂具体工厂抽象产品具体产品

抽象工厂和工厂方法其实很类似,但也有一定的区别:
抽象工厂模式关注一系列产品对象的创建
工厂方法模式关注单个产品对象的创建

举例:
假设我们有两个产品族:手机(Phone)和电脑(Laptop),它们有不同的型号:苹果(Apple)和华为(HuaWei)。

// 手机接口-抽象产品
class Phone
{
public:virtual ~Phone() {}virtual void MakeCall() = 0;
};// 电脑接口-抽象产品
class Laptop
{
public:virtual ~Laptop() {}virtual void PlayGame() = 0;
};// 华为手机-具体产品
class HuaWeiPhone: public Phone
{
public:virtual void MakeCall() override{std::cout << "华为手机打电话" << std::endl;}
};// 华为电脑-具体产品
class HuaWeiLaptop: public Laptop
{
public:virtual void PlayGame() override{std::cout << "华为电脑玩游戏" << std::endl;}
};// 苹果手机-具体产品
class ApplePhone: public Phone
{
public:virtual void MakeCall() override{std::cout << "苹果手机打电话" << std::endl;}
};// 苹果电脑-具体产品
class AppleLaptop: public Laptop
{
public:virtual void PlayGame() override{std::cout << "苹果电脑玩游戏" << std::endl;}
};// 抽象工厂
class AbstractFactory
{
public:virtual ~AbstractFactory() {}virtual std::shared_ptr<Phone> CreatePhone() = 0;virtual std::shared_ptr<Laptop> CreateLaptop() = 0;
};// 华为工厂-具体工厂
class HuaWeiFactory: public AbstractFactory
{
public:virtual std::shared_ptr<Phone> CreatePhone() override{return std::make_shared<HuaWeiPhone>();}virtual std::shared_ptr<Laptop> CreateLaptop() override{return std::make_shared<HuaWeiLaptop>();}
};// 苹果工厂-具体工厂
class AppleFactory: public AbstractFactory
{
public:virtual std::shared_ptr<Phone> CreatePhone() override{return std::make_shared<ApplePhone>();}virtual std::shared_ptr<Laptop> CreateLaptop() override{return std::make_shared<AppleLaptop>();}
};

测试

void TestAbstractFactory()
{// 创建苹果工厂std::shared_ptr<AbstractFactory> apple_factory = std::make_shared<AppleFactory>();// 创建华为工厂std::shared_ptr<AbstractFactory> huawei_factory = std::make_shared<HuaWeiFactory>();// 通过苹果工厂创建苹果电脑和苹果手机std::shared_ptr<Phone> apple_phone = apple_factory->CreatePhone();std::shared_ptr<Laptop> apple_laptop = apple_factory->CreateLaptop();// 通过华为工厂创建华为电脑和华为手机std::shared_ptr<Phone> huawei_phone = huawei_factory->CreatePhone();std::shared_ptr<Laptop> huawei_laptop = huawei_factory->CreateLaptop();// 使用苹果电脑和手机apple_phone->MakeCall();apple_laptop->PlayGame();// 使用华为电脑和手机huawei_phone->MakeCall();huawei_laptop->PlayGame();
}

输出:

苹果手机打电话
苹果电脑玩游戏
华为手机打电话
华为电脑玩游戏

我们通过抽象工厂接口创建了一个苹果工厂和华为工厂,又通过华为工厂接口创建了华为电脑和华为手机(苹果同理),这样的话我们就可以使用华为电脑和手机。

通过这种方式,我们就绕开了new的方式去创建对象。

抽象工厂遵循的设计原则:

  • 依赖倒置原则:通过引入抽象接口,实现了具体产品的实现细节与客户端代码(测试代码或使用代码)的解耦。客户端只需要通过抽象接口创建对象,不需要关心具体的产品类。这样就是实现了高层模块(客户端代码)依赖抽象接口,而不依赖具体的低层模块(具体的产品实现)。
  • 开放封闭原则:通过引入抽象接口,允许添加工厂和产品,而不需要修改已有代码,实现了对扩展开放、对修改关闭。
  • 单一职责原则:抽象工厂模式将产品的创建封装在具体工厂类中,每个工厂又负责创建特定的产品族,使得每一个类只有一个职责。
  • 接口隔离原则:通过引入抽象接口,将产品对象的创建方法和具体的实现细节隔离开,客户端代码不需要关心具体产品的实现,只需要和抽象接口进行交互,避免了对不需要的方法进行依赖。

抽象工厂模式适用于以下场景:

  • 系统需要独立于它的产品的创建、组合和表示时
  • 系统需要一组相关产品对象,并且希望统一地对待它们
  • 系统需要在运行时切换不同的产品族

抽象工厂模式的优点:

  • 将客户端代码于具体产品的实现进行解耦,使客户端可以灵活应用各种产品。

缺点:

  • 增加新的产品族比较困难,需要修改抽象工厂的接口
  • 当创建的产品只有一个时,退化成工厂方法模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/148236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7.22 SpringBoot项目实战【收藏 和 取消收藏】

文章目录 前言一、编写控制器二、编写服务层三、Postman测试最后前言 本系统还支持 收藏图书,就是对心仪的书加一下收藏,大家都懂,这是一个很常见的功能。 那么我们来看看怎么来做,先分析一下:【一个人】对【一本书】只需【收藏一次】,但可以【收藏N本】不同的书,收藏…

【Java并发编程六】多线程越界问题

ArrayList()越界错误 import java.util.ArrayList; public class myTest implements Runnable {static ArrayList<Integer> a new ArrayList<>(10);public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(new myTest());T…

Mac M1 M1 pro安装 protobuf 2.5.0

因为项目中的protobuf是2.5.0版本&#xff0c;但是旧版本的protobuf 不支持M1&#xff0c;此时需要修改源码重新编译 操作步骤&#xff1a; 从git上面下载对应版本的protobuf&#xff0c;地址&#xff1a;Release Protocol Buffers v2.5.0 protocolbuffers/protobuf GitHub…

深度学习之基于YoloV5苹果新鲜程度检测识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 深度学习之基于 YOLOv5 苹果新鲜程度检测识别系统介绍YOLOv5 简介苹果新鲜程度检测系统系统架构应用场景 二、功能三、系统四. 总结 一项目简介 深度学习之…

三十一、W5100S/W5500+RP2040树莓派Pico<TCP_Server多路socket>

文章目录 1 前言2 简介2. 1 使用多路socket的优点2.2 多路socket数据交互原理2.3 多路socket应用场景 3 WIZnet以太网芯片4 多路socket设置示例概述以及使用4.1 流程图4.2 准备工作核心4.3 连接方式4.4 主要代码概述4.5 结果演示 5 注意事项6 相关链接 1 前言 W5100S/W5500是一…

c#字符串

字符串比较 namespace demo1 {internal class progrm{static void Main(string[] args){string str "hello world";Console.WriteLine("大写字符{0}",str.ToUpper());Console.WriteLine("小写字符{0}",str.ToLower());Console.WriteLine("…

GitHub如何删除仓库

GitHub如何删除仓库 删除方法第一步第二步第三步 删除方法 第一步 在仓库的界面选择Settings 第二步 选择General,页面拉到最后。 第三步 删除仓库。

C++ 虚函数和多态性

虚函数和多态性 派生类中与基类重名的成员 如果派生类的成员与基类的成员重名&#xff0c;则派生类的成员将隐藏同名的基类成员。 /*正方形类&#xff0c;基类*/ class Square { protected:double L; public:Square() :L{ 4 } {};Square(double a) :L{ a } {}double GetArea…

C#密封类、偏类

C#密封类 在C#中&#xff0c;密封类&#xff08;Sealed Class&#xff09;是一种特殊的类&#xff0c;它阻止其他类继承它。你可以通过在类定义前面加上 sealed 关键字来创建一个密封类。 以下是一个密封类的例子&#xff1a; public sealed class MyClass {// Class member…

【Redis】zset常用命令集合间操作内部编码使用场景

文章目录 前置知识列表、集合、有序集合三者的异同点 普通命令ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZPOPMAXBZPOPMAXZPOPMINBZPOPMINZRANKZREVRANKZSCOREZREMZREMRANGEBYRANKZREMRANGEBYSCOREZINCRBY 集合之间的操作ZINTERSTOREZUNIONSTORE 命令小结内部编码测试内部编…

PyTorch 成功安装验证

一、确认PyTorch版本 安装PyTorch之后&#xff0c;可以运行以下代码来确认PyTorch的版本&#xff1a; import torchprint(torch.__version__)如果没有报错&#xff0c;同时输出了正确版本号&#xff0c;就说明PyTorch已经成功安装了。 二、测试PyTorch基础功能 为了确保PyT…

C/C++---------------LeetCode第LCR. 024.反转链表

反转链表 题目及要求双指针 题目及要求 双指针 思路&#xff1a;遍历链表&#xff0c;并在访问各节点时修改 next 引用指向&#xff0c;首先&#xff0c;检查链表是否为空或者只有一个节点&#xff0c;如果是的话直接返回原始的头节点&#xff0c;然后使用三个指针来迭代整个…

DHCP配置命令

排除IP地址或IP范围&#xff08;保留&#xff09;&#xff1a; Switch(config)#ip dhcp excluded-address 192.168.10.1 192.168.10.10 为地址池取名&#xff1a; Switch(config)#ip dhcp pool name 分配地址范围&#xff1a; Switch(dhcp-config)#network 192.168.10.0 2…

windows 安装 Oracle Database 19c

目录 什么是 Oracle 数据库 下载 Oracle 数据库 解压文件 运行安装程序 测试连接 什么是 Oracle 数据库 Oracle数据库是由美国Oracle Corporation&#xff08;甲骨文公司&#xff09;开发和提供的一种关系型数据库管理系统&#xff0c;它是一种强大的关系型数据库管理系统…

lambda表达式c++

介绍 可调用对象 对于一个表达式&#xff0c;如果可以对其使用调用运算符&#xff08;&#xff09;&#xff0c;则称它为可调用对象。如函数就是一个可调用对象&#xff0c;当我们定义了一个函数f(int)时&#xff0c;我们可以通过f(5)来调用它。 可调用对象有&#xff1a; …

c语言中*p1++和p1++有啥区别

在C语言中&#xff0c;*p1和p1是两个不同的表达式&#xff0c;有以下区别&#xff1a; *p1&#xff1a;这是一个后缀递增运算符的组合。首先&#xff0c;*p1会取出指针p1所指向的值&#xff0c;并且对p1进行递增操作。简而言之&#xff0c;这个表达式会先取出p1指向的值&#x…

43-设计问题-最小栈

原题链接&#xff1a; 198. 打家劫舍 题目描述&#xff1a; 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&a…

基于springboot实现校园在线拍卖系统项目【项目源码】计算机毕业设计

基于springboot实现校园在线拍卖系统演示 Javar技术 JavaScript是一种网络脚本语言&#xff0c;广泛运用于web应用开发&#xff0c;可以用来添加网页的格式动态效果&#xff0c;该语言不用进行预编译就直接运行&#xff0c;可以直接嵌入HTML语言中&#xff0c;写成js语言&…

Java多线程核心技术第一阶段-Java多线程基础 02

接上篇&#xff1a;Java多线程核心技术第一阶段-Java多线程基础 01 3.3 清除中断状态的使用场景 this.interrupted()方法具有清除状态标志值的功能&#xff0c;借用此特性可以实现一些效果。 【示例3.3.1】在MyThread4线程中向list1和list2存放数据&#xff0c;基于单一职责原…

asp.net mvc点餐系统餐厅管理系统

1. 主要功能 ① 管理员、收银员、厨师的登录 ② 管理员查看、添加、删除菜品类型 ③ 管理员查看、添加、删除菜品&#xff0c;对菜品信息进行简介和封面的修改 ④ 收银员浏览、搜索菜品&#xff0c;加入购物车后进行结算&#xff0c;生成订单 ⑤ 厨师查看待完成菜品信息…