【设计模式 03】抽象工厂模式

一个具体的工厂,可以专门生产单一某一种东西,比如说只生产手机。但是一个品牌的手机有高端机、中端机之分,这些具体的属于某一档次的产品都需要单独建立一个工厂类,但是它们之间又彼此关联,因为都共同属于一个品牌。我们说这种叫做“多类”对象

除了手机之外,还有比如沙发、茶几、椅子,不同于手机的高端型号和低端型号,取而代之的可以是不同的样式风格,比如古典风格的和现代风格的。每一种风格的产品都需要单独建立一个工厂类,但是他们本质上都属于同一样东西。我们可以从这个角度理解“多类对象”,即,就是同一对象的多种类别。

图中包含以下元素:

  • 抽象产品接口:AbstractProduct
  • 具体产品类:ConcreteProduct
  • 抽象工厂接口:AbstractFactory
  • 具体工厂类:ConcreateFactory

 Java代码:

// 1. 定义抽象产品
// 抽象产品A
interface ProductA {void display();
}// 抽象产品B
interface ProductB {void show();
}// 2. 实现具体产品类
// 具体产品A1
class ConcreteProductA1 implements ProductA {@Overridepublic void display() {System.out.println("Concrete Product A1");}
}// 具体产品A2
class ConcreteProductA2 implements ProductA {@Overridepublic void display() {System.out.println("Concrete Product A2");}
}// 具体产品B1
class ConcreteProductB1 implements ProductB {@Overridepublic void show() {System.out.println("Concrete Product B1");}
}// 具体产品B2
class ConcreteProductB2 implements ProductB {@Overridepublic void show() {System.out.println("Concrete Product B2");}
}// 3. 定义抽象工厂接口
interface AbstractFactory {ProductA createProductA();ProductB createProductB();
}// 4. 实现具体工厂类
// 具体工厂1,生产产品A1和B1
class ConcreteFactory1 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA1();}@Overridepublic ProductB createProductB() {return new ConcreteProductB1();}
}// 具体工厂2,生产产品A2和B2
class ConcreteFactory2 implements AbstractFactory {@Overridepublic ProductA createProductA() {return new ConcreteProductA2();}@Overridepublic ProductB createProductB() {return new ConcreteProductB2();}
}// 客户端代码
public class AbstractFactoryExample {public static void main(String[] args) {// 使用工厂1创建产品A1和产品B1AbstractFactory factory1 = new ConcreteFactory1();ProductA productA1 = factory1.createProductA();ProductB productB1 = factory1.createProductB();productA1.display();productB1.show();// 使用工厂2创建产品A2和产品B2AbstractFactory factory2 = new ConcreteFactory2();ProductA productA2 = factory2.createProductA();ProductB productB2 = factory2.createProductB();productA2.display();productB2.show();}
}

为了避免跟之前的工厂方法模式混淆,这里做一个区别:

  • 简单工厂模式:一个工厂方法创建所有具体产品
  • 工厂方法模式:一个工厂方法创建一个具体产品
  • 抽象工厂模式:一个工厂方法创建一个具体产品的某一类

典型的应用场景是,使用抽象工厂模式来创建与不同数据库的连接对象。

总结一下就是抽象工厂模式特别适用于一系列相关或相互依赖的产品被一起创建的情况。

当需要增加新产品时(是新产品而不是某一产品的新型号),则需要增加新的具体产品类,然后修改抽象工厂接口以及所有的具体工厂类,扩展性相对较差。

【设计模式专题之抽象工厂模式】3. 家具工厂

CPP版代码:

#include <iostream>
#include <string>// 抽象椅子接口
class Chair {
public:virtual void showInfo() = 0;
};// 具体现代风格椅子
class ModernChair : public Chair {
public:void showInfo() override {std::cout << "modern chair" << std::endl;}
};// 具体古典风格椅子
class ClassicalChair : public Chair {
public:void showInfo() override {std::cout << "classical chair" << std::endl;}
};// 抽象沙发接口
class Sofa {
public:virtual void displayInfo() = 0;
};// 具体现代风格沙发
class ModernSofa : public Sofa {
public:void displayInfo() override {std::cout << "modern sofa" << std::endl;}
};// 具体古典风格沙发
class ClassicalSofa : public Sofa {
public:void displayInfo() override {std::cout << "classical sofa" << std::endl;}
};// 抽象家居工厂接口
class FurnitureFactory {
public:virtual Chair* createChair() = 0;virtual Sofa* createSofa() = 0;
};// 具体现代风格家居工厂
class ModernFurnitureFactory : public FurnitureFactory {
public:Chair* createChair() override {return new ModernChair();}Sofa* createSofa() override {return new ModernSofa();}
};// 具体古典风格家居工厂
class ClassicalFurnitureFactory : public FurnitureFactory {
public:Chair* createChair() override {return new ClassicalChair();}Sofa* createSofa() override {return new ClassicalSofa();}
};int main() {// 读取订单数量int N;std::cin >> N;// 处理每个订单for (int i = 0; i < N; i++) {// 读取家具类型std::string furnitureType;std::cin >> furnitureType;// 创建相应风格的家居装饰品工厂FurnitureFactory* factory = nullptr;if (furnitureType == "modern") {factory = new ModernFurnitureFactory();} else if (furnitureType == "classical") {factory = new ClassicalFurnitureFactory();}// 根据工厂生产椅子和沙发Chair* chair = factory->createChair();Sofa* sofa = factory->createSofa();// 输出家具信息chair->showInfo();sofa->displayInfo();// 释放动态分配的对象delete chair;delete sofa;delete factory;}return 0;
}

 

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

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

相关文章

android开发网络通信,带你彻底搞懂Android启动速度优化

实现方案 直接依赖 这种方式实现简单&#xff0c;但是耦合太严重&#xff0c;不方便维护与开发&#xff0c;当工程逐渐增大模块逐渐增多&#xff0c;依赖关系会非常复杂&#xff0c;不推荐这种方式。 事件或广播通信 EventBus&#xff1a; 我们非常熟悉的事件总线型的通信框…

Rust学习笔记:深度解析内存管理(二)

在这个信息爆炸的时代&#xff0c;学习一门新的编程语言不仅仅是为了找到一份好工作&#xff0c;更是为了打开思维的新窗口。Rust&#xff0c;作为一门注重安全、速度和并发的系统编程语言&#xff0c;正吸引着越来越多的年轻开发者的目光。今天&#xff0c;我们将一起深入探讨…

angular17+ionic7集成开发

1、需求背景 因部门要求使用angular作为基础的前端框架&#xff0c;也因为近期需要搭建一套新的移动端H5&#xff0c;故此有采用angular17ionic7集成搭建项目。 2、搭建步骤 环境安装 本地开发环境需要需要安装以下版本&#xff1a; node 20.9.0 angular-cli 17.2.2 ionic-…

老卫带你学---K8S源码剖析(Capabilities)

K8S源码剖析&#xff08;Capabilities&#xff09; 我们可以在pod、container中通过设置securityContext来限制container对宿节点的权限 但是有的时候我们需要给予container部分系统特权&#xff0c;那就需要额外配置capability&#xff0c;比如这样&#xff1a; containers…

【语言学习】C++algorithm库的命名空间问题

阅读这篇文章时&#xff0c;发现一个很有趣的点&#xff0c;原来使用copy和back_inserter时不需要使用std::。 查了一圈资料&#xff0c;没找到合理的解释&#xff0c;问了一下GPT&#xff1a; algorithm中的函数不需要显式地使用std命名空间是因为这些函数通常在标准库头文件中…

数据结构与算法:堆排序和TOP-K问题

朋友们大家好&#xff0c;本节内容来到堆的应用&#xff1a;堆排序和topk问题 堆排序 1.堆排序的实现1.1排序 2.TOP-K问题3.向上调整建堆与向下调整建堆3.1对比两种方法的时间复杂度 我们在c语言中已经见到过几种排序&#xff0c;冒泡排序&#xff0c;快速排序&#xff08;qsor…

QJsonValue的学习

类型判断&#xff1a; QJsonValue v("1");QJsonValue v1(1);qDebug()<<v.isString();//trueqDebug()<<v.isBool();//falseqDebug()<<v.isDouble();//falseqDebug()<<v1.isString();//falseqDebug()<<v1.isBool();//falseqDebug()<…

微信小程序云开发教程——墨刀原型工具入门(安装以及基础使用教程)

引言 作为一个小白&#xff0c;小北要怎么在短时间内快速学会微信小程序原型设计&#xff1f; “时间紧&#xff0c;任务重”&#xff0c;这意味着学习时必须把握微信小程序原型设计中的重点、难点&#xff0c;而非面面俱到。 要在短时间内理解、掌握一个工具的使用&#xf…

嵌入式学习32-函数传参复习及进程的消息队列

1.函数: 1.函数的定义 2.函数的调用 3.函数的声明 2.函数传参: 1.赋值传递&#xff08;复制传递&#xff09; 函数体内部想要使用函数体外部变量值的时候使用复制传递 2.全局变量传递 3.地址传递 函数体内部想要修改函数体外部变量值的时候使…

代码随想录刷题day14|二叉树的理论基础二叉树的前中后序递归遍历

文章目录 day14学习内容一、二叉树的理论基础1.1、完全二叉树 二、二叉树的递归遍历2.1、递归三部曲2.2、前序递归遍历2.3、中序递归遍历2.4、后序递归遍历 总结1.感想2.思维导图 day14学习内容 day14主要内容 二叉树的理论基础二叉树的遍历 声明 本文思路和文字&#xff0c;引…

了解MVCC的实现吗 ?(隐式字段,ReadView,undo log)

MVCC即多版本并发控制&#xff0c;它的实现原理主要依赖于记录中的隐藏字段、undo log&#xff08;回滚日志&#xff09;以及Read View&#xff08;读视图&#xff09;。 MVCC是数据库管理系统中用于处理并发操作的一项技术&#xff0c;它允许多个事务对同一数据进行读写操作而…

稀碎从零算法笔记Day4-LeetCode:交替合并字符串

前言&#xff1a;今天妹有深夜档&#xff0c;因为8点有个飞机 题型&#xff1a;字符串、双指针&#xff08;笔者没用这个思路&#xff09; 链接&#xff1a;1768. 交替合并字符串 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 著作权归作者所有。商业转…

java计算日期相差天数的4种方法

方法1&#xff1a;long值相减&#xff08;推荐&#xff09; public static void main(String[] args) {DateFormat dateFormat new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");try {Date startDate dateFormat.parse("2024-03-01 10:00:00");//开始时间D…

基础算法(二)#蓝桥杯

文章目录 8、双指针8.1、挑选子串8.2、聪明的小羊肖恩8.3、神奇的数组 9、二分9.1、跳石头9.2、可凑成的最大花朵数9.3、最大通过数9.4、妮妮的月饼广场9.5、基德的神秘冒险9.6、体育健将 10、倍增10.1、快速幂10.2、最近公共祖先LCA查询10.3、理想之城10.4、数的变换 8、双指针…

【十二】【SQL】表的约束

NOT NULL非空约束 展示对NULL的查询 mysql> select NULL; ------ | NULL | ------ | NULL | ------ 1 row in set (0.00 sec)mysql> select 1NULL; -------- | 1NULL | -------- | NULL | -------- 1 row in set (0.00 sec)mysql> 第一条查询&#xff1a;select NU…

JasperStudio中TextField文本框组件渲染之后,出现行间距不一致的问题

目录 1.1、问题描述 1.2、解决方案 1.1、问题描述 最近在处理线上遇到的一个问题,是有关JasperReports报表相关的问题,问题背景大概是这样的:我们的项目中使用了JasperReports来渲染报表,其中使用到了Text Field文本框组件,但是问题是渲染出来的数据直接会出现一些间距…

Python脚本删除文本文件中的重复行

实例&#xff1a;需要用Python删除文本文件a.txt中的重复行. Case1:仅需要删除文件中的重复行&#xff1a; rFile open(a.txt, r) wFile open(b.txt, w) allLine rFile.readlines() rFile.close() s set() for i in allLine:s.add(i) for i in s:wFile.write(i) open(b.t…

洛谷:P3068 [USACO13JAN] Party Invitations S(枚举、前缀和)

这题我们数据范围太大&#xff0c;用二维肯定是不行的&#xff0c;我们可以采用一维线性存储。 如题意&#xff0c;我们可以将每组奶牛编号都存在一维数组里面&#xff0c;只需记录每组的头尾指针就可以了。 如题中样例我们就可以存储成1 3 3 4 1 2 3 4 5 6 7 4 3 2 1 然后第…

[LeetBook]【学习日记】寻找和为指定数字的连续数字

题目 文件组合 待传输文件被切分成多个部分&#xff0c;按照原排列顺序&#xff0c;每部分文件编号均为一个 正整数&#xff08;至少含有两个文件&#xff09;。传输要求为&#xff1a;连续文件编号总和为接收方指定数字 target 的所有文件。请返回所有符合该要求的文件传输组…

【kubernetes】关于k8s集群的存储卷

目录 一、存储卷的分类 二、empty存储卷以及特点 三、hostpath存储卷以及特点 四、nfs存储卷以及特点 五、pvc存储卷 查看pv的定义 查看pvc的定义 实操&#xff1a;静态创建pv的方式 实现pvc存储卷 步骤一&#xff1a;先完成nfs的目录共享&#xff0c;需要准备不同的目…