C++设计模式(工厂模式)

一、介绍

1.动机

在软件系统中,经常面临着创建对象的工作,这些对象有可能是一系列相互依赖的对象;由于需求的变化,需要创建的对象的具体类型经常变化,同时也可能会有更多系列的对象需要被创建。

如何应对这种变化?如何绕过常规的对象创建方法(new),提供一种“封装机制”来避免客户程序和这种“具体对象创建工作”的紧耦合?

 

2.定义

工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟到子类。——GOF

抽象工厂模式:提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定它们具体的类。——GOF

 

3.结构图

工厂方法模式:

42ffb07cfb8048cea5e8a821a0043e38.jpeg

抽象工厂模式:

ff1b2684237c4725ac531ae5b3535925.jpeg

 

4.要点总结

工厂方法模式:

  • Factory Method模式用于隔离类对象的使用者和具体类型之间的耦合关系。面对一个经常变化的具体类型,紧耦合关系(new)会导致软件的脆弱。
  • Factory Method模式通过面向对象的手法,将创建具体对象的工作延迟到子类,从而实现一种扩展(而非更改)的策略,较好地解决了这种紧耦合关系。
  • Factory Method模式解决“单个对象”的需求变化,缺点在于要求创建方法/参数相同。

抽象工厂模式:

  • 如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式,这时候使用简单的工厂完全可以。
  • “系列对象”指的是在某一特定系列下的对象之间有相互依赖或相互作用的关系,不同系列的对象之间不能相互依赖。
  • Abstract Factory模式主要在于应对“新系列”的需求变动,其缺点在于难以应对“新对象”的需求变动。

 

 

二、工厂模式

1.概念

工厂模式避免直接使用new运算符来创建产品对象,它提供一个抽象的工厂接口来创建和管理对象的实例化,同时也支持对创建逻辑的封装和扩展。

①工厂模式的优点:

  • 解耦:客户端代码与具体产品的创建逻辑分离,只依赖于抽象产品和工厂接口。
  • 扩展性:增加新产品时只需添加新的具体产品类和相应的具体工厂类,不需要修改现有代码。
  • 重用性:同一个工厂类可以用来创建多个产品,提高代码的复用率。

②工厂模式的缺点:

  • 增加类的数量:可能导致系统中类的数量增加,尤其是在使用抽象工厂模式时。
  • 复杂性:引入额外的抽象层,可能会增加理解和维护的复杂性。

 

2.实现要点

  • 抽象产品:定义一个抽象产品类,它将作为具体产品的共同基类或接口。
  • 具体产品:为每个具体的产品实现一个类,这些类将继承或实现抽象产品类。
  • 抽象工厂:创建一个抽象工厂类,它将提供创建产品的接口。
  • 具体工厂:实现抽象工厂中定义的方法,创建具体的产品对象。
  • 客户端:使用工厂方法来创建对象,但不需要知道具体产品的类。

工厂模式可以分为三种类型:简单工厂模式、工厂方法模式及抽象工厂模式。

 

3.简单工厂模式

通过一个工厂类来创建不同类型的产品实例,根据传递的参数来决定创建哪种具体的产品。

//文具类(抽象产品)
class Stationery {
public:virtual void use() = 0;virtual ~Stationery() {}
};//钢笔类(具体产品)
class Pen :public Stationery {
public:Pen() {cout << "Pen()" << endl;}virtual ~Pen() {cout << "~Pen()" << endl;}virtual void use() override{cout << "Use pen." << endl;}
};//铅笔类(具体产品)
class Pencil :public Stationery {
public:Pencil() {cout << "Pencil()" << endl;}virtual ~Pencil() {cout << "~Pencil()" << endl;}virtual void use() override {cout << "Use pencil." << endl;}
};//枚举类型
enum StationeryType {PEN,PENCIL
};//文具工厂类
class StationeryFactory {
public:static shared_ptr<Stationery> createStationery(StationeryType type) {switch (type) {case PENCIL:return shared_ptr<Stationery>(new Pencil);break;case PEN:return shared_ptr<Stationery>(new Pen);break;defalut:return nullptr;break;}}
};

 测试代码:

shared_ptr<Stationery> pen = StationeryFactory::createStationery(PEN);
pen->use();
shared_ptr<Stationery> pencil = StationeryFactory::createStationery(PENCIL);
pencil->use();

 输出结果;

Pen()
Use pen.
Pencil()
Use pencil.
~Pencil()
~Pen()

 

4.工厂方法模式

将创建具体产品的任务分发给具体的产品工厂,每个具体工厂负责创建对应的具体产品对象。

//交通工具类(抽象类)
class Vehicle {
public:virtual void run() = 0;virtual ~Vehicle() {}
};//汽车类(具体类)
class Car :public Vehicle {
public:virtual void run() override {cout << "The car is running." << endl;}
};//自行车类(具体类)
class Bicycle :public Vehicle {
public:virtual void run() override {cout << "The bicycle is moving." << endl;}
};//交通工具工厂(抽象工厂)
class VehicleFactory {
public:virtual Vehicle* createVehicle() = 0;virtual ~VehicleFactory() {}
};//汽车工厂(具体工厂)
class CarFactory :public VehicleFactory {
public:virtual Vehicle* createVehicle() override {return new Car();}
};//自行车工厂(具体工厂)
class BicycleFactory :public VehicleFactory {
public:virtual Vehicle* createVehicle() override {return new Bicycle();}
};

测试代码: 

VehicleFactory* carFactory = new CarFactory();
Vehicle* car = carFactory->createVehicle();
car->run();
delete car;
delete carFactory;VehicleFactory* bicycleFactory = new BicycleFactory();
Vehicle* bicycle = bicycleFactory->createVehicle();
bicycle->run();
delete bicycle;
delete bicycleFactory;

输出结果: 

The car is running.
The bicycle is moving.

 

5.抽象工厂模式

提供一个抽象的工厂接口以及多个具体工厂类,每个具体工厂类负责创建一种或多种产品。

//桌子类(抽象类)
class Table {
public:virtual void display() = 0;virtual ~Table() {}
};//现代风格桌子(具体类)
class ModernTable :public Table {
public:virtual void display() override {cout << "A modern style table." << endl;}
};//古典风格桌子(具体类)
class ClassicalTable :public Table {
public:virtual void display() override {cout << "A classical style table." << endl;}
};//椅子类(抽象类)
class Chair {
public:virtual void sit() = 0;virtual ~Chair() {}
};//现代风格椅子(具体类)
class ModernChair :public Chair {
public:virtual void sit() override {cout << "Sitting on modern style chair." << endl;}
};//古典风格椅子(具体类)
class ClassicalChair :public Chair {
public:virtual void sit() override {cout << "Sitting on classical style chair." << endl;}
};//沙发类(抽象类)
class Sofa {
public:virtual void relax() = 0;virtual ~Sofa() {}
};//现代风格沙发(具体类)
class ModernSofa :public Sofa {
public:virtual void relax() override {cout << "Relaxing on modern style sofa." << endl;}
};//古典风格沙发(具体类)
class ClassicalSofa :public Sofa {
public:virtual void relax() override {cout << "Relaxing on Classical style sofa." << endl;}
};//家具工厂(抽象工厂)
class FurnitureFactory {
public:virtual Table* createTable() = 0;virtual Chair* createChair() = 0;virtual Sofa* createSofa() = 0;virtual ~FurnitureFactory() {}
};//现代风格家具工厂(具体工厂)
class ModernFurnitureFactory :public FurnitureFactory {
public:virtual Table* createTable() override {return new ModernTable;}virtual Chair* createChair() override {return new ModernChair;}virtual Sofa* createSofa() override {return new ModernSofa;}
};//古典风格家具工厂(具体工厂)
class ClassicalFurnitureFactory :public FurnitureFactory {
public:virtual Table* createTable() override {return new ClassicalTable;}virtual Chair* createChair() override {return new ClassicalChair;}virtual Sofa* createSofa() override {return new ClassicalSofa;}
};

测试代码: 

FurnitureFactory* modernFactory = new ModernFurnitureFactory();
Table* modernTable = modernFactory->createTable();
Chair* modernChair = modernFactory->createChair();
Sofa* modernSofa = modernFactory->createSofa();
modernTable->display();
modernChair->sit();
modernSofa->relax();
delete modernTable;
delete modernChair;
delete modernSofa;FurnitureFactory* classicalFactory = new ClassicalFurnitureFactory();
Table* classicalTable = new ClassicalTable();
Chair* classicalChair = new ClassicalChair();
Sofa* classicalSofa = new ClassicalSofa();
classicalTable->display();
classicalChair->sit();
classicalSofa->relax();
delete classicalTable;
delete classicalChair;
delete classicalSofa;

 输出结果:

A modern style table.
Sitting on modern style chair.
Relaxing on modern style sofa.
A classical style table.
Sitting on classical style chair.
Relaxing on Classical style sofa.

 

 

 

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

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

相关文章

速度革命:esbuild如何改变前端构建游戏 (1)

什么是 esbuild&#xff1f; esbuild 是一款基于 Go 语言开发的 JavaScript 构建打包工具&#xff0c;以其卓越的性能著称。相比传统的构建工具&#xff08;如 Webpack&#xff09;&#xff0c;esbuild 在打包速度上有着显著的优势&#xff0c;能够将打包速度提升 10 到 100 倍…

scp比rz sz传文件更好

scp (Secure Copy) 是一个用于在本地主机和远程主机之间安全地传输文件的工具&#xff0c;它使用SSH协议来加密传输的数据。下面是 scp 的基本用法&#xff1a; 从本地复制到远程 scp /path/to/local/file usernameremote_host:/path/to/remote/directory 这条命令将本地文件…

java八股-分布式服务的接口幂等性如何设计?

文章目录 接口幂等token Redis分布式锁 原文视频链接&#xff1a;讲解的流程特别清晰&#xff0c;易懂&#xff0c;收获巨大 【新版Java面试专题视频教程&#xff0c;java八股文面试全套真题深度详解&#xff08;含大厂高频面试真题&#xff09;】 https://www.bilibili.com/…

C++:多态的原理

目录 一、多态的原理 1.虚函数表 2.多态的原理 二、单继承和多继承的虚函数表 1、单继承中的虚函数表 2、多继承中的虚函数表 一、多态的原理 1.虚函数表 首先我们创建一个使用了多态的类&#xff0c;创建一个对象来看其内部的内容&#xff1a; #include<iostre…

Local Changes不展示,DevEco Studio的git窗口中没有Local Changes

DevEco Studio的git窗口中&#xff0c;没有Local Changes&#xff0c;怎么设置可以调出&#xff1f; 进入File-->Settings-->Version Control&#xff0c;将Use non-modal commit interface前的勾选框取消勾选&#xff0c;点击OK即可在打开git窗口&#xff0c;就可以看到…

情绪识别项目

文章目录 1、mp4s文件转mp3文件2、Audition下载3、Audition安装4、Audition使用&#xff1a; 1、mp4s文件转mp3文件 在线转&#xff1a;Convert audio to MP3&#xff08;https://audio.online-convert.com/convert-to-mp3&#xff09; 2、Audition下载 Audition CC2019/64位…

Windows Qtcreator不能debug 调试 qt5 程序

Windows下 Qt Creator 14.0.2 与Qt5.15.2 正常release打包都是没有问题的&#xff0c;就是不能debug&#xff0c;最后发现是两者不兼容导致的&#xff1b; 我使用的是 编译器是 MinGW8.1.0 &#xff0c;这个版本是有问题的&#xff0c;需要更新到最新&#xff0c;我更新的是Mi…

解决整合Django与Jinja2兼容性的问题

提问 解决整合Django与Jinja2时遇到了一些兼容性问题。已经按照常规步骤在我的settings.py中配置了Jinja2作为模板引擎&#xff0c;同时保留了Django默认的模板设置。然而尝试同时使用Django和Jinja2时&#xff0c;系统报错提示我没有指定模板。如果我尝试移除Django的默认模板…

如何搭建C++环境--1.下载安装并调试Microsoft Visual Studio Previerw(Windows)

1.首先&#xff0c;打开浏览器 首先&#xff0c;搜索“Microsoft Visual Studio Previerw” 安装 1.运行VisualStudioSetup (1).exe 无脑一直点继续 然后就到 选择需要的语言 我一般python用pycharm Java&#xff0c;HTML用vscode&#xff08;Microsoft Visual Studio cod…

【Kubernetes 指南】基础入门——Kubernetes 简介(一)

目录 一、Kubernetes 简单介绍 二、Kubernetes 是一个平台 三、Kubernetes 不是什么&#xff1f; 一、Kubernetes 简单介绍 Kubernetes 是谷歌开源的容器集群管理系统&#xff0c;是 Google 多年大规模容器管理技术 Borg 的开源版本&#xff0c;主要功能包括&#xff1a; ①…

Java线程的使用

Java中的线程是用来实现多任务并发执行的机制。在Java中&#xff0c;主要有两种方式来创建和使用线程&#xff1a;实现Runnable接口和继承Thread类。 实现Runnable接口&#xff1a; 创建一个类&#xff0c;实现Runnable接口&#xff0c;并重写run()方法。在run()方法中定义线程…

go clean -modcache命令清理缓存

go clean -modcache命令用于清理Go模块的本地缓存。Go模块缓存位于$GOPATH/pkg/mod/cache目录下&#xff0c;存储了所有下载和使用的模块版本。当执行go clean -modcache时&#xff0c;这个命令会删除该目录下的所有内容&#xff0c;迫使Go在下次构建时重新下载所有依赖的模块。…

Python 中的 Lxml 库与 XPath 用法

Python 中的 Lxml 库与 XPath 用法 Python 中的 Lxml 库与 XPath 用法Lxml安装 Lxml基础用法加载文档解析与查询创建新的 XML/HTML 高级特性1. 复杂的 XPath 查询2. DTD 和 Schema 验证3. XSLT 变换4. 自定义命名空间5. 异常处理6. 大文件流式处理7. 并发和线程安全性8. 性能优…

共享售卖机语音芯片方案选型:WTN6020引领智能化交互新风尚

在共享经济蓬勃发展的今天&#xff0c;共享售卖机作为便捷购物的新形式&#xff0c;正逐步渗透到人们生活的各个角落。为了提升用户体验&#xff0c;增强设备的智能化和互动性&#xff0c;增加共享售卖机的语音功能就显得尤为重要。 共享售卖机语音方案选型&#xff1a; WTN602…

关闭AWS账号后,服务是否仍会继续运行?

在使用亚马逊网络服务&#xff08;AWS&#xff09;时&#xff0c;用户有时可能会考虑关闭自己的AWS账户。这可能是因为项目结束、费用过高&#xff0c;或是转向使用其他云服务平台。然而&#xff0c;许多人对关闭账户后的服务状态感到困惑&#xff0c;我们九河云和大家一起探讨…

新版本PasteSpider开发中专用部署工具介绍(让2GB的服务器也能使用CI/CD,简化你的部署过程)

如果你有linux服务器&#xff0c;可以试试这个PasteSpider&#xff0c;利用容器管理软件(docker/podman)&#xff0c;可以快速上手&#xff01; 拉取镜像并安装 【【【PasteSpider的下载和安装(支持docker的一键模式)】】】 建议使用 最简单的模式SqliteMemoryCache 测试嘛…

【小白学机器学习37】用numpy计算协方差cov(x,y) 和 皮尔逊相关系数 r(x,y)

目录 1 关于1个数组np.array&#xff08;1组数据&#xff09;如何求各种统计数据 2 关于2个数组np.array&#xff08;2组数据&#xff09;如何求数组的相关关系&#xff1f; 2.1 协方差公式和方差公式 2.2 协方差 公式 的相关说明 2.3 用np.cov(x,y,ddof0) 直接求协方差矩…

C++ 11重点总结1

智能指针 智能指针: C11引入了四种智能指针: auto_ptr(已弃用)、unique_ptr、shared_ptr和weak_ptr。智能指针可以更有效地管理堆内存,并避免常见的内存泄漏问题。 shared_ptr: 自定义删除器。 shared_ptr使用引用计数来管理它指向的对象的生命周期。多个shared_ptr实例可以指向…

2024年nvm保姆级安装教程

需求&#xff1a;当前我的nodejs的版本是6.14.10&#xff0c;想切换为更高的版本。故使用nvm工具来实现不同node版本之间的切换 目录 一、删除node二、nvm安装三、配置nvm镜像四、安装所需要的nodejs版本nvm常用命令 一、删除node 第一步&#xff1a;首先在控制面板删除node.j…

Java部分新特性

模式匹配 instance of 模式匹配 之前写法 public void print(Object o) {if (o instanceof String){String str (String) obj;System.out.println("This is a String of length " s.length());} else {System.out.println("This is not a String");} …