重看工厂模式

简介: 重看工厂模式

重看工厂模式


之前整个设计模式的专栏是看了李建忠老师的视频,并没有太多的自己的总结,今天来回看一下设计模式,重温设计模式的魅力


工厂模式我们介绍三个:


简单工厂


我们举个例子,现在世界上有三场备受关注的战争。俄罗斯保护卢甘斯克和顿涅斯克独立共和国之战,加沙保卫战和果敢电诈反击战。


有战争就需要武器,这个时候他们需要枪,炮,无人机等等。他们就有了对武器的需求。


例子如下:

#include <iostream>
#include <string>

using namespace std;

class Weapon
{
public:
    explicit Weapon(const string &name) {
        name_ = name;
        if (name == "枪") {}
        else if (name == "炮") {}
        else if (name == "飞机") {}
    }

    void useWeapon() {
        if (name_ == "枪") {
            cout << "我是枪" << endl;
        } else if (name_ == "炮") {
            cout << "我是炮" << endl;
        } else if (name_ == "飞机") {
            cout << "我是飞机" << endl;
        }
    }

private:
    string name_;
};

int main()
{
    Weapon gun = Weapon("枪");
    Weapon cannon = Weapon("炮");
    Weapon plane = Weapon("飞机");
    gun.useWeapon();
    cannon.useWeapon();
    plane.useWeapon();
    return 0;
}


从上面的例子中我们能看到,如果我们需要大量型号武器的话,Weapon明显会是一个巨大的类。该类设计时候存在以下的问题:


  • 在Weapon中包含了很多的if elseif 代码块,整个类代码冗长,增加阅读和维护难度;并且大量的条件语句会影响系统的性能,程序执行的时候需要进行大量判断。
  • Weapon职责过重,需要初始化和显示所有的武器对象,将各种武器初始化和使用放在一个类中实现,违反了单一职责原则,不利于类的维护。
  • 当需要增加新型号的武器的时候,必须修改weapon代码,违反了开闭原则。


我们需要一种方式,来创建不同的武器,并且使得我们使用的时候,分的清楚,拿过来就用。以便我们更快获取战争的胜利。


  • 工厂角色:即简单工厂的核心,用来创建所有的武器实例,可以被外部直接使用,创建我们需要的产品
  • 抽象产品:简单工厂所有产品的父类,负责描述公共接口
  • 具体产品:需要创造的具体产品


如上述的例子:我们需要一个武器工厂,使用武器工厂来生产不同的武器,则修改为如下方式:

#include <iostream>
#include <string>

using namespace std;

class Weapon
{
public:
    virtual ~Weapon() {}
    virtual void useWeapon() = 0;
};

class Gun : public Weapon
{
public:
    void useWeapon() override
    {
        cout << "我是枪" << endl;
    }
};

class Cannon : public Weapon
{
public:
    void useWeapon() override
    {
        cout << "我是炮" << endl;
    }
};

class Plane : public Weapon
{
public:
    void useWeapon() override
    {
        cout << "我是飞机" << endl;
    }
};

class Factory
{
public:
    Weapon *createWeapon(const std::string &name)
    {
        if (name == "枪") {
           return new Gun;
        } else if (name == "炮") {
            return new Cannon;
        } else if (name == "飞机") {
            return new Plane;
        }
    }
};

int main()
{
    Factory ff;
    Weapon* weapon = nullptr;
    weapon = ff.createWeapon("枪");
    weapon->useWeapon();
    delete weapon;
    weapon = nullptr;
    weapon = ff.createWeapon("炮");
    weapon->useWeapon();
    delete weapon;
    weapon = nullptr;
    weapon = ff.createWeapon("飞机");
    weapon->useWeapon();
    delete weapon;
    weapon = nullptr;
    return 0;
}

如上例子所示,我们需要生产武器种类多的时候,工厂就会变的臃肿。但是我们使用的时候,只要抽象一个武器,工厂负责生产,且生产的武器我们直接拿来使用就可以。因为工厂生产的是具体的武器,所以我们在使用的时候会用具体的武器去击败敌人。


简单工厂的优缺点也很明显了:


  • 优点:实现了对象创建和使用的分离;不需要记得具体的类名称,只需要记住工厂参数即可。
  • 缺点:对工厂类的依赖过重,一旦工厂类不能工作,整个系统会崩溃;增加了系统中类的个数,复杂度和理解度增加;违反开闭原则,添加新产品需要修改工厂逻辑,工厂会越来越复杂。


简单工厂适合工厂产品较少,客户端只需要告诉工厂需要生产对应的产品,对如何创建不关心的场景


工厂方法


角色和对应的职责:


  • 抽象工厂:工厂方法模式的核心,任何工厂类都必须实现这个接口。
  • 工厂:具体工厂是抽象工厂的一个实现,负责具体实例化产品。
  • 抽象产品:工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的接口。
  • 具体产品:工厂方法所创建的具体实例对象。


我们使用简单工厂生产武器的时候,工厂堆积严重,因此我们需要一个工厂调度中心,然后将武器分给不同的工厂分别生产,代码如下:

#include <iostream>
#include <string>

using namespace std;

class Weapon
{
public:
    virtual ~Weapon() {}
    virtual void useWeapon() = 0;
};

class Gun : public Weapon
{
public:
    void useWeapon() override
    {
        cout << "我是枪" << endl;
    }
};

class Cannon : public Weapon
{
public:
    void useWeapon() override
    {
        cout << "我是炮" << endl;
    }
};

class Plane : public Weapon
{
public:
    void useWeapon() override
    {
        cout << "我是飞机" << endl;
    }
};

class AbstractFactory
{
public:
    virtual Weapon *createWeapon() = 0;
};

class GunFactory : public AbstractFactory
{
public:
    Weapon *createWeapon() override
    {
        return new Gun;
    }
};

class CannonFactory : public AbstractFactory
{
public:
    Weapon *createWeapon() override
    {
        return new Cannon;
    }
};

class PlaneFactory : public AbstractFactory
{
public:
    Weapon *createWeapon() override
    {
        return new Plane;
    }
};

int main()
{
    AbstractFactory *ff = nullptr;
    Weapon* weapon = nullptr;
    ff = new GunFactory;
    weapon = ff->createWeapon();
    weapon->useWeapon();
    delete weapon;
    weapon = nullptr;
    delete ff;
    ff = nullptr;
    ff = new CannonFactory;
    weapon = ff->createWeapon();
    weapon->useWeapon();
    delete weapon;
    weapon = nullptr;
    delete ff;
    ff = nullptr;
    ff = new PlaneFactory;
    weapon = ff->createWeapon();
    weapon->useWeapon();
    delete weapon;
    weapon = nullptr;
    delete ff;
    ff = nullptr;
    return 0;
}

优缺点:


  • 优点:不需要记住具体的武器名字,甚至不需要对应的参数;实现了创建和使用的分离;系统扩展性变好,如果有新的武器,不需要修改原来的接口和类。
  • 缺点:增加了类的数量,增加了抽象性和理解难度


工厂分类明确,职责清晰。如果我们某类型的武器不足,只需要到对应类型的工厂去取即可。


抽象工厂方法


工厂方法通过引入工厂调度中心,解决了简单工厂中工厂类职责过重的问题,但是由于工厂方法中的每个工厂只生产一类产品,导致我们工厂非常多,肯定会增加系统的开销,因此我们考虑将一些产品组成一类,使用同一个工厂生产。


比如我们在俄罗斯生产一种型号的枪炮飞机,在朝鲜生产另外一种型号的枪炮飞机,则武器供应不断,胜利就在眼前。


角色和对应的职责:


  • 抽象工厂:工厂方法模式的核心,任何工厂类都必须实现这个接口。
  • 工厂:具体工厂是抽象工厂的一个实现,负责具体实例化产品。
  • 抽象产品:工厂方法模式所创建的所有对象的父类,它负责描述所有实例所共有的接口。
  • 具体产品:工厂方法所创建的具体实例对象。
#include <iostream>
#include <string>

using namespace std;

class WeaponGun
{
public:
    virtual void useWeapon() = 0;
};

class WeaponPlane
{
public:
    virtual void useWeapon() = 0;
};

class WeaponCannon
{
public:
    virtual void useWeapon() = 0;
};

class TMXGun : public WeaponGun
{
public:
    void useWeapon() override
    {
        cout << "使用汤姆逊" << endl;
    }
};
class JKSGun : public WeaponGun
{
public:
    void useWeapon() override
    {
        cout << "使用捷克式" << endl;
    }
};
class WeaponCannon1 : public WeaponCannon
{
public:
    void useWeapon() override
    {
        cout << "二营长的意大利炮" << endl;
    }
};

class WeaponCannon2 : public WeaponCannon
{
public:
    void useWeapon() override
    {
        cout << "二营长的迫击炮" << endl;
    }
};

class WeaponPlane1 : public WeaponPlane
{
public:
    void useWeapon() override
    {
        cout << "战斗机" << endl;
    }
};
class WeaponPlane2 : public WeaponPlane
{
public:
    void useWeapon() override
    {
        cout << "轰炸机" << endl;
    }
};


class AbstractFactory {
public:
    virtual WeaponGun* createGun() = 0;
    virtual WeaponCannon* createCannon() = 0;
    virtual WeaponPlane* createPlane() = 0;
};

class RussiaFactory : public AbstractFactory
{
public:
    WeaponGun* createGun() override {
        return new TMXGun;
    }
    WeaponCannon* createCannon() override
    {
        return new WeaponCannon1;
    }
    WeaponPlane* createPlane() override
    {
        return new WeaponPlane1;
    }
};
class NorthKoreaFactory : public AbstractFactory
{
public:
    WeaponGun* createGun() override {
        return new JKSGun;
    }
    WeaponCannon* createCannon() override
    {
        return new WeaponCannon2;
    }
    WeaponPlane* createPlane() override
    {
        return new WeaponPlane2;
    }
};

int main()
{
    AbstractFactory *factory = nullptr;
    WeaponGun *gun = nullptr;
    WeaponCannon *cannon = nullptr;
    WeaponPlane *plane = nullptr;
    factory = new RussiaFactory;
    gun = factory->createGun();
    cannon = factory->createCannon();
    plane = factory->createPlane();
    gun->useWeapon();
    cannon->useWeapon();
    plane->useWeapon();
    delete  factory;
    delete  gun;
    delete  cannon;
    delete  plane;

    factory = new NorthKoreaFactory;
    gun = factory->createGun();
    cannon = factory->createCannon();
    plane = factory->createPlane();
    gun->useWeapon();
    cannon->useWeapon();
    plane->useWeapon();
    delete  factory;
    delete  gun;
    delete  cannon;
    delete  plane;
    return 0;
}

至此,多地共同生产产品,战争胜利近在眼前。

目录
相关文章
|
SQL 前端开发 关系型数据库
LLM大模型实战 —— DB-GPT阿里云部署指南
DB-GPT 是一个实验性的开源应用,它基于FastChat,并使用vicuna-13b作为基础模型, 模型与数据全部本地化部署, 绝对保障数据的隐私安全。 同时此GPT项目可以直接本地部署连接到私有数据库, 进行私有数据处理, 目前已支持SQL生成、SQL诊断、数据库知识问答、数据处理等一系列的工作。
11690 75
|
网络协议 Linux
Centos IP、DNS设置
1、CentOS 修改DNS 修改对应网卡的DNS的配置文件# vi /etc/resolv.conf 修改以下内容 nameserver 8.8.8.8 #google域名服务器nameserver 8.8.4.4 #google域名服务器2、CentOS 修改网关 修改对应网卡的网关的配置文件[root@centos]# vi /etc/sysconfig/network 修改以下内容NETWORKING=yes(表示系统是否使用网络,一般设置为yes。
3901 0
|
3月前
|
存储 人工智能 弹性计算
阿里云新用户2026年购买云服务器优惠解析:优惠、实例与决策指南
2026年阿里云为新用户提供了丰富的云服务器优惠。轻量应用服务器低至38元/年,经济型e实例99元/年(活动持续至2029年3月),u1实例199元/年,u2i实例年付3折起,第九代实例年付最低6.4折。此外,618 AI加速季推出总额2088元优惠券礼包(个人360元、企业1728元),满额最高减800元;百炼产品还有"先用后返"活动,最高返200元。多重优惠可叠加使用,大幅降低新用户上云及AI应用落地成本。
|
11月前
|
运维 监控 安全
公链应用开发智能合约部署全流程要点
本章聚焦公链智能合约部署全流程,明确目标、场景与边界条件,通过可量化验收、场景清单与对照分析,实现从编码到上线的可复用、可追溯落地。结合安全审计与跨链适配,提供标准化资源清单与分阶段操作模板,确保部署高效、可控、一致,支撑多链环境下的低故障率交付。
|
10月前
|
存储 机器学习/深度学习 并行计算
Python解析NC格式文件全攻略:从基础到实战
本文系统介绍NetCDF(NC)文件的解析与应用,涵盖其结构、常用工具(netCDF4、xarray、Dask)、核心操作及性能优化方法,结合气象、台风分析等实战案例,助力高效处理海量气候数据,适用于地球科学研究与大数据分析。
2045 0
|
4月前
|
JSON 自然语言处理 API
大模型应用:解锁大模型能力边界:Skill 与 Function Call的底层逻辑与实战应用.117
本文深入解析大模型能力扩展核心机制:Skill(技能)与Function Call(函数调用)的关系。Skill是标准化、可复用的能力单元(如计算器、天气查询),定义“能做什么”;Function Call是执行协议,实现“如何调用”。二者结合突破大模型在实时性、准确性、安全性上的局限,推动其从对话工具进化为可执行复杂任务的智能体。
768 6
|
3月前
|
存储 人工智能 安全
AI智能体的开发
AI智能体是企业数字化转型的关键引擎,融合大模型(大脑)、知识库(记忆)与API工具(双手),实现自动化办公。本文详解其四大核心模块、五步开发流程及三档费用构成,助企业科学评估与落地AI员工。(239字)
IPv4内网与公网地址范围
本文介绍了内网和公网IPv4地址的范围及用途。内网IP(私有地址)包括10.0.0.0/8、172.16.0.0/12和192.168.0.0/16,分别适用于大型、中型和小型网络。公网IP分为A、B、C类,分别支持大规模、中等规模和小规模网络;D类用于多播通信,E类保留实验用途。此外,127.0.0.0/8为环回地址,不用于公网。这些划分确保了IP地址的有效利用与网络通信的正常进行。
6747 10
|
人工智能 数据可视化 算法
CrewAI与LangGraph:下一代智能体编排平台深度测评
在过去的一年里,我深度研究了多种智能体编排平台的技术演进,见证了从单一智能体应用向多智能体协作系统的转变。随着大语言模型能力的不断提升,**智能体编排(Agent Orchestration)**已成为构建复杂AI系统的核心技术。在众多新兴框架中,CrewAI以其直观的团队协作模式和LangGraph以其强大的状态图编排能力,代表了两种截然不同的技术路径。 CrewAI采用**代码优先(Code-First)的编排方式,将智能体建模为具有特定角色和目标的团队成员;而LangGraph则提供可视化编排(Visual Orchestration)**能力,通过状态图来管理复杂的工作流程。这两种平台
1765 0
CrewAI与LangGraph:下一代智能体编排平台深度测评
|
存储 人工智能 弹性计算
阿里云gpu云服务器收费价格,热门实例简介和最新按量、1个月、1年收费标准参考
在阿里云所有gpu云服务器实例规格中,计算型gn5、gn6i、gn6v、gn7i和最新推出的gn8is、gn8v-tee等实例规格是其中比较热门的gpu云服务器实例。阿里云gpu云服务器最新租用价格参考,适合AI推理/训练的16核60G+1张A10 24G显存(gn7i-c16g1.4xlarge),按量优惠价1.9/小时起。本文为大家展示阿里云gpu云服务器中gn5、gn6i等热门实例规格的主要性能和适用场景以及最新按量和1个月、1年收费标准,以供参考。