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

设计模式(工厂模式)

工厂设计模式:打造你的代码生产线

引言

想象一下,你正站在一家现代化的玩具工厂门前。工厂内部,各种机器有条不紊地运转,原材料在传送带上流动,最终变成精美的玩具。你不需要了解每个玩具的具体制作工艺,只需告诉工厂经理:“我需要一个泰迪熊”,工厂就会为你生产出来。这正是工厂设计模式的核心思想 — 封装对象的创建过程,使客户端代码与具体产品的实现细节解耦

在这里插入图片描述

什么是工厂设计模式?

工厂设计模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,而是通过使用一个共同的接口来指向新创建的对象。

工厂模式主要分为三种类型:

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

简单工厂模式:披萨店的点单系统

场景描述

想象你走进了一家披萨店。你不需要自己准备面团、酱料和配料,只需告诉服务员你想要什么类型的披萨(如"奶酪披萨"、“素食披萨"或"肉食披萨”),服务员就会将你的订单传递给厨房,厨房(工厂)将为你制作披萨。

在这里插入图片描述

代码实现

// 披萨接口
interface Pizza {void prepare();void bake();void cut();void box();
}// 具体披萨类 - 奶酪披萨
class CheesePizza implements Pizza {@Overridepublic void prepare() {System.out.println("准备奶酪披萨的原料...");}@Overridepublic void bake() {System.out.println("烘烤奶酪披萨...");}@Overridepublic void cut() {System.out.println("切割奶酪披萨...");}@Overridepublic void box() {System.out.println("包装奶酪披萨...");}
}// 具体披萨类 - 素食披萨
class VeggiePizza implements Pizza {@Overridepublic void prepare() {System.out.println("准备素食披萨的原料...");}@Overridepublic void bake() {System.out.println("烘烤素食披萨...");}@Overridepublic void cut() {System.out.println("切割素食披萨...");}@Overridepublic void box() {System.out.println("包装素食披萨...");}
}// 简单工厂
class SimplePizzaFactory {public Pizza createPizza(String type) {Pizza pizza = null;if (type.equals("cheese")) {pizza = new CheesePizza();} else if (type.equals("veggie")) {pizza = new VeggiePizza();}// 可以添加更多披萨类型...return pizza;}
}// 披萨店类
class PizzaStore {private SimplePizzaFactory factory;public PizzaStore(SimplePizzaFactory factory) {this.factory = factory;}public Pizza orderPizza(String type) {Pizza pizza = factory.createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}
}// 客户端代码
public class SimplePizzaExample {public static void main(String[] args) {SimplePizzaFactory factory = new SimplePizzaFactory();PizzaStore store = new PizzaStore(factory);// 订购奶酪披萨Pizza cheesePizza = store.orderPizza("cheese");System.out.println("小明订购了一个奶酪披萨\n");// 订购素食披萨Pizza veggiePizza = store.orderPizza("veggie");System.out.println("小红订购了一个素食披萨");}
}

简单工厂模式的优缺点

优点:

  • 客户端不需要知道具体产品类的类名,只需知道对应的参数即可
  • 将创建实例的过程与使用实例的过程分离,使用者不必关心创建的细节

缺点:

  • 工厂类集中了所有产品的创建逻辑,一旦工厂类出现问题,整个系统都会受到影响
  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,违反了开闭原则

工厂方法模式:特色地区披萨店连锁

场景描述

随着业务扩展,披萨店开始在不同城市开设分店。每个地区的分店都有自己的特色披萨。比如,纽约店的披萨饼皮薄而脆,而芝加哥店的披萨饼皮厚实松软。这时候,简单工厂已经不能满足需求,需要让各个分店能够创建自己特色的披萨。
在这里插入图片描述

代码实现

// 披萨接口
interface Pizza {void prepare();void bake();void cut();void box();String getName();
}// 纽约风格奶酪披萨
class NYStyleCheesePizza implements Pizza {private String name = "纽约风格奶酪披萨";@Overridepublic void prepare() {System.out.println("准备 " + name);}@Overridepublic void bake() {System.out.println("烘烤25分钟");}@Overridepublic void cut() {System.out.println("对角线切片");}@Overridepublic void box() {System.out.println("放入纽约披萨店盒子中");}@Overridepublic String getName() {return name;}
}// 芝加哥风格奶酪披萨
class ChicagoStyleCheesePizza implements Pizza {private String name = "芝加哥风格深盘奶酪披萨";@Overridepublic void prepare() {System.out.println("准备 " + name);}@Overridepublic void bake() {System.out.println("烘烤40分钟");}@Overridepublic void cut() {System.out.println("方块切片");}@Overridepublic void box() {System.out.println("放入芝加哥披萨店盒子中");}@Overridepublic String getName() {return name;}
}// 抽象披萨店
abstract class PizzaStore {public Pizza orderPizza(String type) {Pizza pizza = createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}// 工厂方法protected abstract Pizza createPizza(String type);
}// 纽约披萨店
class NYPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {if (type.equals("cheese")) {return new NYStyleCheesePizza();}// 可以添加更多纽约风格披萨...return null;}
}// 芝加哥披萨店
class ChicagoPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {if (type.equals("cheese")) {return new ChicagoStyleCheesePizza();}// 可以添加更多芝加哥风格披萨...return null;}
}// 客户端代码
public class FactoryMethodExample {public static void main(String[] args) {PizzaStore nyStore = new NYPizzaStore();PizzaStore chicagoStore = new ChicagoPizzaStore();Pizza pizza = nyStore.orderPizza("cheese");System.out.println("小明订购了 " + pizza.getName() + "\n");pizza = chicagoStore.orderPizza("cheese");System.out.println("小红订购了 " + pizza.getName());}
}

工厂方法模式的优缺点

优点:

  • 符合开闭原则,新增产品时,只需添加具体工厂和产品类,不需要修改原有代码
  • 符合单一职责原则,每个具体工厂只负责创建对应的产品
  • 客户端只需要知道产品的抽象类,无须关心具体实现类

缺点:

  • 类的个数容易过多,增加复杂度
  • 增加了系统的抽象性和理解难度

抽象工厂模式:披萨原料工厂

场景描述

随着披萨连锁店的成功,管理层决定统一原料供应链,确保每家分店都使用高质量的原料。不同地区的披萨店需要使用不同风格的原料(如纽约的薄面团和马苏里拉奶酪,芝加哥的厚面团和意大利白干酪)。

在这里插入图片描述

代码实现

// 原料接口
interface Dough {String toString();
}interface Sauce {String toString();
}interface Cheese {String toString();
}// 具体原料类
class ThinCrustDough implements Dough {public String toString() {return "薄饼皮";}
}class ThickCrustDough implements Dough {public String toString() {return "厚饼皮";}
}class MarinaraSauce implements Sauce {public String toString() {return "番茄酱";}
}class PlumTomatoSauce implements Sauce {public String toString() {return "李子番茄酱";}
}class MozzarellaCheese implements Cheese {public String toString() {return "马苏里拉奶酪";}
}class ReggianoCheese implements Cheese {public String toString() {return "雷吉亚诺奶酪";}
}// 抽象原料工厂
interface PizzaIngredientFactory {Dough createDough();Sauce createSauce();Cheese createCheese();// 可以添加更多原料...
}// 具体原料工厂 - 纽约
class NYPizzaIngredientFactory implements PizzaIngredientFactory {@Overridepublic Dough createDough() {return new ThinCrustDough();}@Overridepublic Sauce createSauce() {return new MarinaraSauce();}@Overridepublic Cheese createCheese() {return new ReggianoCheese();}
}// 具体原料工厂 - 芝加哥
class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory {@Overridepublic Dough createDough() {return new ThickCrustDough();}@Overridepublic Sauce createSauce() {return new PlumTomatoSauce();}@Overridepublic Cheese createCheese() {return new MozzarellaCheese();}
}// 抽象产品 - 披萨
abstract class Pizza {String name;Dough dough;Sauce sauce;Cheese cheese;abstract void prepare();void bake() {System.out.println("烘烤175度,25分钟");}void cut() {System.out.println("将披萨对角切片");}void box() {System.out.println("将披萨放在官方盒子里");}void setName(String name) {this.name = name;}String getName() {return name;}public String toString() {StringBuilder result = new StringBuilder();result.append("---- ").append(name).append(" ----\n");if (dough != null) {result.append(dough).append("\n");}if (sauce != null) {result.append(sauce).append("\n");}if (cheese != null) {result.append(cheese);}return result.toString();}
}// 具体产品 - 奶酪披萨
class CheesePizza extends Pizza {PizzaIngredientFactory ingredientFactory;public CheesePizza(PizzaIngredientFactory ingredientFactory) {this.ingredientFactory = ingredientFactory;}@Overridevoid prepare() {System.out.println("准备 " + name);dough = ingredientFactory.createDough();sauce = ingredientFactory.createSauce();cheese = ingredientFactory.createCheese();}
}// 改进后的披萨店
abstract class PizzaStore {public Pizza orderPizza(String type) {Pizza pizza = createPizza(type);pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}protected abstract Pizza createPizza(String type);
}// 纽约披萨店
class NYPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {Pizza pizza = null;PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();if (type.equals("cheese")) {pizza = new CheesePizza(ingredientFactory);pizza.setName("纽约风格奶酪披萨");}// 可以添加更多纽约风格披萨...return pizza;}
}// 芝加哥披萨店
class ChicagoPizzaStore extends PizzaStore {@Overrideprotected Pizza createPizza(String type) {Pizza pizza = null;PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory();if (type.equals("cheese")) {pizza = new CheesePizza(ingredientFactory);pizza.setName("芝加哥风格奶酪披萨");}// 可以添加更多芝加哥风格披萨...return pizza;}
}// 客户端代码
public class AbstractFactoryExample {public static void main(String[] args) {PizzaStore nyStore = new NYPizzaStore();PizzaStore chicagoStore = new ChicagoPizzaStore();Pizza pizza = nyStore.orderPizza("cheese");System.out.println("小明订购了:\n" + pizza + "\n");pizza = chicagoStore.orderPizza("cheese");System.out.println("小红订购了:\n" + pizza);}
}

抽象工厂模式的优缺点

优点:

  • 产品族的约束性,确保一系列相关的产品对象被一起创建
  • 将一个系列的产品族统一到一起创建,减少了具体产品对象的依赖
  • 符合开闭原则,易于扩展,可以在不修改已有代码的情况下引入新的产品族

缺点:

  • 扩展产品族比较困难,需要修改抽象工厂的接口
  • 比工厂方法模式更加抽象,更难理解

工厂模式在实际开发中的应用

工厂模式在许多框架和应用中被广泛使用:

  1. Java集合框架Collections.singleton()Collections.singletonList()等方法都是工厂方法的实现。

  2. JDBC连接数据库:通过DriverManager.getConnection()方法获取数据库连接对象,隐藏了具体数据库连接的细节。

  3. Spring框架:Spring的BeanFactory是工厂模式的典型应用,它根据配置文件创建不同的Bean对象。

  4. 日志框架:如Log4j、SLF4J等,它们使用工厂模式创建不同的日志对象。

总结

工厂设计模式是一种非常实用的创建型设计模式,它通过封装对象的创建过程,使客户端代码与具体产品的实现细节解耦。根据不同的需求和场景,我们可以选择使用简单工厂、工厂方法或抽象工厂。

  • 简单工厂:适用于产品种类相对固定,变化不大的场景。
  • 工厂方法:适用于产品种类多样化,需要不同工厂创建不同产品的场景。
  • 抽象工厂:适用于需要创建一系列相关或依赖对象的场景,无须指定它们的具体类。

相关文章:

  • VUE篇之树形特殊篇
  • 探寻软件稳定性的奥秘
  • 【最新 MCP 战神手册 09】利用资源和提示增强上下文
  • 【记录】Python调用大模型(以Deepseek和Qwen为例)
  • 使用 np.zeros_like(label) 保存预测概率时发现数据类型不匹配导致的隐式类型转换
  • 局域网视频会议软件BeeWorks Meet
  • 软考高项(信息系统项目管理师)第 4 版全章节核心考点解析(力扬老师课程精华版)
  • MES系列-ISO95 IEC/ISO 62264
  • 推荐系统中 Label 回收机制之【时间窗口设计】
  • Agent开源工具:mcp快速接入,mcp-use上手指南
  • 极客天成参与”AI助力智慧城市构建”主题演讲暨招商引智专题推介活动
  • 哈希表笔记(一 )
  • 使用C# ASP.NET创建一个可以由服务端推送信息至客户端的WEB应用(一)
  • 简单音频比较
  • 信息科技伦理与道德3-4:面临挑战
  • 前端与后端开发详解:从概念到就业技能指南
  • 【零基础】Ubuntu22.04本地部署Dify
  • Nginx 核心功能笔记
  • 案例解析:基于量子计算的分子对接-QDOCK(Quantum Docking)
  • 告别碎片化!两大先进分块技术如何提升RAG的语义连贯性?
  • 上海“模速空间”:将形成人工智能“北斗七星”和群星态势
  • 巴西外长维埃拉:国际形势日益复杂,金砖国家必须发挥核心作用
  • “不意外”和“不遗余力”,直击上海商超对接外贸企业
  • 日本大米价格连续16周上涨,再创最高纪录
  • 影子调查丨危房之下,百余住户搬离梦嘉商贸楼
  • 四川邻水县县长石国平拟任县(市、区)党委书记