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

类图+案例+代码详解:软件设计模式----简单工厂方法、工厂方法、抽象工厂方法

1、简单工厂方法

只一个具体的创建者类,包含一个静态的工厂方法,在该方法中根据传过来的参数(所要创建的产品类型),用条件语句进行判断来创建相应的对象。有一个产品接口(一种产品,例如保险),具体产品(同种产品不种类型的,例如意外保险、事故保险等)实现产品接口。创建类的接口与产品接口通过客户(<---client--->)进行连接。

因此,当增加具体产品时,需要修改工厂方法的判断语句,违背了开闭原则。

核心思想:找一个 “工厂” 帮你生产东西,你不用关心怎么做,只说要什么

比如你去快餐店买汉堡:

  • 你不用自己揉面、煎肉饼、组装汉堡,只需要告诉点餐机 “我要牛肉堡” 或 “鸡肉堡”

  • 点餐机(工厂)会根据你的需求,偷偷安排后厨(具体生产逻辑)做出对应的汉堡,然后交给你。

用生活案例拆解核心角色:

  1. 工厂(点餐机)

    • 负责接收 “需求”,决定创建哪种 “产品”。

    • 隐藏了具体产品的制作细节,对你来说是个 “黑盒子”。

  2. 产品(汉堡)

    • 所有汉堡都有共同特点(比如 “有面包、夹肉”),但具体类型不同(牛肉堡、鸡肉堡)。

  3. 具体产品(牛肉堡、鸡肉堡)

    • 每种汉堡的制作方式不同,但都属于 “汉堡” 家族。

代码思维:用 “if-else” 判断造什么对象

假设你要写一个 “动物创建” 的程序:

// 1. 定义产品接口(动物)
interface Animal {void makeSound();
}
​
// 2. 具体产品类(狗、猫)
class Dog implements Animal {@Overridepublic void makeSound() {System.out.println("汪汪!");}
}
​
class Cat implements Animal {@Overridepublic void makeSound() {System.out.println("喵喵!");}
}
​
// 3. 简单工厂类
class AnimalFactory {public static Animal createAnimal(String type) {if ("dog".equalsIgnoreCase(type)) {return new Dog();} else if ("cat".equalsIgnoreCase(type)) {return new Cat();}throw new IllegalArgumentException("不支持的动物类型: " + type);}
}
​
// 4. 客户端使用
public class Main {public static void main(String[] args) {// 通过工厂创建对象,无需直接newAnimal dog = AnimalFactory.createAnimal("dog");Animal cat = AnimalFactory.createAnimal("cat");dog.makeSound(); // 输出: 汪汪!cat.makeSound(); // 输出: 喵喵!}
}

简单工厂的优缺点:

  • 优点

    • 你不用关心对象怎么造的,只管用,减少了代码复杂度。

    • 比如新增 “猪” 动物时,只需要改工厂的 if-else,客户端代码不用变。

  • 缺点

    • 工厂像个 “大管家”,如果产品太多(比如 100 种动物),工厂的 if-else 会巨长无比,难以维护。

    • 这也是为什么有 “工厂方法模式” 和 “抽象工厂模式” 来优化它。

2、工厂方法

有一个创建类的接口,具体的创建类实现这个接口,每个具体的创建类只负责创建相应的具体产品。有一个产品接口(一种产品,例如保险),具体产品(同种产品不种类型的,例如意外保险、事故保险等)实现产品接口。创建类的接口与产品接口通过客户(<---client--->)进行连接。

但是,当有多种产品时,若为每种产品都创建一个创建类的接口,过于麻烦,所以有了抽象工厂方法。

也就是一个Creator对应一个Product,有多个Product则需要多个Creator。

核心思想:把 “造东西” 的权力下放给子类,每个分店自己决定怎么造

对比简单工厂(只有一个中央厨房):

  • 工厂方法模式像 “连锁快餐品牌”(比如麦当劳):

    • 总部(抽象工厂)规定 “必须卖汉堡”,但每个分店(具体工厂)可以自己决定卖 “北京分店限定汉堡” 还是 “上海分店限定汉堡”。

    • 你去哪家分店,就拿到哪家的汉堡,总部不插手具体制作。

用生活案例拆解核心角色:

  1. 抽象工厂(快餐品牌总部)

    • 定义 “创建产品” 的抽象方法(比如createHamburger()),但不具体实现。

    • 相当于规定 “每个分店必须能做汉堡”。

  2. 具体工厂(北京分店、上海分店)

    • 各自实现createHamburger()方法,决定做什么汉堡。

    • 比如北京分店做 “北京烤鸭堡”,上海分店做 “生煎牛肉堡”。

  3. 抽象产品(汉堡)

    • 定义所有汉堡的共同特征(比如eat()方法)。

  4. 具体产品(北京烤鸭堡、生煎牛肉堡)

    • 每个分店的汉堡有自己的实现方式。

代码思维:用 “抽象类 + 子类” 替代简单工厂的 if-else

用 Java 实现 “动物工厂” 案例:

// 1. 抽象产品:定义动物共同行为
interface Animal {void makeSound();
}
​
// 2. 具体产品
class Dog implements Animal {@Override public void makeSound() { System.out.println("汪汪!"); }
}
class Cat implements Animal {@Override public void makeSound() { System.out.println("喵喵!"); }
}
// 新增产品:比如猪
class Pig implements Animal {@Override public void makeSound() { System.out.println("哼哼!"); }
}
​
// 3. 抽象工厂:定义创建动物的方法,但不实现
abstract class AnimalFactory {public abstract Animal createAnimal();
}
​
// 4. 具体工厂:各自决定创建什么动物
class DogFactory extends AnimalFactory {@Override public Animal createAnimal() { return new Dog(); }
}
class CatFactory extends AnimalFactory {@Override public Animal createAnimal() { return new Cat(); }
}
// 新增工厂:猪工厂
class PigFactory extends AnimalFactory {@Override public Animal createAnimal() { return new Pig(); }
}
​
// 5. 客户端使用:选哪个工厂,就造哪种动物
public class Main {public static void main(String[] args) {// 想创建狗?找狗工厂AnimalFactory dogFactory = new DogFactory();Animal dog = dogFactory.createAnimal();dog.makeSound(); // 输出:汪汪!// 想创建猪?新增猪工厂即可,无需修改原有代码AnimalFactory pigFactory = new PigFactory();Animal pig = pigFactory.createAnimal();pig.makeSound(); // 输出:哼哼!}
}

工厂方法对比简单工厂:

模式核心区别优缺点
简单工厂一个工厂用 if-else 判断所有产品简单,但新增产品需改工厂代码
工厂方法每个产品对应一个工厂子类新增产品只需新增工厂,符合开闭原则

工厂方法的优缺点:

  • 优点

    • 新增产品时,只需新增对应的工厂子类,无需修改原有代码(开闭原则)。

    • 比如新增 “鸟” 动物,只需要写Bird类和BirdFactory类,其他代码不用动。

  • 缺点

    • 如果产品种类太多(比如 100 种动物),会导致工厂子类数量爆炸(100 个工厂类)。

3、抽象工厂方法

与工厂方法的区别是,有多个Product(多个产品系列)时,抽象工厂方法的Creator负责创建所有的Product。

但是,当增加Product时,需要对Creator进行修改,此时违背了开闭原则。

核心思想:造 “一家人” 而不是 “一个人”—— 批量生产相关联的产品家族

比如你要开一家家具厂:

  • 简单工厂 / 工厂方法只能造 “沙发” 或 “椅子” 单个产品

  • 抽象工厂能造 “北欧风沙发 + 北欧风椅子 + 北欧风茶几” 一整套家具 (每个风格就是一个 “产品家族”,工厂负责造一整套)

用生活案例拆解核心角色:

  1. 抽象工厂(家具工厂总部)

    • 定义 “创建一整套家具” 的方法(比如createSofa()createChair()),但不具体实现。

    • 相当于规定 “工厂必须能造沙发和椅子”。

  2. 具体工厂(北欧风工厂、中式工厂)

    • 实现抽象工厂的方法,决定每个家具的具体样式。

    • 北欧工厂造 “极简沙发 + 原木椅子”,中式工厂造 “红木沙发 + 雕花椅子”。

  3. 抽象产品(沙发、椅子)

    • 定义同类产品的共同特征(比如Sofa接口有use()方法)。

  4. 具体产品(北欧沙发、中式沙发、北欧椅子、中式椅子)

    • 每个工厂的产品属于同一系列(风格统一)。

代码思维:用 “工厂接口” 生产 “多个产品接口” 的实现类

用 Java 实现 “家具工厂” 案例:

// 1. 抽象产品1:沙发
interface Sofa {void use(); // 使用沙发
}
class NordicSofa implements Sofa {@Override public void use() { System.out.println("坐北欧风极简沙发"); }
}
class ChineseSofa implements Sofa {@Override public void use() { System.out.println("坐中式红木沙发"); }
}
​
// 2. 抽象产品2:椅子
interface Chair {void sit(); // 坐椅子
}
class NordicChair implements Chair {@Override public void sit() { System.out.println("坐北欧风原木椅子"); }
}
class ChineseChair implements Chair {@Override public void sit() { System.out.println("坐中式雕花椅子"); }
}
​
// 3. 抽象工厂:定义创建一整套家具的方法
interface FurnitureFactory {Sofa createSofa();      // 创建沙发Chair createChair();    // 创建椅子
}
​
// 4. 具体工厂1:北欧风格工厂
class NordicFactory implements FurnitureFactory {@Overridepublic Sofa createSofa() { return new NordicSofa(); }@Overridepublic Chair createChair() { return new NordicChair(); }
}
​
// 5. 具体工厂2:中式风格工厂
class ChineseFactory implements FurnitureFactory {@Overridepublic Sofa createSofa() { return new ChineseSofa(); }@Overridepublic Chair createChair() { return new ChineseChair(); }
}
​
// 6. 客户端使用:选工厂=选风格,直接拿一整套家具
public class Main {public static void main(String[] args) {// 想要北欧风家具?FurnitureFactory nordicFactory = new NordicFactory();Sofa nordicSofa = nordicFactory.createSofa();Chair nordicChair = nordicFactory.createChair();nordicSofa.use();    // 输出:坐北欧风极简沙发nordicChair.sit();   // 输出:坐北欧风原木椅子// 想要中式风家具?换个工厂即可FurnitureFactory chineseFactory = new ChineseFactory();chineseFactory.createSofa().use();    // 坐中式红木沙发chineseFactory.createChair().sit();   // 坐中式雕花椅子}
}

抽象工厂对比工厂方法:

模式生产能力适用场景
工厂方法生产单个产品(如一把椅子)产品种类多,但每个产品独立生产
抽象工厂生产成套产品(椅子 + 沙发)产品需成系列(风格 / 品牌统一)

抽象工厂的优缺点:

  • 优点

    • 保证同一系列产品的风格统一(比如北欧工厂绝不会造出中式沙发)。

    • 新增产品系列时(如日式家具),只需新增工厂和产品类,不修改原有代码(开闭原则)。

  • 缺点

    • 新增单个产品(如 “茶几”)需要修改所有工厂接口和实现类,违反开闭原则。 (比如抽象工厂要新增createTable()方法,所有具体工厂都要实现)

总结

简单工厂:一个工厂造所有东西(用 if-else)

工厂方法:每个产品有专属工厂(分权给子类)

抽象工厂:一个工厂造一整套东西(家族化生产)

http://www.lqws.cn/news/575983.html

相关文章:

  • 腾讯云实名资质 “待补充后提交” 解决方法
  • 蓝桥杯51单片机设计
  • 青少年编程与数学 02-022 专业应用软件简介 04 矢量图形设计软件:CorelDRAW
  • 华为云Flexus+DeepSeek征文 | Word办公软件接入华为云ModelArts Studio大模型,实现AI智能办公
  • 【Unity】MiniGame编辑器小游戏(七)贪吃蛇【Snake】
  • Rust C++ OpenCV kafka-rs实践
  • 【Wireshark】高级过滤技巧精讲
  • 【c/c++3】类和对象,vector容器,类继承和多态,systemd,stdboost
  • 【c/c++1】数据类型/指针/结构体,static/extern/makefile/文件
  • 利用deepseek学术搜索
  • HTTP中常见的Content-Type
  • [Android]ANR的线程
  • Redis Cluster Gossip 协议
  • C++高效结合主流工具:现代系统底层动力
  • 机电一体化论文写作实战指南:从创新设计到工程验证的完整路径
  • 面试复盘6.0
  • mybatis-plus从入门到入土(一):快速开始
  • Windows安装虚拟机、ROS2
  • 实战四:基于PyTorch实现猫狗分类的web应用【2/3】
  • springboot校园新闻网站
  • 如果将Word里每页的行数设置成50行
  • STM32——HAL库总结
  • ECMAScript 2019(ES2019):数组与对象操作的精细化升级
  • PYTHON从入门到实践10-文件操作与异常
  • MySQL-复合查询
  • 推荐几本关于网络安全的书
  • 暴力风扇方案介绍
  • 【学习】《算法图解》第八章学习笔记:平衡树
  • docker的离线安装
  • [数论](a % MOD + b % MOD) % MOD = (a + b) % MOD