设计模式3、工厂方法模式 Factory Method

news/2025/2/21 10:50:47/
解释说明:定义一个用于创建对象的接口,但是让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类
抽象工厂(AbstractFactory):提供了创建产品的接口,调用者通过它访问具体工厂的工厂方法来创建产品
具体工厂(ConcreteFactory):主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
抽象产品(Product):定义产品的规范,描述了产品的主要特性和功能
具体产品(ConcreteProduct):实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是一对一的关系
优点:
克服了简单工厂模式违背开放-封闭原则的缺点,又保留了封装对象创建过程的优点,降低客户端和工厂的耦合性。所以说,“工厂方法模式”是“简单工厂模式”的进一步抽象和推广。
缺点:
每增加一个产品,相应的也要增加一个子工厂,加大了额外的开发量
适用场景
对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。
只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程对于使用者来说是透明的
考虑这样一个场景,如下图:
Jungle想要进行户外运动,它可以选择打篮球、踢足球或者玩排球。和上一次的体育保管室不同,这次分别由篮球保管室、足球保管室和排球保管室,Jungle只需直接去相应的保管室就可以拿到对应的球!然后Jungle就可以愉快地玩耍了
product.h
#pragma once
#include <string>
using namespace std;
// 汽车接口
class ICar
{
public:virtual string Name() = 0;  // 汽车名称
};
concreteProduct.h
#pragma once
#include "product.h"
// 奔驰汽车
class BenzCar : public ICar
{
public:string Name(){return "Benz Car";}
};
// 宝马汽车
class BmwCar : public ICar
{
public:string Name(){return "Bmw Car";}
};
// 奥迪汽车
class AudiCar : public ICar
{
public:string Name(){return "Audi Car";}
};
factory.h
#pragma once
#include "product.h"
// 工厂接口
class AFactory
{
public:virtual ICar* CreateCar() = 0;  // 生产汽车
};
concreteProduct.h
#pragma once
#include "factory.h"
#include "concreteProduct.h"
// 奔驰工厂
class BenzFactory : public AFactory
{
public:ICar* CreateCar(){return new BenzCar();}
};
// 宝马工厂
class BmwFactory : public AFactory
{
public:ICar* CreateCar(){return new BmwCar();}
};
// 奥迪工厂
class AudiFactory : public AFactory
{
public:ICar* CreateCar(){return new AudiCar();}
};
main.cpp
#include "concreteFactory.h"
#include "product.h"
#include <iostream>
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if(p){delete(p); (p)=NULL;} }
#endif
int main()
{// 奔驰AFactory *pFactory = new BenzFactory();ICar *pCar = pFactory->CreateCar();cout << "Benz factory: " << pCar->Name() << endl;SAFE_DELETE(pCar);SAFE_DELETE(pFactory);// 宝马pFactory = new BmwFactory();pCar = pFactory->CreateCar();cout << "Bmw factory: " << pCar->Name() << endl;SAFE_DELETE(pCar);SAFE_DELETE(pFactory);// 奥迪pFactory = new AudiFactory();pCar = pFactory->CreateCar();cout << "Audi factory: " << pCar->Name() << endl;SAFE_DELETE(pCar);SAFE_DELETE(pFactory);system("pause");return 0;
}


http://www.ppmy.cn/news/1129378.html

相关文章

蓝牙核心规范(V5.4)11.2-LE Audio 笔记之LE Auido架构

专栏汇总网址&#xff1a;蓝牙篇之蓝牙核心规范学习笔记&#xff08;V5.4&#xff09;汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德&#xff0c;任何非CSDN看到的这篇文章都是盗版网站&#xff0c;你也看不全。认准原始网址。&#xff01;&#xff01;&#x…

VBA 将TXT的多行文本文件进行处理,以ID为单位处理成 一行

VBA 将TXT的多行文本文件进行处理&#xff0c;以ID为单位处理成 一行 序言 由于需要将TXT文件与Excel文件进行对比&#xff0c;但两种文件格式差异比较大&#xff0c;于是通过VBA写了一下小工具&#xff0c;以便日后方便使用。 TXT文件如下 VBA代码如下 ********************…

Web Worker实现前端的“多线程”

Web Workers 是一种 JavaScript 机制&#xff0c;允许在后台运行独立的线程&#xff0c;以执行一些计算密集型或耗时的任务。这使得在多核 CPU 上并行处理任务成为可能。 直接show code&#xff1a; hello.html代码 <!DOCTYPE html> <html lang"en"> …

vue 基于vue-seamless-scroll无缝滚动的用法和遇到的问题解决

vue 基于vue-seamless-scroll无缝滚动的用法和遇到的问题解决 背景 最近再做一个大屏项目,需要用到表格滚动效果,之前自己写过js实现,最近发现一个组件vue-seamless-scroll可以实现滚动,感觉挺方便的,准备用一下,但是用完之后才发现这个组件有很多坑需要解决.我把用法和一些问…

判断编译器类型、编译器版本、操作系统。

目录 1. 判断编译器类型&#xff1a; 2. 判断编译器版本&#xff1a; 3. 判断操作系统&#xff1a; 总结&#xff1a; 1. 判断编译器类型&#xff1a; 可以使用预定义的宏来判断编译器类型。例如&#xff0c;__GNUC__ 宏用于判断是否使用了GCC 编译器&#xff0c;_MSC_VER…

读高性能MySQL(第4版)笔记17_复制(下)

1. 复制切换 1.1. 复制是高可用性的基础 1.1.1. 总是保留一份持续更新的副本数据&#xff0c;会让灾难恢复更简单 1.2. “切换副本”&#xff08;promoting a replica&#xff09;和“故障切换”&#xff08;failing over&#xff09;是同义词 1.2.1. 意味着源服务器不再接…

ubuntu http 服务器响应

代码&#xff1a; h文件 #include <iostream> #include <curl/curl.h>#include <net/if.h> #include <sys/ioctl.h> #include <arpa/inet.h> #include <string.h>#include <event.h> #include <event2/http.h> #include <…

wireshark of tshark tools v3.4.0版本 支持json

tshark(1) Install tshark (Wireshark) Ver.3.4.0 on CentOS7 --It must be "ps", "text", "pdml", "psml" or "fields". TCP 协议中的三次握手和四次挥手是 TCP 连接建立和关闭的过程。 三次握手 客户端向服务器发送 SYN…