当前位置: 首页 > news >正文

简单工厂,工厂方法,抽象工厂模式

文章目录

  • 简单工厂模式
    • 简单工厂模式的角色
    • 简单工厂的介绍
  • 工厂方法
    • UML图片
    • 代码
    • 工厂方法总结:
  • 抽象工厂
    • 代码实现

简单工厂模式

简单工厂模式(Simple Factory Pattern)专门定义一个类来负责创建其他类的实例,被创建的实例通常具有共同的父类。

简单工厂模式,是一种实例化对象的方式,只要输入需要实例化对象的名字,就可以通过工厂对象的相应工厂函数来制造你需要的对象。

简单工厂模式的角色

(1)Factory工厂角色(工厂类):

工厂角色即工厂类,是简单工厂模式的核心,负责创建所有实例的内部逻辑,工厂类可以被外界直接调用,创建所需要的产品对象。

(2)Product(抽象产品角色):

抽象产品角色是简单工厂模式所创建的所有对象的父类,负责描述所有实例所共有的公告接口。所创建的具体产品对象都是其子类对象。

(3)ConcreteProduct(具体产品角色):

具体产品角色是简单工厂模式的创建目标。每个具体产品角色都继承了抽象产品角色,需要实现定义在抽象产品中的方法。

简单工厂的介绍

简单工厂(Simple Factory)不属于标准的OOP设计模式中的一项,在编写大型C++软件的时候,代码里面会出现很多的类,每次创建对象的时候,都需要通过new 类名称的方式来生成对象,这样一来,用户需要记忆很多类的名称,暂且不管记不记得住,这样的设计使得代码很难维护,类名如果做了改变,那么所有使用类名称的地方都需要去修改,耦合性太强,不符合我们软件设计的思想,Simple Factory就是在这样的需求下诞生的。

在这里插入图片描述

我们把对象的创建全部都封装在了SimpleFactory的create方法中,在这里我们传入一个Product就可以创建一个对象,省略了new的过程

#include <iostream>
#include <string>
using namespace std;
//产品类型的声明,抽象产品
class  Product
{
public:Product(string name) : ProductName(name) {};virtual void show() = 0;
protected:string ProductName;
};//具体产品的声明
class BaoMa :public Product
{
public:BaoMa(string name) : Product(name) {};void show(){std::cout << "This is BaoMa Product" << char(10);std::cout << ProductName << char(10);}
};//具体产品2 的申明
class BengChi :public Product
{
public:BengChi(string name) : Product(name) {};void show(){std::cout << "This is <BengChi> Product" << char(10);std::cout << ProductName << char(10);}
};enum ProductType
{BWM,BC
};class SimpleFactory
{
public://通过传入的枚举类型,创建对应的对象,返回对象的基类指针Product* createProduct(ProductType type){switch (type){case BWM:return new BaoMa("宝马");break;case BC:return new BengChi("奔驰");break;default:std::cout << "你输入了错误的名字" << type << char(10);break;}}
};int main()
{//创建简单工厂的实例SimpleFactory sf;unique_ptr<Product> p1(sf.createProduct(BWM));unique_ptr<Product> p2(sf.createProduct(BC));p1->show();p2->show();return 0;
}

工厂方法

UML图片

在这里插入图片描述

通过产生具体的工厂创建具体的产品,做到了在扩充新产品时,能够达到软件设计的“开-闭”原则

代码

#include <iostream>
#include <string>
using namespace std;class AbstractProduct
{
public:AbstractProduct(string name): _name(name){}//模拟产品对象的抽象方法virtual void show() = 0;
protected:string _name;
};class ProductA:public AbstractProduct
{
public://其实这是一个委托构造函数ProductA(string name) : AbstractProduct(name) {}void show() { std::cout << "这是一个产品A的对象"; char(10);std::cout << "string name : " << _name << char(10);}
};class ProductB :public AbstractProduct
{
public://其实这是一个委托构造函数ProductB(string name) : AbstractProduct(name) {}void show() { std::cout << "这是一个产品B的对象"<< char(10);std::cout << "string name : " << _name << char(10);}
};//定义枚举类型的数据
enum  ProductType
{XIAOMI,HUAWEI,
};//定义抽象工厂
class AbstractFactory
{
public:virtual AbstractProduct* createProduct() = 0;
};//小米手机工厂
class XiaoMiFactory:public AbstractFactory
{
public:AbstractProduct* createProduct(){std::cout << "调用了小米工厂的创建方法" << char(10);return new ProductA("小米手机");}
};//华为手机工厂
class HuaWeiFactory :public AbstractFactory
{
public:AbstractProduct* createProduct(){std::cout << "调用了华为工厂的创建方法" << char(10);return new ProductB("华为手机");}
};int main()
{//在这里我们使用智能指针,创建具体工厂unique_ptr<AbstractFactory> Fac1(new XiaoMiFactory);unique_ptr<AbstractFactory> Fac2(new HuaWeiFactory);//通过工厂方法创建产品unique_ptr<AbstractProduct> Pro1(Fac1->createProduct());unique_ptr<AbstractProduct> Pro2(Fac2->createProduct());Pro1->show();Pro2->show();return 0;
}

工厂方法可以解决一簇产品(一款产品有多种形态)的问题,并且工厂一次只能生产一种产品;但需要一个工厂能够同时生产多款产品时,则需要用到抽象工厂模式

工厂方法总结:

仔细理解上面的工厂方法模式,会发现一个问题,就是每一个实例工厂负责生产一个实例产品,也就是一个产品对应一个工厂,一个工厂对应一个产品,那么小米不仅仅生产手机,还生产耳机,智能手环,智能插座等等相关的小米产品簇,不可能给这每一个产品都创建一个工厂类,那样的话代码中的类就太多了,不好维护,而且也不符合实际情况。

实际上小米或者华为的工厂里面,有相关联的产品簇都是在一个工厂完成创建的;BMW或者Audi汽车制造工厂除了生产汽车,生产线上也有可能生产轮胎,或者其它的汽车附属产品。

所以对于包含产品簇这么一类实体关系的设计,就需要使用Abstract Factory抽象工厂了,你也可以把上面的工厂方法看作只生产一种产品的抽象工厂,本质是相同的。

抽象工厂

在这里插入图片描述

可以看到,抽象工厂模式把一个产品簇的产品放在一个工厂类中去创建,不仅大大减少了工厂类的个数,更符合现实中工厂生产产品的模式。根据上面的内容描述,仔细思考简单工厂,工厂方法和抽象工厂的区别联系

代码实现

#include <iostream>
using namespace std;//抽象产品 手机类
class AbstractPhone
{
public:AbstractPhone(string name) : _name(name) {};//模拟产品对象的一个抽象的方法virtual void show() = 0; 
protected:string _name;
};//产品实体类型 小米
class XiaoMiPhone: public AbstractPhone
{
public:XiaoMiPhone(string name) : AbstractPhone(name) {};void show(){std::cout << "这是" << _name << "手机" << char(10);}
};//产品实体类型 华为
class HuaweiPhone : public AbstractPhone
{
public:HuaweiPhone(string name) : AbstractPhone(name) {};void show(){std::cout << "这是" << _name << "手机" << char(10);}
};//抽象产品 手环
class AbstractCircle
{
public:AbstractCircle(string name) : _name(name) {};//模拟产品对象的一个抽象的方法virtual void show() = 0;
protected:string _name;
};//产品实体 小米手环
class  XiaoMiCircle:public AbstractCircle
{
public:XiaoMiCircle(string name) :AbstractCircle(name) {};void show(){std::cout << "这是" << _name << "手环" << char(10);}
};//产品实体 华为手环
class  HuaWeiCircle :public AbstractCircle
{
public:HuaWeiCircle(string name) :AbstractCircle(name) {};void show(){std::cout << "这是" << _name << "手环" << char(10);}
};//抽象工厂,创建一个产品族的设备的产品
class AbstractFactory
{
public://创建手机的纯虚函数virtual AbstractPhone* createPhone() = 0;virtual AbstractCircle* createCircle() = 0;
};//生产小米的工厂
class XiaoMiFactory:public AbstractFactory
{
public:virtual AbstractPhone* createPhone(){return new XiaoMiPhone("小米14Pro");}virtual AbstractCircle* createCircle(){return new XiaoMiCircle("小米手环NFC版本");}
};//生产华为的工厂
class HuaWeiFactory :public AbstractFactory
{
public:virtual AbstractPhone* createPhone(){return new XiaoMiPhone("华为Mate60 pro");}virtual AbstractCircle* createCircle(){return new XiaoMiCircle("华为GT Runing");}
};int main()
{//利用智能指针,创建生产的工厂unique_ptr< AbstractFactory> fac1(new XiaoMiFactory);unique_ptr< AbstractFactory> fac2(new HuaWeiFactory);//通过工厂来生产手机的unique_ptr< AbstractPhone > phone1(fac1->createPhone());unique_ptr< AbstractPhone > phone2(fac2->createPhone());phone1->show();phone2->show();//生产手环unique_ptr< AbstractCircle > cir1(fac1->createCircle());unique_ptr< AbstractCircle > cir2(fac2->createCircle());cir1->show();cir2->show();return 0;
}

相关文章:

  • 原码、反码、补码,计算机中负数的表示
  • 八大算法排序@希尔排序(C语言版本)
  • 【MySQL】数据库之主从复制和读写分离
  • Ubuntu 常用命令之 locate 命令用法介绍
  • 2022年全球运维大会(GOPS深圳站)-核心PPT资料下载
  • LeetCode 2807. 在链表中插入最大公约数
  • HLS 2017.4 导出 RTL 报错:ERROR: [IMPL 213-28] Failed to generate IP.
  • C语言—第1次作业:编译与连接基础知识
  • AI:106-基于卷积神经网络的遥感图像地物分类
  • 2023-12-25 LeetCode每日一题(不浪费原料的汉堡制作方案)
  • k8s的声明式资源管理
  • java struts2教务管理系统Myeclipse开发mysql数据库struts2结构java编程计算机网页项目
  • RocketMQ5.0延时消息时间轮算法
  • Postgresql源码(119)PL/pgSQL中ExprContext的生命周期
  • 3D视觉-相机选用的原则
  • 【译】理解JavaScript:new 关键字
  • Create React App 使用
  •  D - 粉碎叛乱F - 其他起义
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Vue2.x学习三:事件处理生命周期钩子
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 如何优雅地使用 Sublime Text
  • 手写一个CommonJS打包工具(一)
  • 一起参Ember.js讨论、问答社区。
  • “十年磨一剑”--有赞的HBase平台实践和应用之路 ...
  • 阿里云ACE认证学习知识点梳理
  • (42)STM32——LCD显示屏实验笔记
  • (C++17) std算法之执行策略 execution
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (十六)串口UART
  • (四)汇编语言——简单程序
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (正则)提取页面里的img标签
  • (转)Oracle 9i 数据库设计指引全集(1)
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .form文件_一篇文章学会文件上传
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .NET 依赖注入和配置系统
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/C# 使用反射注册事件
  • @Service注解让spring找到你的Service bean
  • [ C++ ] STL_list 使用及其模拟实现
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [Bugku]密码???[writeup]
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [CC2642R1][VSCODE+Embedded IDE+IAR Build+Cortex-Debug] TI CC2642R1基于VsCode的开发环境
  • [CF494C]Helping People