如何实现工厂模式?

概念

工厂模式(Factory Pattern)是一种创建对象的设计模式,提供了一个接口用于创建对象,但由子类决定要实例化的类是哪一个。这种模式可以解耦对象的创建与使用,使得代码更加灵活和易于扩展。

简单工厂模式

简单工厂模式定义了一个工厂类,根据输入的参数返回不同类型的对象。虽然这不是一个正式的设计模式,但它是工厂模式的基础。

#include <iostream>  
#include <memory>  
#include <string>  

// 产品基类  
class Product {  
public:  
    virtual void use() = 0; // 纯虚函数  
    virtual ~Product() = default; // 虚析构函数  
};  

// 具体产品 A  
class ProductA : public Product {  
public:  
    void use() override {  
        std::cout << "Using Product A" << std::endl;  
    }  
};  

// 具体产品 B  
class ProductB : public Product {  
public:  
    void use() override {  
        std::cout << "Using Product B" << std::endl;  
    }  
};  

// 简单工厂  
class SimpleFactory {  
public:  
    // 工厂方法,根据类型创建不同产品  
    static std::unique_ptr<Product> createProduct(const std::string& type) {  
        if (type == "A") {  
            return std::make_unique<ProductA>();  
        } else if (type == "B") {  
            return std::make_unique<ProductB>();  
        }  
        return nullptr; // 返回空指针  
    }  
};  

int main() {  
    // 使用工厂创建不同类型的产品  
    std::unique_ptr<Product> productA = SimpleFactory::createProduct("A");  
    if (productA) {  
        productA->use();  
    }  

    std::unique_ptr<Product> productB = SimpleFactory::createProduct("B");  
    if (productB) {  
        productB->use();  
    }  

    return 0;  
}

代码解析

  • 产品基类 (Product):定义了一个接口,所有具体产品都需要实现这个接口。
  • 具体产品 (ProductA, ProductB):实现了基类的接口。
  • 简单工厂 (SimpleFactory):根据输入字符串类型返回相应的产品实例。
  • 客户端代码:通过简单工厂创建所需产品并使用。

工厂方法模式

工厂方法模式定义了一个接口来创建对象,但让子类决定实例化哪一个类。这样可以将对象的创建逻辑推向子类,保持高内聚、低耦合。

#include <iostream>  
#include <memory>  

// 产品基类  
class Product {  
public:  
    virtual void use() = 0;  
    virtual ~Product() = default;  
};  

// 具体产品 A  
class ProductA : public Product {  
public:  
    void use() override {  
        std::cout << "Using Product A" << std::endl;  
    }  
};  

// 具体产品 B  
class ProductB : public Product {  
public:  
    void use() override {  
        std::cout << "Using Product B" << std::endl;  
    }  
};  

// 工厂基类  
class Factory {  
public:  
    virtual std::unique_ptr<Product> createProduct() = 0; // 工厂方法  
    virtual ~Factory() = default;  
};  

// 具体工厂 A  
class FactoryA : public Factory {  
public:  
    std::unique_ptr<Product> createProduct() override {  
        return std::make_unique<ProductA>(); // 创建产品 A  
    }  
};  

// 具体工厂 B  
class FactoryB : public Factory {  
public:  
    std::unique_ptr<Product> createProduct() override {  
        return std::make_unique<ProductB>(); // 创建产品 B  
    }  
};  

int main() {  
    std::unique_ptr<Factory> factoryA = std::make_unique<FactoryA>();  
    std::unique_ptr<Product> productA = factoryA->createProduct();  
    productA->use();  

    std::unique_ptr<Factory> factoryB = std::make_unique<FactoryB>();  
    std::unique_ptr<Product> productB = factoryB->createProduct();  
    productB->use();  

    return 0;  
}

代码解析

  • 工厂基类 (Factory):定义工厂方法接口。
  • 具体工厂 (FactoryA, FactoryB):实现工厂方法,返回不同的产品。
  • 客户端代码:通过具体工厂创建对应的产品并使用。

抽象工厂模式

抽象工厂模式提供一个接口用于创建一系列相关或相互依赖的对象,而无需指定它们的具体类。这通常用于需要产品系列中的多个产品的情况。

#include <iostream>  
#include <memory>  

// 产品接口  
class Button {  
public:  
    virtual void paint() = 0;  
    virtual ~Button() = default;  
};  

// 具体产品 A  
class WinButton : public Button {  
public:  
    void paint() override {  
        std::cout << "Rendering a Windows Button." << std::endl;  
    }  
};  

// 具体产品 B  
class MacButton : public Button {  
public:  
    void paint() override {  
        std::cout << "Rendering a Mac Button." << std::endl;  
    }  
};  

// 产品接口  
class Checkbox {  
public:  
    virtual void paint() = 0;  
    virtual ~Checkbox() = default;  
};  

// 具体产品 A  
class WinCheckbox : public Checkbox {  
public:  
    void paint() override {  
        std::cout << "Rendering a Windows Checkbox." << std::endl;  
    }  
};  

// 具体产品 B  
class MacCheckbox : public Checkbox {  
public:  
    void paint() override {  
        std::cout << "Rendering a Mac Checkbox." << std::endl;  
    }  
};  

// 抽象工厂  
class GUIFactory {  
public:  
    virtual std::unique_ptr<Button> createButton() = 0;  
    virtual std::unique_ptr<Checkbox> createCheckbox() = 0;  
    virtual ~GUIFactory() = default;  
};  

// 具体工厂 A  
class WinFactory : public GUIFactory {  
public:  
    std::unique_ptr<Button> createButton() override {  
        return std::make_unique<WinButton>();  
    }  
    std::unique_ptr<Checkbox> createCheckbox() override {  
        return std::make_unique<WinCheckbox>();  
    }  
};  

// 具体工厂 B  
class MacFactory : public GUIFactory {  
public:  
    std::unique_ptr<Button> createButton() override {  
        return std::make_unique<MacButton>();  
    }  
    std::unique_ptr<Checkbox> createCheckbox() override {  
        return std::make_unique<MacCheckbox>();  
    }  
};  

// 客户端代码  
void renderUI(GUIFactory& factory) {  
    auto button = factory.createButton();  
    button->paint();  

    auto checkbox = factory.createCheckbox();  
    checkbox->paint();  
}  

int main() {  
    WinFactory factory;  
    renderUI(factory);  

    MacFactory macFactory;  
    renderUI(macFactory);  

    return 0;  
}

代码解析

  • 产品接口 (Button, Checkbox):定义不同类型的产品接口。
  • 具体产品 (WinButton, MacButton, WinCheckbox, MacCheckbox):实现不同平台的具体产品。
  • 抽象工厂 (GUIFactory):定义创建产品方法的接口。
  • 具体工厂 (WinFactory, MacFactory):实现产品创建方法,返回平台特定的产品。
  • 客户端代码:可以轻松切换工厂,实现不同平台的界面。

总结

工厂模式通过提供一个接口来创建对象,将对象的创建过程与使用解耦。简单工厂适合小型应用,工厂方法模式适合需要扩展性和可维护性的应用,而抽象工厂模式适合复杂的产品系列。根据具体需求选择合适的工厂模式可以提高代码的灵活性和可维护性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[数据结构] 链表

目录 1.链表的基本概念 2.链表的实现 -- 节点的构造和链接 节点如何构造? 如何将链表关联起来? 3.链表的方法(功能) 1).display() -- 链表的遍历 2).size() -- 求链表的长度 3).addFirst(int val) -- 头插法 4).addLast(int val) -- 尾插法 5).addIndex -- 在任意位置…

20241220在荣品开发板PRO-RK3566的buildroot下适配gc2093

20241220在荣品开发板PRO-RK3566的buildroot下适配gc2093 2024/12/20 16:00 余顺?PRO-RK3566开发板 挂 gc2093模块。刷 buildroot的预编译固件。 update-pro-rk3566-buildroot-hdmi-20231130-034633.img 1、现在发现 qcamera的 拍照Capture、Record录像模式都是640x480分辨率…

实习冲刺数据库练习-01 基础查询

原题链接&#xff1a;牛客网在线编程_SQL篇_非技术快速入门 数据表示例&#xff1a; 根据数据表示例要求我们完成以下查询&#xff1a; &#xff08;1&#xff09;获取用户信息表中所有的数据&#xff0c;请你取出相应结果 &#xff08;2&#xff09;获取用户的设备id对应的…

【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换

相关链接&#xff1a; http://mars3d.cn/editor-vue.html?keyex_1_2_1&idmap/other/backgroundImg 实现代码&#xff1a; export function show1() {map.setOptions({scene: {backgroundType: "image",backgroundImage: "url(//data.mars3d.cn/img/busin…

telnet命令检查端口

1、简介 telnet是一种用于远程登录的协议&#xff0c;可以通过telnet客户端连接到远程主机&#xff0c;并在远程主机上执行命令。 2、使用telnet命令检查端口 2.1 进入linux终端 2.2 输入telnet命令 如果没有安装telnet命令&#xff0c;请执行以下命令安装 sudo yum install…

Unity 根据文本宽度自动移动图像位置

游戏中有时候需要变动的显示一个物品的数量&#xff0c;变化的文本宽度不停的变化&#xff0c;这时候需要将物品的icon随着文本的长度而改变位置。 实现思路&#xff1a;使用Content Size Fitter来动态改变内容的大小。 首先建立一个文本组件&#xff0c;添加Content Size Fi…

基于Springboot人口老龄化社区服务与管理平台【附源码】

基于Springboot人口老龄化社区服务与管理平台 效果如下&#xff1a; 系统登陆页面 系统主页面 社区信息页面 社区文件页面 活动报名页面 走访任务管理页面 社区资讯页面 老人信息管理页面 研究背景 随着社会老龄化的加剧&#xff0c;老年人口比例逐渐增加&#xff0c;对老年…

加密数据库在现代企业中的应用实践

以下是对加密数据库在现代企业中的应用实践的详细阐述&#xff1a; 一、加密数据库的应用背景 随着信息技术的飞速发展&#xff0c;现代企业对于数据的安全性和隐私保护要求越来越高。数据库作为存储大量敏感信息的关键设施&#xff0c;其安全性直接关系到企业的商业利益和声誉…

安卓环境配置及打开新项目教程,2024年12月20日最新版

1.去官网下载最新的Android Studio&#xff0c;网址&#xff1a;https://developer.android.com/studio?hlzh-cn 2.下载加速器&#xff0c;注册账号&#xff0c;开启加速器。网址&#xff1a;放在文末。 3.下载安卓代码&#xff0c;项目的路径上不能有中文&#xff0c;特别是…

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕 2024/12/17 17:21 缘起&#xff0c;最近需要识别法国电影《地下铁》的法语字幕&#xff0c;使用 字幕小工具V1.2【whisper套壳/GUI封装了】 无效。 那就是直接使用最原始的whisper来干了。 当你重装WIN10的时候&#…

sqlite3 支持位运算 和view和 triger

数据设置条件以后可以.根据门限自动调整其他的值 由数据库记录修改时间,及记录-> 网元设备的告警产生时间,设置超时清除时间,记录系统的原始时间戳 CPp 有 sqlite 支持 json 导出字符串,json 库将字符串,映射为结构体 triger update table 更新到一个 可设置参数列表 ,view …

11-C语言结构体(下篇)

一、结构体指针变量 结构体指针变量&#xff1a;本质上是一个指针变量&#xff0c;保存的是结构体变量的地址。 1.结构体变量的地址 结构体变量的地址&#xff1a;对结构体变量名取地址。 代码演示 typedef struct stu {char name[32];int age;float score; }STU;int main…

linux普通用户使用sudo不需要输密码

1.root用户如果没有密码&#xff0c;先给root用户设置密码 sudo passwd root #设置密码 2.修改visudo配置 su #切换到root用户下 sudo visudo #修改visudo配置文件 用户名 ALL(ALL) NOPASSWD: ALL #下图所示处新增一行配置 用户名需要输入自己当前主机的用户名

百度面试手撕 go context channel部分学习

题目 手撕 对无序的切片查询指定数 使用context进行子协程的销毁 并且进行超时处理。 全局变量定义 var (startLoc int64(0) // --- 未处理切片数据起始位置endLoc int64(0) // --- 切片数据右边界 避免越界offset int64(0) // --- 根据切片和协程数量 在主线程 动态设…

任务一登录安全加固

1 &#xff08;1&#xff09;、&#xff08;2&#xff09; secpol.msc打开本地安全策略 2 &#xff08;1&#xff09; DCOM: 在安全描述符定义语言(SDDL)语法中的计算机访问限制 没有定义 DCOM: 在安全描述符定义语言(SDDL)语法中的计算机启动限制 没有定义 Microsoft 网络服…

无人机推流直播平台EasyDSS视频技术如何助力冬季森林防火

冬季天干物燥&#xff0c;大风天气频繁&#xff0c;是森林火灾的高发期。相比传统的人力巡查&#xff0c;无人机具有更高的灵敏度和准确性&#xff0c;尤其在夜间或浓雾天气中&#xff0c;依然能有效地监测潜在火源。 无人机可以提供高空视角和实时图像传输&#xff0c;帮助巡…

写SQL太麻烦?免费搭建 Text2SQL 应用,智能写 SQL | OceanBase AI 实践

自OceanBase 4.3.3版本推出以来&#xff0c;向量检索的能力受到了很多客户的关注&#xff0c;也纷纷表达希望OB能拓展更多 多模数据库大模型 的AI应用实践。 在上篇文章 &#x1f449; OceanBase LLM&#xff0c;免费构建你的专属 AI 助手 &#xff0c;我们介绍了如何去搭建一…

Halcon 机器视觉案例 之 药剂液面高度测量

第二篇 机器视觉案例 之 药剂液面高度测量 文章目录 第二篇 机器视觉案例 之 药剂液面高度测量1.案例要求2.实现思路2.1获得液面的位置&#xff1a;2.1.1 获得每支药剂的位置坐标2.1.2 根据药剂的横坐标设置卡尺工具助手找到每一个液面的位置 2.2 获得基准线的位置&#xff1a;…

使用k6进行MongoDB负载测试

1.安装环境 安装xk6-mongo扩展 ./xk6 build --with github.com/itsparser/xk6-mongo 2.安装MongoDB 参考Docker安装MongoDB服务-CSDN博客 连接成功后新建test数据库和sample集合 3.编写脚本 test_mongo.js import xk6_mongo from k6/x/mongo;const client xk6_mongo.new…

LabVIEW随机扫描成像系统

利用LabVIEW开发了一套随机扫描成像系统&#xff0c;利用硬件时钟实现声光偏转器&#xff08;AOD&#xff09;的频率控制与信号采集之间的高速时间同步。系统利用了高精度的时钟同步技术&#xff0c;确保了成像精度和重复性&#xff0c;从而有效提高了成像速度和质量。 项目背景…