工厂方法模式

点击阅读:设计模式系列文章


1. 工厂方法模式的定义

简单工厂模式文中,阐述了简单工厂模式的缺点:

  1. 扩展性受限:如果需要添加新的产品类型,通常需要修改工厂类的逻辑,违反了开闭原则。
  2. 责任过重:工厂类负责创建多种产品,导致工厂类代码可能会变得非常庞大。
  3. 违反单一职责原则:工厂类不仅负责对象的创建,还可能包括其它业务逻辑,违反了单一职责原则。
  4. 静态方法限制: 静态方法不支持多态,无法通过继承扩展行为

工厂方法模式可以解决上述问题。

工厂方法模式是创建型设计模式 ,核心思想是将对象创建延迟到子类,通过多态机制实现产品族的动态扩展。 。通过定义创建对象的抽象方法,让子类决定具体实例化哪个类,完美遵循开闭原则(对扩展开放,对修改关闭)。

解决的核心问题

  1. 动态扩展瓶颈:当系统需要支持新产品时,简单工厂需修改工厂类代码
  2. 创建逻辑定制化:不同场景需要不同的对象创建策略
  3. 框架级扩展:允许框架用户定义自己的产品实现

核心机制:

java 复制代码
abstract class Creator {
    // 工厂方法 - 延迟到子类实现
    protected abstract Product factoryMethod();
    
    // 模板方法
    public final void businessLogic() {
        Product product = factoryMethod(); // 运行时多态调用
        product.operation();
    }
}

2. 工厂方法模式的结构

工厂方法模式主要包含以下角色:

  • Creator(抽象创建者):定义工厂方法接口,包含调用工厂方法的业务逻辑。
  • ConcreteCreator(具体创建者):实现工厂方法,负责创建具体产品。
  • Product(抽象产品):定义产品的接口。
  • ConcreteProduct(具体产品):实现产品接口的具体类。
txt 复制代码
Creator (抽象)
    |
    |-- factoryMethod() : Product
    |-- businessLogic()
    |
ConcreteCreator --> ConcreteProduct
    |
Product (抽象)
    |
ConcreteProduct

特点

  • 每个具体工厂负责创建一种具体产品。
  • 客户端通过抽象工厂接口使用,不依赖具体实现。
  • 新增产品类型时,只需新增对应的工厂子类。

2.1 Creator 抽象创建者

java 复制代码
public abstract class ShapeFactory {
    // 工厂方法 - 延迟到子类实现
    protected abstract Shape createShape();
    
    public final void render() {
        Shape shape = createShape();
        System.out.println("开始渲染图形:");
        shape.draw();
        System.out.println("渲染完成");
    }
}

2.2 Product 抽象产品

java 复制代码
public interface Shape {
    void draw();
}

public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制圆形 ○");
    }
}

public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制正方形 □");
    }
}

2.3 ConcreteCreator 具体创建者

java 复制代码
public class CircleFactory extends ShapeFactory {
    @Override
    protected Shape createShape() {
        return new Circle();
    }
}

public class SquareFactory extends ShapeFactory {
    @Override
    protected Shape createShape() {
        return new Square();
    }
}

2.4 Client 客户端

java 复制代码
public class Client {
    public static void main(String[] args) {
        // 创建圆形
        ShapeFactory circleFactory = new CircleFactory();
        circleFactory.render();
        
        // 创建正方形
        ShapeFactory squareFactory = new SquareFactory();
        squareFactory.render();
    }
}

3. 工厂方法模式的优缺点

优点:

  1. 符合开闭原则:新增产品类型时,只需新增工厂子类,无需修改现有代码。
  2. 降低耦合度:客户端不直接依赖具体产品类,而是依赖抽象。
  3. 单一职责:每个工厂只负责创建一种产品。
  4. 支持扩展:可以方便地添加新的产品类型。

缺点:

  1. 类的数量增加:每增加一个产品,就需要增加一个对应的工厂类。
  2. 增加系统复杂度:引入了额外的抽象层。
  3. 理解成本:相比直接创建对象,需要理解工厂层次结构。

4. 工厂方法模式的设计思想

  • 延迟实例化:将对象创建延迟到子类中进行。
  • 多态性:通过继承和多态实现不同产品的创建。
  • 模板方法:在抽象类中定义算法骨架,具体步骤由子类实现。
  • 依赖倒置:高层模块不依赖低层模块,都依赖于抽象。

5. 一些问题

Q1: 工厂方法模式与简单工厂模式的区别是什么?

A1:

  • 简单工厂模式:用一个工厂类创建所有产品,新增产品需要修改工厂类
  • 工厂方法模式:每个产品对应一个工厂类,新增产品只需新增工厂类
  • 核心区别:简单工厂违反开闭原则,工厂方法符合开闭原则
java 复制代码
// 简单工厂:集中创建,需要修改工厂类
class SimpleFactory {
    public static Shape createShape(String type) {
        switch (type) {
            case "circle": return new Circle();
            case "square": return new Square();
            // 新增产品需要修改这里
            default: throw new IllegalArgumentException();
        }
    }
}

// 工厂方法:分散创建,新增工厂子类
abstract class ShapeFactory {
    abstract Shape createShape();
}
class CircleFactory extends ShapeFactory { /* ... */ }
class SquareFactory extends ShapeFactory { /* ... */ }
// 新增产品只需新增工厂类

Q2: 工厂方法模式在什么场景下不适用?

  1. 产品类型固定且简单

    • 解释:如果产品类型很少且不会变化,使用简单工厂或直接创建更合适。
    • 例子:只有2-3种固定的配置对象,且未来不会扩展。
  2. 性能要求极高

    • 解释:工厂方法涉及虚方法调用和继承层次,有轻微性能开销。
    • 例子:游戏引擎中的高频对象创建,每毫秒创建数千个对象。
  3. 简单的一次性使用

    • 解释:如果对象只在一个地方创建和使用,工厂模式会增加不必要的复杂性。
    • 例子:临时的数据传输对象或简单的值对象。
  4. 类爆炸问题严重

    • 解释:每个产品都需要对应的工厂类,可能导致类数量翻倍。
    • 例子:有50种产品类型,就需要50个工厂类,维护成本高。
相关推荐
青鱼入云3 小时前
【面试场景题】订单超时自动取消功能如何设计
面试
future_studio4 小时前
如何用 Kotlin 在 Android 手机开发一个小闹钟、计时器、秒表
android·智能手机·kotlin
Deepsleep.4 小时前
前端常见安全问题 + 防御方法 + 面试回答
前端·安全·面试
zhangguojia74 小时前
android中常见布局及其约束
android
猪哥帅过吴彦祖4 小时前
JavaScript Set 和 Map:现代 JavaScript 的数据结构双雄
前端·javascript·面试
paynnne4 小时前
Android 事件分发机制
android
郝学胜-神的一滴4 小时前
策略模式:模拟八路军的抗日策略
开发语言·c++·程序人生·设计模式·策略模式
水牛4 小时前
一行代码完成startActivityForResult
android·android jetpack
秋难降4 小时前
结构型模式 “全家桶”:适配、装饰、代理…7 种模式让你的代码更 “有章法”
java·设计模式·程序员