1. 工厂方法模式的定义
在简单工厂模式文中,阐述了简单工厂模式的缺点:
- 扩展性受限:如果需要添加新的产品类型,通常需要修改工厂类的逻辑,违反了开闭原则。
- 责任过重:工厂类负责创建多种产品,导致工厂类代码可能会变得非常庞大。
- 违反单一职责原则:工厂类不仅负责对象的创建,还可能包括其它业务逻辑,违反了单一职责原则。
- 静态方法限制: 静态方法不支持多态,无法通过继承扩展行为
工厂方法模式可以解决上述问题。
工厂方法模式是创建型设计模式 ,核心思想是将对象创建延迟到子类,通过多态机制实现产品族的动态扩展。 。通过定义创建对象的抽象方法,让子类决定具体实例化哪个类,完美遵循开闭原则(对扩展开放,对修改关闭)。
解决的核心问题:
- 动态扩展瓶颈:当系统需要支持新产品时,简单工厂需修改工厂类代码
- 创建逻辑定制化:不同场景需要不同的对象创建策略
- 框架级扩展:允许框架用户定义自己的产品实现
核心机制:
            
            
              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. 工厂方法模式的优缺点
优点:
- 符合开闭原则:新增产品类型时,只需新增工厂子类,无需修改现有代码。
- 降低耦合度:客户端不直接依赖具体产品类,而是依赖抽象。
- 单一职责:每个工厂只负责创建一种产品。
- 支持扩展:可以方便地添加新的产品类型。
缺点:
- 类的数量增加:每增加一个产品,就需要增加一个对应的工厂类。
- 增加系统复杂度:引入了额外的抽象层。
- 理解成本:相比直接创建对象,需要理解工厂层次结构。
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: 工厂方法模式在什么场景下不适用?
- 
产品类型固定且简单 - 解释:如果产品类型很少且不会变化,使用简单工厂或直接创建更合适。
- 例子:只有2-3种固定的配置对象,且未来不会扩展。
 
- 
性能要求极高 - 解释:工厂方法涉及虚方法调用和继承层次,有轻微性能开销。
- 例子:游戏引擎中的高频对象创建,每毫秒创建数千个对象。
 
- 
简单的一次性使用 - 解释:如果对象只在一个地方创建和使用,工厂模式会增加不必要的复杂性。
- 例子:临时的数据传输对象或简单的值对象。
 
- 
类爆炸问题严重 - 解释:每个产品都需要对应的工厂类,可能导致类数量翻倍。
- 例子:有50种产品类型,就需要50个工厂类,维护成本高。