当前位置: 首页 > news >正文

创建型模式-工厂方法

创建型模式-工厂方法

创建型模式-工厂方法

目录
  • 创建型模式-工厂方法
      • 辛弃疾《丑奴儿·书博山道中壁》
    • 1. 简单工厂
      • 1.1 介绍
      • 1.2 实现
      • 1.3 使用场景
      • 1.4 优缺点
        • ✅ 优点
        • ❌ 缺点
    • 2. 工厂方法
      • 2.1 介绍
      • 2.2 实现
      • 2.3 使用场景
      • 2.4 优缺点
        • ✅ 优点
        • ❌ 缺点

002456-1721492696c292

辛弃疾《丑奴儿·书博山道中壁》

少年不识愁滋味,爱上层楼。爱上层楼,为赋新词强说愁。
而今识尽愁滋味,欲说还休。欲说还休,却道天凉好个秋。

文章大部分由AI生成

1. 简单工厂

1.1 介绍

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式。

它的核心思想是:把“创建对象”的具体细节封装到一个专门的“工厂类”里,客户端只需要告诉工厂“我要什么”,而不需要知道这个东西是怎么“new”出来的。

  • 别名:静态工厂方法模式(因为工厂里的创建方法通常是静态的)。
  • 本质:用一个单独的类来负责所有产品的实例化。

简单工厂的本质选择实现,其重点在选择。工厂类内部的主要功能是“选择合适的实现类”来创建实例对象。

简单工厂的目的:为客户端选择相应的实现,从而使得客户端和实现之间解耦。这样,具体实现发生了变化,也就不必变动客户端了,这个变化被简单工厂吸收和屏蔽掉了。

classDiagramdirection TBclass Shoes {<<abstract>>+Show()}class NiKeShoes {+Show()}class AdidasShoes {+Show()}class SimpleShoesFactory {+CreateShoes()}class ClientShoes <|-- NiKeShoesShoes <|-- AdidasShoesSimpleShoesFactory ..> ShoesSimpleShoesFactory ..> NiKeShoesSimpleShoesFactory ..> AdidasShoesClient ..> SimpleShoesFactoryClient ..> Shoes

1.2 实现

第 1 步:定义一个工厂类
这个类里有一个方法,根据你传入的参数(比如字符串),返回对应的对象。

// 简单工厂类
class SimpleShoesFactory 
{
public:// 核心方法:根据名字造鞋static Shoes* CreateShoes(const std::string& brand) {if (brand == "nike") {return new NiKeShoes();} else if (brand == "adidas") {return new AdidasShoes();} else {return nullptr;}}
};

第 2 步:客户端调用
客户端不再直接面对具体的 NiKeShoes 类,只面对 Shoes 抽象类和 Factory 工厂类。

int main() {// 我想要耐克,跟工厂说一声就行Shoes* myShoes = SimpleShoesFactory::CreateShoes("nike");if (myShoes) {myShoes->Show();  // 输出:我是耐克球鞋...delete myShoes;}return 0;
}

1.3 使用场景

简单工厂模式比较适合产品种类较少、且相对固定的情况。

  1. 对象创建逻辑复杂
    比如创建对象前需要读取配置文件、需要计算参数、需要根据环境变量判断。把这一坨逻辑放在 main 或业务代码里很难看,不如直接丢给工厂的 Create 方法。
  2. 需要统一管理对象创建
    项目里有 100 个地方都要 new Car(),万一哪天 Car 构造函数改了(比如增加了一个必填参数 发动机型号),你就得改 100 处。如果用工厂,你只需要改工厂里的那一行代码。

1.4 优缺点

✅ 优点

  1. 解耦(最重要)
    客户端(main函数)从“直接制造”变成了“下单购买”。客户端只依赖抽象产品Shoes)和工厂,不再依赖具体产品类NiKeShoes)。
  2. 责任分离
    业务逻辑(展示广告语)和 创建逻辑(判断该 new 哪个对象)分开了,代码更容易维护。
  3. 复用性
    如果项目里 100 个地方都要创建鞋子,这 100 个地方都可以直接复用这一行调用代码:Factory.Create("nike")

❌ 缺点

  1. 违反开闭原则(最大的硬伤)
    这是它被称作“简单”工厂的原因,也是它与“工厂方法模式”最大的区别。
    • 问题:如果我要增加一款李宁球鞋。
    • 后果:你不仅要写一个 LiNingShoes 类,还必须去修改 SimpleShoesFactory 里的 CreateShoes 方法,增加一个 else if 分支
    • 风险:修改已有的、正在线上运行的工厂类,有可能会改坏原有逻辑(比如手抖把 nike 的分支删了)。
  2. 工厂类职责过重
    所有的创建逻辑堆在一个类里,一旦产品多了(比如 100 种鞋子),CreateShoes 方法会变成很长很长的 if...else if...,难以阅读和维护。这种被称为上帝类
  3. 不支持产品族的扩展
    如果你想要鞋子+衣服的套装组合,简单工厂很难优雅处理,需要引入抽象工厂模式。

2. 工厂方法

2.1 介绍

工厂方法模式(Factory Method Pattern)是一种创建型设计模式。

它的核心思想是:定义一个用于创建对象的接口(抽象工厂),但让子类决定具体实例化哪一个类。工厂方法让类的实例化推迟到子类中进行。

  • 别名:虚拟构造器模式(Virtual Constructor)
  • 本质:将产品工厂都抽象化,每个具体产品对应一个具体工厂。
  • 简单工厂:一个万能工厂生产所有产品。
  • 工厂方法:每个产品都有自己的专属工厂。
classDiagramdirection TBclass Shoes {<<abstract>>+Show()}class NiKeShoes {+Show()}class AdidasShoes {+Show()}class ShoesFactory {<<abstract>>+CreateShoes() Shoes*}class NiKeFactory {+CreateShoes() Shoes*}class AdidasFactory {+CreateShoes() Shoes*}class ClientShoes <|-- NiKeShoesShoes <|-- AdidasShoesShoesFactory <|-- NiKeFactoryShoesFactory <|-- AdidasFactoryNiKeFactory ..> NiKeShoesAdidasFactory ..> AdidasShoesClient ..> ShoesFactoryClient ..> Shoes

2.2 实现

第 1步:定义抽象产品 + 产品

// 抽象产品:鞋子
class Shoes {
public:virtual void Show() = 0;virtual ~Shoes() {}
};// 具体产品:耐克鞋
class NiKeShoes : public Shoes {
public:void Show() override {std::cout << "我是耐克球鞋,我的广告语:Just do it" << std::endl;}
};// 具体产品:阿迪鞋
class AdidasShoes : public Shoes {
public:void Show() override {std::cout << "我是阿迪球鞋,我的广告语:Impossible is nothing." << std::endl;}
};// 具体产品:李宁鞋(新增,完全不影响已有代码)
class LiNingShoes : public Shoes {
public:void Show() override {std::cout << "我是李宁球鞋,我的广告语:Anything is possible." << std::endl;}
};

第 2 步:定义抽象工厂 + 具体工厂

// 抽象工厂:鞋子工厂
class ShoesFactory {
public:virtual Shoes* CreateShoes() = 0;  // 工厂方法virtual ~ShoesFactory() {}
};// 具体工厂:耐克工厂
class NiKeFactory : public ShoesFactory {
public:Shoes* CreateShoes() override {return new NiKeShoes();}
};// 具体工厂:阿迪工厂
class AdidasFactory : public ShoesFactory {
public:Shoes* CreateShoes() override {return new AdidasShoes();}
};// 具体工厂:李宁工厂(新增,完全不影响已有代码)
class LiNingFactory : public ShoesFactory {
public:Shoes* CreateShoes() override {return new LiNingShoes();}
};

第 2 步:客户端使用

int main() {// 想生产耐克鞋,就用耐克工厂ShoesFactory* factory = new NiKeFactory();Shoes* shoes = factory->CreateShoes();shoes->Show();  // 输出:我是耐克球鞋...delete shoes;delete factory;// 想换成阿迪鞋,只需换工厂factory = new AdidasFactory();shoes = factory->CreateShoes();shoes->Show();  // 输出:我是阿迪球鞋...delete shoes;delete factory;return 0;
}

2.3 使用场景

  1. 产品种类会频繁扩展
    比如电商平台不断上新品牌,每次新增品牌只需要新增一个工厂类,不需要修改任何已有代码,完全符合开闭原则。
  2. 客户端不知道具体要创建哪个类
    比如框架开发中,你只知道需要一个 Shoes 对象,但具体是哪个品牌的鞋,由子类或配置决定。
  3. 创建逻辑比较复杂
    每个具体工厂可以封装自己的创建逻辑(比如耐克鞋需要特殊的质检流程,阿迪鞋需要特殊的材料准备),互不干扰。
  4. 需要控制产品创建时机
    工厂方法将创建推迟到子类,可以在子类中添加额外的初始化逻辑。

2.4 优缺点

✅ 优点

优点 说明
符合开闭原则 新增产品时,只需新增具体产品类和具体工厂类,无需修改已有代码
单一职责原则 每个具体工厂只负责创建一种产品,职责清晰
解耦 客户端只依赖抽象工厂和抽象产品,不依赖具体实现
扩展性强 可以轻松扩展新产品线,互不影响
支持产品族 可以演化为抽象工厂模式,支持产品族创建

❌ 缺点

缺点 说明
类的数量成倍增加 每增加一个产品,就需要增加一个工厂类。产品多时,类会非常多
代码复杂度增加 相比简单工厂,引入了更多抽象层,理解和维护成本更高
客户端需要选择工厂 客户端仍然需要知道用哪个具体工厂(虽然可以通过配置文件解决)
工厂层次深 如果产品本身还有子类,工厂也需要对应继承,层次会变得复杂
http://www.jsqmd.com/news/652474/

相关文章:

  • 如何在TensorFlow生态中集成BERTopic:打造强大的主题模型应用
  • FLUX.1文生图保姆级教程:WSL2环境快速部署与风格选择
  • 揭秘!云南化妆培训学校哪家才是真“王者” - 品牌测评鉴赏家
  • 2026年昆明靠谱高考美术培训机构推荐 - 云南美术头条
  • 【生成式AI分布式事务处理黄金法则】:20年架构师亲授3大不可绕过的容错设计模式
  • 掌握大模型技能!运维工程师薪资飙升53%,从“救火队员”变身“AI架构师”的跃迁秘籍!
  • windows风险排查
  • 终极指南:如何在移动设备上快速部署BERTopic主题模型
  • Jimeng LoRA部署案例:国产昇腾910B平台LoRA热切换适配进展实录
  • 2026年3-8岁少儿美育启蒙机构什么品牌靠谱 - 云南美术头条
  • PyTorch模型权重如何可视化_利用Matplotlib提取卷积核权重绘图
  • 实测参考|COS化妆培训学校选择指南(新手适配) - 品牌测评鉴赏家
  • 番茄小说下载器终极指南:创新技术实现离线阅读自由
  • BERTopic模型部署终极指南:构建生产级主题分析API服务
  • PP-DocLayoutV3高算力适配:支持TensorRT加速,A100上推理速度达38 FPS(1080p)
  • 贵州化妆培训学校哪家好?2026实测避坑+靠谱清单,小白直接抄作业 - 品牌测评鉴赏家
  • 如何从零打造一个高性价比的DIY蓝牙音箱?
  • 2026年4月昆明艺考机构排名前十 - 云南美术头条
  • 别再只复制代码了!深入理解LAMMPS中BKS势函数的物理内涵与参数调试技巧
  • 避开功耗估算的坑:详解XPE中Toggle Rate设置的门道(附常见设计场景参考值)
  • 保姆级教程:用Helm在K8s上部署RustFS对象存储(含Local Path配置与Ingress暴露)
  • yolo11模型部署记录
  • 创建型模式-自注册工厂方法
  • 【2026年】新大纲普通话考试真题题库50套(PDF电子版)
  • 高效拦截微信撤回消息的专业工具:WeChatIntercept完整指南
  • 魔兽争霸III终极优化指南:5个技巧让经典游戏焕发新生
  • 去掉 UWB / 蓝牙标签:浙江普陀时空大数据应用技术联合研究院无感定位,免穿戴、免部署、降本、全场景覆盖
  • LeetCode HOT100 - 合并两个有序链表
  • Hoppscotch:开源免费的Postman替代品,轻量级API测试神器
  • Unity UI布局核心:从RectTransform的localPosition与anchoredPosition看父子坐标系