如何实现工厂模式?

news2024/12/22 4:01:27

概念

工厂模式(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):实现产品创建方法,返回平台特定的产品。
  • 客户端代码:可以轻松切换工厂,实现不同平台的界面。

总结

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

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

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

相关文章

【Java基础面试题025】什么是Java的Integer缓存池?

回答重点 Java的Integer缓存池&#xff08;Integer Cache&#xff09;是为了提升性能和节省内存。根据实践发现大部分的数据操作都集中在值比较小的范围&#xff0c;因此缓存这些对象可以减少内存分配和垃圾回收的负担&#xff0c;提升性能 在 -128到127范围内的Integer对象会…

AI广告爆发元年,心动网络能否成下一个Applovin?

如果说2023年标志着AI大模型技术的崛起&#xff0c;那么2024年无疑是AI广告应用爆发的元年。 大洋彼岸的Applovin凭借着智能广告分发引擎完成彻底翻身&#xff0c;股价上涨超过30倍。一跃成为AI领域乃至整个美股市场的明星。 与此同时&#xff0c;心动网络作为同样深耕于游戏…

基于Python3编写的Golang程序多平台交叉编译自动化脚本

import argparse import os import shutil import sys from shutil import copy2from loguru import loggerclass GoBuild:"""一个用于构建跨平台执行文件的类。初始化函数&#xff0c;设置构建的主文件、生成的执行文件名称以及目标平台。:param f: 需要构建的…

java全栈day20--Web后端实战(Mybatis基础2)

一、Mybatis基础 1.1辅助配置 配置 SQL 提示。 默认在 mybatis 中编写 SQL 语句是不识别的。可以做如下配置&#xff1a; 现在就有sql提示了 新的问题 产生原因&#xff1a; Idea 和数据库没有建立连接&#xff0c;不识别表信息 解决方式&#xff1a;在 Idea 中配置 MySQL 数…

MacOS下PostIn安装配置指南

PostIn是一款开源免费的接口管理工具&#xff0c; 下面介绍私有部署版本的MacOS下安装与配置。私有部署版本更适合有严格数据安全要求的企业&#xff0c;实现对数据和系统的完全控制。 &#xfeff; &#xfeff; 1、MacOS服务端安装 Mac安装包下载地址&#xff1a;下载Mac安…

【Apache Doris】周FAQ集锦:第 26 期

SQL问题 Q1 doris 3.0存算分离模式下&#xff0c;建表的时是否需要指定表的副本数 不需要&#xff0c;指定了也会忽略&#xff1b;存算分离模式下&#xff0c;数据副本由远端存储去管控。 Q2 doris 通过dbeaver查询时报错&#xff1a;[SXXXX]… doris的错误码通常都是EXXXX&…

【Mongo工具】Mongo迁移工具之Mongo-shake

Mongo-Shake 简介 Mongo-Shake 是一个基于 MongoDB 操作日志&#xff08;oplog&#xff09;的通用服务平台。它从源 MongoDB 数据库中获取操作日志&#xff0c;并在目标 MongoDB 数据库中重放&#xff0c;或者通过不同的隧道发送到其他终端。如果目标端是 MongoDB 数据库&…

【Unity基础】AudioSource 常用方法总结

在 Unity 中&#xff0c;AudioSource 组件用于控制音频的播放和管理。以下是常用的 AudioSource 控制方法及其说明。 1. 播放和暂停音频 Play()&#xff1a;开始播放音频&#xff0c;如果是从暂停的地方继续播放&#xff0c;可以直接调用。Pause()&#xff1a;暂停当前播放的…

flink SQL实现mysql source sink

接上文&#xff1a;一文说清flink从编码到部署上线 环境说明&#xff1a;MySQL&#xff1a;5.7&#xff1b;flink&#xff1a;1.14.0&#xff1b;hadoop&#xff1a;3.0.0&#xff1b;操作系统&#xff1a;CentOS 7.6&#xff1b;JDK&#xff1a;1.8.0_401。 1.代码实现 1.1 E…

知乎 PB 级别 TiDB 数据库集群管控实践

以下文章来源于知乎技术专栏 &#xff0c;作者代晓磊 导读 在现代企业中&#xff0c;数据库的运维管理至关重要&#xff0c;特别是面对分布式数据库的复杂性和大规模集群的挑战。作为一款兼容 MySQL 协议的分布式关系型数据库&#xff0c;TiDB 在高可用、高扩展性和强一致性方…

SpringBoot+Vue3实现阿里云视频点播 实现教育网站 在上面上传对应的视频,用户开会员以后才能查看视频

要使用阿里云视频点播&#xff08;VOD&#xff09;实现一个教育网站&#xff0c;其中用户需要成为会员后才能查看视频&#xff0c;这个过程包括上传视频、设置权限控制、构建前端播放页面以及确保只有付费会员可以访问视频内容。 1. 视频上传与管理 创建阿里云账号&#xff…

【前端】 async 和 await 以及 generator生成器函数

一、背景 这一篇随机主要是想记录一下自己学习js中有关异步内容的东西。然后发现有人拿异步跟生成器函数进行比较了一下&#xff0c;因此一起学习了一下。 二、知识点相关内容及实验test 2.1 generator 生成器函数 generator函数的作用&#xff1a;每次访问返回函数中yield…

智能座舱进阶-应用框架层-Handler分析

首先明确&#xff0c; handler是为了解决单进程内的线程之间的通信问题的。我也需要理解Android系统中进程和线程的概念&#xff0c; APP启动后&#xff0c;会有三四个线程启动起来&#xff0c;其中&#xff0c;有一条mainUITread的线程&#xff0c;专门用来处理UI事件&#xf…

windows openssl编译x64版libssl.lib,编译x64版本libcurl.lib,支持https,vs2015编译器

不要纠结&#xff0c;直接选择用perl编译&#xff01; 告诫想要用弄成vs编译版的&#xff0c;暂时先别给自己增加麻烦 告诫&#xff0c;以下执行的每一步&#xff0c;都不要纠结 先安装环境 nasm 64位版本 https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-…

汽车供应链 “剧变”开始,“智能感知潜在龙头”诞生

智能汽车产业链“剧变”已经开启&#xff0c;智能感知软硬件能力的权重正在不断被放大。 比如满足高阶泊车的第二代AK2超声波传感器、满足人机共驾场景需求的电子外后视镜&#xff08;CMS&#xff09;、iTOF 3D成像视觉感知&#xff08;用于舱内监控&#xff09;等新产品&…

Python+OpenCV系列:AI看图识人、识车、识万物

在人工智能风靡全球的今天&#xff0c;用 Python 和 OpenCV 结合机器学习实现物体识别&#xff0c;不仅是酷炫技能&#xff0c;更是掌握未来的敲门砖。本篇博文手把手教你如何通过摄像头或图片输入&#xff0c;识别人、动物、车辆及其他物品&#xff0c;让你的程序瞬间具备 AI …

JVM 详解

一. JVM 内存区域的划分 1. 程序计数器 程序计数器是JVM中一块比较小的空间, 它保存下一条要执行的指令的地址. [注]: 与CPU的程序计数器不同, 这里的下一条指令不是二进制的机器语言, 而是Java字节码. 2. 栈 保存方法中的局部变量, 方法的形参, 方法之间的调用关系. 栈又…

C# opencvsharp 流程化-脚本化-(2)ROI

ROI ROI也是经常需要使用的方法。特别是在图像编辑中。ROI又称感兴趣的区域&#xff0c;但是图像是矩阵是矩形的&#xff0c;感兴趣的是乱八七糟的&#xff0c;所以还有一个Mask需要了解一下的。 public class RoiStep : IImageProcessingStep{public ImageProcessingStepType…

wazuh-modules-sca-scan

sca模块主函数wm_sca_main -> wm_sca_start 检查policy文件中的每一个项目wm_sca_check_policy static int wm_sca_check_policy(const cJSON * const policy, const cJSON * const checks, OSHash *global_check_list) {if(!policy) {return 1;}const cJSON * const id c…

uniapp 自定义图标03

插入工程&#xff0c;修改名称文件内容 编译运行