%% # 纲要 > 主干纲要、Hint/线索/路标 # Q&A #### 已明确 #### 待明确 > 当下仍存有的疑惑 **❓<font color="#c0504d"> 有什么问题?</font>** %% # 三种工厂模式的区别 - **简单工厂模式**: - 思路:一个工厂类**根据 "传入==参==数"** 创建不同类型的**具体产品对象**; - 缺点:**违反开闭原则**,增加新的产品对象时,需要**修改工厂类的代码**。 - **工厂方法模式**: - 思路:一个**抽象工厂基类**定义**一个 `create` 通用接口**,每种 **==具体工厂子类==** 实现接口,直接负责 **==某一种==具体产品对象** 的创建。 - 优点: - 增加新的产品对象时,只需**添加新的具体工厂子类**,无需修改既有代码。 - 可形成 "**工厂的继承体系**",不同等级的产品由相应等级的工厂创建,形成产品树和工厂树的对应关系。 - **抽象工厂模式**: - 思路:在 "工厂方法模式" 的基础上,**一个工厂类负责 "多个相关产品",即==整套 "产品族"== 的构造**(例如同一品牌下的配套设备:车+轮胎+引擎)。 - **抽象工厂基类**定义**多个 `create` 接口**(对应同一族的各个产品),每种 **==具体工厂子类==** 实现各个接口,负责**某一族具体产品对象**的创建。 #### 优缺点对比 - 简单工厂模式不满足 "**开放-封闭**" 原则,将 "**判断创造哪种对象的逻辑**" 与 "**对象创建**" 混合,不够灵活,新增对象时需修改工厂类代码。 - 工厂方法模式将 "**判断创造哪种对象的逻辑**" 与 "**对象创建**" 分离,每种具体工厂类只负责一种具体产品对象的创造,更符合 "**单一职责原则**"。 - 抽象工厂模式下,**一个具体工厂类** 通常作为 "**抽象工厂模式类**" 的成员(`has-a` 关系),而后者则是对 "**一族相关产品**" 的大封装,再进一步对外提供一个 "**大接口**"——创建整个产品家族。 > [!summary] > > 实现上,三种方法都基于 "**多态**",返回的是 "**==抽象产品类==**" 的指针,而实际指向 "**具体产品类**" 对象,差异在于: > > - **简单工厂模式**:一个工厂生产 **多个产品**,根据传入参数用 if/else 或 switch 控制。 > - **工厂方法模式**:一个工厂生产 **一个特定产品**,新增产品 => 新增工厂类。 > - **抽象工厂模式**:一个工厂生产 **一族相关联的多个产品**,而无需指定具体类。 # 简单工厂模式 <br><br><br> # 工厂方法模式 Factory Method **工厂方法模式**(Factory Method)定义了一个 "**==创建对象==**" 的**接口**(抽象类),**由其==具体子类==决定实例化的对象的类型**。 其将 "业务代码" 与 "**实例化具体类**" 的代码解耦,适用于 "**事先不知道需要哪些具体类的情况**"。 > [!NOTE] 工厂模式旨在解决的问题: > > 每次 `new` 一个对象是在**针对 "具体类/具体实现" 编程**,这就导致了高耦合性——例如,当**可选的具体类**扩充时,各处涉及 `new` 的代码都需要重新修改。 > **"工厂模式" 封装了通过 `new` 这一 "创建对象" 的过程**,称之为 "**==工厂方法==**",从而进行解耦。 > <br> ### 工厂方法模式的构成 - **抽象工厂类**(也称 Creator 类):定义了 "**==工厂方法==**" 接口 `factoryMethod` ,该接口由 "**具体工厂类**" 进行实现。 - **具体工厂类**:具体实现 "**工厂方法**",决定实例化对象的具体类型。 - **抽象产品类**:定义 "**产品**" 的 **==共同接口==**。 - **具体产品类**:实现产品接口的具体类。 > [!NOTE] 工厂方法模式的类图 > ![[_attachment/02-开发笔记/16-设计模式/工厂模式.assets/IMG-工厂模式-A8218FB6945B771CDE3EE6BC16D29E9A.png|900]] <br> ### 示例代码 ```cpp #include <memory> #include <iostream> // 披萨品类 enum class PizzaType { Cheese, Veggie, Pepperoni }; // 抽象产品类 class Pizza { public: virtual void prepare() const = 0; virtual ~Pizza() = default; }; // 具体产品类11: 纽约风格的起司披萨 class NYStyleCheesePizza: public Pizza { public: void prepare() const override { std::cout << "Preparing NYStyleCheese Pizza" << std::endl; } }; // 具体产品类12: 纽约风格的蔬菜披萨 class NYStyleVeggiePizza: public Pizza { public: void prepare() const override { std::cout << "Preparing NYStyleVeggie Pizza" << std::endl; } }; // 具体产品类13: 纽约风格的胡椒披萨 class NYStylePepperoniPizza: public Pizza { public: void prepare() const override { std::cout << "Preparing NYStylePepperoni Pizza" << std::endl; } }; // 具体产品类21: 芝加哥风格的起司披萨 class ChicagoStyleCheesePizza: public Pizza { void prepare() const override { std::cout << "Preparing ChicagoStyleCheese Pizza" << std::endl; } }; // 具体产品类22: 芝加哥风格的蔬菜披萨 class ChicagoStyleVeggiePizza: public Pizza { void prepare() const override { std::cout << "Preparing ChicagoStyleVeggie Pizza" << std::endl; } }; // 具体产品类23: 芝加哥风格的胡椒披萨 class ChicagoStylePepperoniPizza: public Pizza { public: void prepare() const override { std::cout << "Preparing ChicagoStylePepperoni Pizza" << std::endl; } }; // 抽象工厂类 class PizzaStore { public: virtual std::shared_ptr<Pizza> orderPizza(PizzaType type) const = 0; virtual std::shared_ptr<Pizza> createPizza(PizzaType type) const = 0; // 工厂方法 Factory Method. virtual ~PizzaStore() = default; }; // 具体工厂类1: 纽约风味披萨店 class NYStylePizzaStore : public PizzaStore { public: std::shared_ptr<Pizza> orderPizza(PizzaType style) const { std::shared_ptr<Pizza> pizza = createPizza(style); if (pizza) { pizza->prepare(); // 对抽象产品类执行op, 与具体类型无关. } else { std::cout << "No such kind of pizza" << std::endl; } return pizza; } // 工厂方法: 封装创建对象的过程, 决定具体创建的对象类型. // 这里是 "参数化工厂方法", 根据传入参数来选择具体创建类型. std::shared_ptr<Pizza> createPizza(PizzaType style) const { // 多态 std::shared_ptr<Pizza> pizza; switch (style) { case PizzaType::Cheese: pizza = std::make_shared<NYStyleCheesePizza>(); break; case PizzaType::Veggie: pizza = std::make_shared<NYStyleVeggiePizza>(); break; case PizzaType::Pepperoni: pizza = std::make_shared<NYStylePepperoniPizza>(); break; default: pizza = nullptr; } return pizza; } }; // 具体工厂类2: 芝加哥风味披萨店 class ChicagoStylePizzaStore : public PizzaStore { public: std::shared_ptr<Pizza> orderPizza(PizzaType style) const { std::shared_ptr<Pizza> pizza = createPizza(style); pizza->prepare(); // 对抽象产品类执行op, 与具体类型无关. return pizza; }; // 工厂方法: 封装创建对象的过程, 决定具体创建的对象类型. // 这里是 "参数化工厂方法", 根据传入参数来选择具体创建类型. std::shared_ptr<Pizza> createPizza(PizzaType style) const { // 多态 std::shared_ptr<Pizza> pizza; switch (style) { case PizzaType::Cheese: pizza = std::make_shared<ChicagoStyleCheesePizza>(); break; case PizzaType::Veggie: pizza = std::make_shared<ChicagoStyleVeggiePizza>(); break; case PizzaType::Pepperoni: pizza = std::make_shared<ChicagoStylePepperoniPizza>(); break; default: pizza = nullptr; } return pizza; } }; int main() { NYStylePizzaStore nyStore; ChicagoStylePizzaStore chicagoStore; nyStore.orderPizza(PizzaType::Cheese); chicagoStore.orderPizza(PizzaType::Cheese); std::cout << std::endl; nyStore.orderPizza(PizzaType::Veggie); chicagoStore.orderPizza(PizzaType::Veggie); std::cout << std::endl; nyStore.orderPizza(PizzaType::Pepperoni); chicagoStore.orderPizza(PizzaType::Pepperoni); std::cout << std::endl; return 0; } ``` <br><br><br> # 抽象工厂模式 Abstract Factory 抽象工厂模式用于 **需要"创建==一系列 "相关" 产品==**" 的场景——**"一个工厂" 提供多个 `create` 接口,各个 `create` 接口创建的不同产品属于 "同一族相关产品"**。 ### 抽象工厂模式的构成 - **抽象工厂类**:定义 "**==一系列工厂方法==**": `createXXX()` 接口,各接口所创建的产品属于 "**同一族**"。 - **具体工厂类**:具体实现 "**工厂方法**",决定实例化对象的具体类型。 - **抽象产品类**:定义 "**产品**" 的 **==共同接口==**。 - **具体产品类**:实现产品接口的具体类。 ![[_attachment/02-开发笔记/16-设计模式/工厂模式.assets/IMG-工厂模式-BFEB983A240363AD7F4A3D3368884E42.png|946]] <br><br> <br><br> # Buffer ## 闪念 > sudden idea ## 候选资料 > Read it later # ♾️参考资料 # Footnotes