rokevin
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
移动
前端
语言
  • 基础

    • Linux
    • 实施
    • 版本构建
  • 应用

    • WEB服务器
    • 数据库
  • 资讯

    • 工具
    • 部署
开放平台
产品设计
  • 人工智能
  • 云计算
计算机
其它
GitHub
  • 工厂方法模式(Factory Method Pattern)

  • 简单工厂模式
  • 简单工厂(反射)
  • 多个工厂方法模式
  • 静态工厂方法模式
  • 一、工厂方法模式核心概念(通用)
    • 1. 定义
    • 2. 意图
    • 3. 通用核心组件
  • 二、工厂方法模式详细解析(以 “汽车生产” 为例)
    • 1. 结构
    • 2. 类图(Mermaid)
    • 3. 时序图(Mermaid)
    • 4. 优点
    • 5. 缺点
  • 三、Java 代码实现(汽车生产示例)
    • 1. 抽象产品(Car)
    • 2. 具体产品(Benz、BMW)
    • 3. 抽象工厂(CarFactory)
    • 4. 具体工厂(BenzFactory、BMWFactory)
    • 5. 客户端(Client)
    • 6. 输出结果(使用 BenzFactory 时)
    • 7. 新增产品(奥迪车)的扩展示例
  • 四、适用环境
  • 五、模式分析
    • 1. 核心本质
    • 2. 与其他模式的区别
    • 3. 关键设计原则
  • 六、模式扩展
    • 1. 带默认实现的抽象工厂
    • 2. 工厂方法返回缓存对象
    • 3. 参数化工厂方法
    • 4. 静态工厂方法(非模式标准,但广泛使用)
  • 七、模式应用(通用 + Android)
    • 1. 通用领域应用
    • 2. Android 中的应用
      • (1)BitmapFactory(核心应用)
      • (2)LayoutInflater(布局加载器)
      • (3)ViewModelProvider.Factory(ViewModel 创建)
      • (4)IntentService(服务创建)
  • 八、总结

工厂方法模式(Factory Method Pattern)

工厂方法模式是创建型设计模式的核心成员,其核心目标是定义一个创建对象的接口,但让实现这个接口的子类决定实例化哪个类,从而将对象的创建延迟到子类。它如同现实中的 “汽车工厂”—— 抽象工厂定义 “生产汽车” 的标准,具体工厂(如奔驰工厂、宝马工厂)分别负责生产对应的汽车,新增车型时只需新增对应的工厂,无需修改原有工厂逻辑。

public interface ShirtProducer {

    void produceShirt();

}
public class ManShirtProducer implements ShirtProducer {

    @Override
    public void produceShirt() {
        System.out.println("produce man shirt.");
    }

}
public class WomanShirtProducer implements ShirtProducer {

    @Override
    public void produceShirt() {
        System.out.println("produce woman shirt.");
    }

}

简单工厂模式

public class SimpleShirtFactory {

    public ShirtProducer produce(String shirtType) {
        if ("t-shirt".equals(shirtType)) {
            return new WomanShirtProducer();
        } else {
            return new ManShirtProducer();
        }
    }
}

简单工厂(反射)

public class ReflectSimpleShirtFactory {

    public ShirtProducer produce(String shirtType)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<?> ShirtProducer = Class.forName(shirtType);
        return (ShirtProducer) ShirtProducer.newInstance();
    }
}

多个工厂方法模式

对普通工厂方法模式的改进,在普通工厂方法模式中,如果传递的字符串出错,则不能正确创建对象,而多个工厂方法模式是提供多个工厂方法,分别创建对象。

public class MultiShirtFactory {

    public ShirtProducer produceManShirt() {
        return new ManShirtProducer();
    }

    public ShirtProducer produceWomanShirt() {
        return new WomanShirtProducer();
    }

}

静态工厂方法模式

将多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可。

public class StaticMultiShirtFactory {

    public static ShirtProducer produceShirt() {
        return new ManShirtProducer();
    }

    public static ShirtProducer produceTShirt() {
        return new WomanShirtProducer();
    }

}
public class ShirtFactoryMain {

    public static void main(String[] args) {
        System.out.println("普通工厂模式");
        SimpleShirtFactory shirtFactory1 = new SimpleShirtFactory();
        ShirtProducer shirtProducer1 = shirtFactory1.produce("shirt");
        shirtProducer1.produceShirt();

        try {
            System.out.println("普通工厂模式(反射)");
            ReflectSimpleShirtFactory shirtFactory11 = new ReflectSimpleShirtFactory();
            ShirtProducer shirtProducer11 = shirtFactory11.produce(ManShirtProducer.class.getName());
            shirtProducer11.produceShirt();
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        
        System.out.println("多工厂方法模式");
        MultiShirtFactory shirtFactory2 = new MultiShirtFactory();
        ShirtProducer shirtProducer2 = shirtFactory2.produceManShirt();
        shirtProducer2.produceShirt();
        
        System.out.println("静态工厂方法模式");
        ShirtProducer shirtProducer3 = StaticMultiShirtFactory.produceShirt();
        shirtProducer3.produceShirt();
    }

}

一、工厂方法模式核心概念(通用)

1. 定义

定义一个用于创建对象的接口(抽象工厂),让子类(具体工厂)决定实例化哪一个类(具体产品)。工厂方法使一个类的实例化延迟到其子类。

2. 意图

  • 解决简单工厂的扩展性问题:简单工厂模式中,新增产品需修改工厂类逻辑(违反 “开闭原则”);工厂方法模式将产品创建逻辑分散到具体工厂子类,新增产品只需新增子类,无需修改原有代码。
  • 分离对象创建与使用:客户端只需关心抽象产品和抽象工厂,无需知道具体产品的类名和创建细节(如 “我要一辆车”,无需知道是奔驰还是宝马的生产过程)。
  • 支持多态创建:不同具体工厂可创建不同类型的产品,客户端通过切换具体工厂实现产品的动态切换(如从 “奔驰工厂” 切换到 “宝马工厂”,即可获得不同产品)。

3. 通用核心组件

工厂方法模式通过 “抽象工厂定义接口,具体工厂实现创建逻辑” 实现对象创建的延迟,包含 4 个核心角色:

角色名称职责描述
Product(抽象产品)定义所有产品的共同接口或抽象类,声明产品的核心业务方法(如汽车的 “行驶” 方法)。
ConcreteProduct(具体产品)实现抽象产品接口,是工厂方法模式的创建目标(如奔驰车、宝马车)。
Factory(抽象工厂)声明工厂方法(factoryMethod()),返回一个 Product 类型的对象。抽象工厂可定义默认实现(可选),或仅作为接口。
ConcreteFactory(具体工厂)继承或实现抽象工厂,重写工厂方法,返回具体产品实例(如BenzFactory的createCar()返回Benz对象)。

二、工厂方法模式详细解析(以 “汽车生产” 为例)

以 “汽车生产系统” 为场景:系统需支持多种汽车(奔驰、宝马)的生产,且未来可能新增更多品牌(如奥迪)。若用简单工厂,新增品牌需修改CarFactory的createCar()方法(添加if-else);工厂方法模式通过BenzFactory、BMWFactory等具体工厂分别生产对应汽车,新增奥迪时只需新增Audi(具体产品)和AudiFactory(具体工厂),无需修改现有代码。

1. 结构

  1. Product(抽象产品):Car,定义drive()方法(汽车行驶)。
  2. ConcreteProduct(具体产品):Benz(奔驰)、BMW(宝马),实现drive()方法(具体行驶逻辑)。
  3. Factory(抽象工厂):CarFactory,声明createCar()方法(返回Car对象)。
  4. ConcreteFactory(具体工厂):BenzFactory、BMWFactory,重写createCar(),分别返回Benz、BMW实例。

2. 类图(Mermaid)

classDiagram
    %% 抽象产品:汽车接口
    class Car {
        <<Interface>>
        +drive(): void  // 汽车行驶
    }

    %% 具体产品1:奔驰车
    class Benz {
        +drive(): void  // 实现奔驰行驶逻辑
    }

    %% 具体产品2:宝马车
    class BMW {
        +drive(): void  // 实现宝马行驶逻辑
    }

    %% 抽象工厂:汽车工厂接口
    class CarFactory {
        <<Interface>>
        +createCar(): Car  // 工厂方法:创建汽车
    }

    %% 具体工厂1:奔驰工厂
    class BenzFactory {
        +createCar(): Car  // 实现:返回Benz实例
    }

    %% 具体工厂2:宝马工厂
    class BMWFactory {
        +createCar(): Car  // 实现:返回BMW实例
    }

    %% 客户端:使用工厂和产品
    class Client {
        +useCar(): void
    }

    %% 关系梳理
    
    %% 具体产品实现抽象产品
    Car <|-- Benz
    Car <|-- BMW
    
    %%具体工厂实现抽象工厂
    CarFactory <|-- BenzFactory
    CarFactory <|-- BMWFactory
    BenzFactory --> Benz : 创建(返回实例)
    BMWFactory --> BMW : 创建(返回实例)
    Client --> CarFactory : 依赖抽象工厂
    Client --> Car : 依赖抽象产品

3. 时序图(Mermaid)

以 “客户端通过奔驰工厂创建并使用奔驰车” 为例,展示工厂方法模式的调用流程:

sequenceDiagram
    participant Client(客户端)
    participant BenzFactory(具体工厂:奔驰工厂)
    participant Benz(具体产品:奔驰车)
    participant CarFactory(抽象工厂)
    participant Car(抽象产品)

    %% 1. 客户端选择具体工厂(奔驰工厂)
    Client->>BenzFactory: new BenzFactory()
    BenzFactory-->>Client: 返回BenzFactory实例

    %% 2. 客户端通过抽象工厂接口调用工厂方法
    Client->>CarFactory: createCar()(多态调用BenzFactory的实现)
    BenzFactory->>Benz: new Benz()(具体工厂创建具体产品)
    Benz-->>BenzFactory: 返回Benz实例
    BenzFactory-->>Car: 返回Benz实例(向上转型为Car)
    Car-->>Client: 返回Car类型的Benz实例

    %% 3. 客户端通过抽象产品接口使用产品
    Client->>Car: drive()(多态调用Benz的实现)
    Benz->>Client: 执行奔驰车的drive():"Benz is driving..."

4. 优点

  • 符合开闭原则:新增产品时,只需新增具体产品类和对应的具体工厂类,无需修改现有工厂和客户端代码(如新增奥迪车,只需添加Audi和AudiFactory)。
  • 降低耦合度:客户端仅依赖抽象产品(Car)和抽象工厂(CarFactory),不直接依赖具体产品和工厂,符合 “依赖倒置原则”。
  • 封装产品创建细节:客户端无需知道具体产品的类名(如Benz),只需通过工厂获取产品,简化客户端逻辑。
  • 支持多态创建:不同具体工厂可创建不同产品,客户端通过切换工厂实现产品的动态替换(如从BenzFactory切换到BMWFactory)。

5. 缺点

  • 类数量增加:每个具体产品对应一个具体工厂,产品种类增多时,类数量会成对增加(如 n 个产品对应 n 个工厂),增加系统复杂度。
  • 客户端需了解工厂类型:客户端需知道哪个具体工厂对应哪种产品(如 “要奔驰车需用BenzFactory”),否则无法正确获取所需产品。
  • 抽象层次提高:相比简单工厂模式,引入了更多抽象(抽象产品、抽象工厂),对新手而言理解难度略高。

三、Java 代码实现(汽车生产示例)

1. 抽象产品(Car)

定义所有汽车的共同接口:

// 抽象产品:汽车接口
public interface Car {
    // 汽车行驶方法
    void drive();
}

2. 具体产品(Benz、BMW)

实现抽象产品,提供具体功能:

// 具体产品1:奔驰车
public class Benz implements Car {
    @Override
    public void drive() {
        System.out.println("奔驰车:平稳行驶中...");
    }
}

// 具体产品2:宝马车
public class BMW implements Car {
    @Override
    public void drive() {
        System.out.println("宝马车:激情驾驶中...");
    }
}

3. 抽象工厂(CarFactory)

声明工厂方法,定义创建产品的接口:

// 抽象工厂:汽车工厂接口
public interface CarFactory {
    // 工厂方法:创建汽车(返回抽象产品类型)
    Car createCar();
}

4. 具体工厂(BenzFactory、BMWFactory)

实现工厂方法,创建具体产品:

// 具体工厂1:奔驰工厂
public class BenzFactory implements CarFactory {
    @Override
    public Car createCar() {
        // 可在此添加奔驰车的创建细节(如配置、质检)
        return new Benz();
    }
}

// 具体工厂2:宝马工厂
public class BMWFactory implements CarFactory {
    @Override
    public Car createCar() {
        // 可在此添加宝马车的创建细节
        return new BMW();
    }
}

5. 客户端(Client)

通过抽象工厂和抽象产品使用系统,无需依赖具体类:

// 客户端:使用汽车工厂
public class Client {
    public static void main(String[] args) {
        // 1. 选择具体工厂(可动态切换,如从配置文件读取)
        CarFactory factory = new BenzFactory(); // 奔驰工厂
        // CarFactory factory = new BMWFactory(); // 切换为宝马工厂

        // 2. 通过工厂方法获取产品(返回抽象产品类型)
        Car car = factory.createCar();

        // 3. 使用产品(通过抽象接口调用)
        car.drive();
    }
}

6. 输出结果(使用 BenzFactory 时)

奔驰车:平稳行驶中...

若切换为BMWFactory,输出结果为:

宝马车:激情驾驶中...

7. 新增产品(奥迪车)的扩展示例

无需修改现有代码,只需新增具体产品和工厂:

// 新增具体产品:奥迪车
public class Audi implements Car {
    @Override
    public void drive() {
        System.out.println("奥迪车:科技驾驶中...");
    }
}

// 新增具体工厂:奥迪工厂
public class AudiFactory implements CarFactory {
    @Override
    public Car createCar() {
        return new Audi();
    }
}

// 客户端使用新工厂
public class Client {
    public static void main(String[] args) {
        CarFactory factory = new AudiFactory(); // 新增工厂
        Car car = factory.createCar();
        car.drive(); // 输出:奥迪车:科技驾驶中...
    }
}

四、适用环境

工厂方法模式适用于以下场景,核心判断标准是 “产品种类可能扩展,且需将创建与使用分离”:

  1. 产品种类不确定,可能扩展:如日志系统(可能新增文件日志、数据库日志)、支付系统(可能新增支付宝、微信支付),新增产品时需避免修改现有代码。
  2. 客户端不依赖具体产品的创建细节:客户端只需知道 “获取产品”,无需知道产品的类名、初始化参数等(如 “我要支付”,无需知道支付接口的具体实现)。
  3. 需要通过子类决定创建哪种产品:父类无法预测需要创建的具体产品(如框架设计中,框架只定义接口,由用户实现具体产品和工厂)。
  4. 需封装产品创建过程:产品创建逻辑复杂(如需配置、初始化、校验),需将这些逻辑集中到工厂中,避免客户端代码混乱。

五、模式分析

1. 核心本质

工厂方法模式的本质是 “延迟实例化 + 抽象接口 + 子类实现”:

  • 延迟实例化:将产品的创建延迟到具体工厂子类,父类(抽象工厂)不参与具体创建逻辑。
  • 抽象接口:通过抽象产品和抽象工厂定义接口,确保客户端和工厂、产品之间的依赖是抽象而非具体。
  • 子类实现:具体工厂子类负责创建对应的具体产品,每个产品与工厂一一对应,实现 “单一职责”。

2. 与其他模式的区别

模式核心差异典型场景
工厂方法模式抽象工厂定义接口,具体工厂子类创建对应产品,支持扩展(符合开闭)汽车生产、日志系统(多产品类型)
简单工厂模式一个工厂类负责所有产品的创建,新增产品需修改工厂(违反开闭)产品类型少且稳定(如计算器)
抽象工厂模式一个工厂创建多个相关产品(产品族),如 “宝马工厂” 生产宝马车和宝马配件产品族场景(如不同品牌的全套产品)
建造者模式关注产品的创建过程(分步构建复杂对象),如 “汽车建造者” 分步组装零件复杂对象的分步构建(如电脑、文档)

3. 关键设计原则

  • 依赖倒置原则:客户端依赖抽象产品和抽象工厂,不依赖具体类(如Client只依赖Car和CarFactory)。
  • 开闭原则:新增产品时,只需新增具体产品和工厂,无需修改现有代码(如新增Audi和AudiFactory)。
  • 单一职责原则:每个具体工厂只负责创建一种具体产品(如BenzFactory只创建Benz),逻辑清晰。

六、模式扩展

工厂方法模式可根据场景需求扩展出以下变体:

1. 带默认实现的抽象工厂

抽象工厂提供默认工厂方法实现,具体工厂可选择性重写(适用于大部分产品创建逻辑相似的场景):

// 带默认实现的抽象工厂
public abstract class AbstractCarFactory implements CarFactory {
    // 默认实现:创建基础款汽车
    @Override
    public Car createCar() {
        return new BasicCar(); // 基础款汽车
    }

    // 可选:抽象方法,强制子类实现特定产品
    public abstract Car createPremiumCar(); // 高端款汽车
}

// 具体工厂可复用默认实现,或重写
public class BenzFactory extends AbstractCarFactory {
    @Override
    public Car createPremiumCar() {
        return new BenzPremium(); // 奔驰高端款
    }
    // 复用默认的createCar(),返回基础款
}

2. 工厂方法返回缓存对象

工厂方法不每次创建新对象,而是返回缓存的实例(适用于单例产品或池化对象):

public class SingletonCarFactory implements CarFactory {
    private static Car singletonCar; // 缓存单例对象

    @Override
    public synchronized Car createCar() {
        if (singletonCar == null) {
            singletonCar = new Benz(); // 仅首次创建
        }
        return singletonCar; // 返回缓存对象
    }
}

3. 参数化工厂方法

抽象工厂的工厂方法接收参数,具体工厂根据参数返回不同产品(平衡工厂数量和灵活性):

// 参数化抽象工厂
public interface CarFactory {
    // 工厂方法接收参数(如车型)
    Car createCar(String model);
}

// 具体工厂根据参数创建不同产品
public class LuxuryCarFactory implements CarFactory {
    @Override
    public Car createCar(String model) {
        switch (model) {
            case "BenzS": return new BenzS();
            case "BMWM5": return new BMWM5();
            default: throw new IllegalArgumentException("未知车型");
        }
    }
}

4. 静态工厂方法(非模式标准,但广泛使用)

将工厂方法定义为静态方法(无需创建工厂实例),简化调用(如 Java 的Integer.valueOf()):

public class CarStaticFactory {
    // 静态工厂方法:创建奔驰
    public static Car createBenz() {
        return new Benz();
    }

    // 静态工厂方法:创建宝马
    public static Car createBMW() {
        return new BMW();
    }
}

// 客户端调用(无需创建工厂实例)
Car benz = CarStaticFactory.createBenz();

七、模式应用(通用 + Android)

1. 通用领域应用

  • Java 集合框架:Collection.iterator() 是工厂方法,ArrayList、HashSet 等具体集合类(具体工厂)实现该方法,返回对应的 Iterator(具体产品)。

    List<String> list = new ArrayList<>();
    Iterator<String> iterator = list.iterator(); // 工厂方法:ArrayList创建对应的迭代器
    
  • 日志框架(SLF4J):LoggerFactory.getLogger()是工厂方法,不同日志实现(如 Logback、Log4j)对应不同的具体工厂,返回适配的日志对象。

  • Spring 框架:FactoryBean接口是工厂方法模式的应用,getObject()方法由具体实现类(如JdbcTemplateFactoryBean)重写,创建并返回特定 Bean。

  • 数据库访问(JDBC):DriverManager.getConnection()根据连接字符串选择对应的数据库驱动(具体工厂),创建数据库连接(具体产品)。

2. Android 中的应用

Android 框架和常用库大量使用工厂方法模式,核心场景集中在对象创建和框架扩展:

(1)BitmapFactory(核心应用)

  • 角色对应:

    • 抽象产品:Bitmap(图片对象);
    • 具体产品:不同来源的Bitmap(资源文件、文件、字节流等);
    • 抽象工厂:BitmapFactory(包含静态工厂方法);
    • 具体工厂:BitmapFactory的静态方法(decodeResource()、decodeFile()等)作为工厂方法,创建不同来源的Bitmap。
  • 核心逻辑:

    // 客户端通过静态工厂方法创建Bitmap(不同来源)
    Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.drawable.image); // 从资源创建
    Bitmap bitmap2 = BitmapFactory.decodeFile("/sdcard/image.jpg"); // 从文件创建
    // 工厂方法隐藏了不同来源Bitmap的创建细节
    

(2)LayoutInflater(布局加载器)

  • 角色对应:

    • 抽象产品:View(视图对象);
    • 具体产品:TextView、Button等具体视图;
    • 抽象工厂:LayoutInflater(声明inflate()工厂方法);
    • 具体工厂:LayoutInflater的实现类(如PhoneLayoutInflater),重写inflate()创建具体视图。
  • 核心逻辑:

    // 客户端通过工厂方法加载布局(创建View树)
    LayoutInflater inflater = LayoutInflater.from(context);
    View view = inflater.inflate(R.layout.activity_main, null); // 工厂方法创建View
    

(3)ViewModelProvider.Factory(ViewModel 创建)

  • 角色对应:

    • 抽象产品:ViewModel(页面数据模型);
    • 具体产品:自定义UserViewModel、OrderViewModel等;
    • 抽象工厂:ViewModelProvider.Factory(声明create()工厂方法);
    • 具体工厂:ViewModelProvider.NewInstanceFactory(默认工厂)或自定义工厂,创建具体ViewModel。
  • 核心逻辑:

    // 自定义具体工厂:创建UserViewModel
    public class UserViewModelFactory implements ViewModelProvider.Factory {
        @Override
        public <T extends ViewModel> T create(Class<T> modelClass) {
            if (modelClass.isAssignableFrom(UserViewModel.class)) {
                return (T) new UserViewModel(); // 创建具体产品
            }
            throw new IllegalArgumentException("未知ViewModel类型");
        }
    }
    
    // 客户端使用工厂创建ViewModel
    ViewModelProvider provider = new ViewModelProvider(this, new UserViewModelFactory());
    UserViewModel viewModel = provider.get(UserViewModel.class);
    

(4)IntentService(服务创建)

  • 角色对应:
    • 抽象产品:Service(Android 服务);
    • 具体产品:自定义DownloadService、SyncService等;
    • 抽象工厂:IntentService(声明onHandleIntent()抽象方法,类似工厂方法);
    • 具体工厂:自定义IntentService子类,重写onHandleIntent()实现具体服务逻辑。

八、总结

工厂方法模式是 “对象创建” 的核心解决方案,其核心价值在于 “延迟创建 + 灵活扩展 + 解耦封装”:

  1. 核心优势:完美符合 “开闭原则”,新增产品无需修改现有代码;客户端与具体产品解耦,仅依赖抽象;封装了产品创建细节,简化客户端使用。
  2. 适用场景:产品种类可能扩展、需分离创建与使用、需封装创建逻辑的场景(如框架设计、多产品系统)。
  3. 实践建议:
    • 简单场景(产品少且稳定)可用简单工厂,复杂场景(产品多变)用工厂方法;
    • 抽象工厂和抽象产品尽量设计为接口,确保灵活性;
    • 避免过度设计:若产品种类极少且不可能扩展,直接new对象可能比引入工厂更简单;
    • 可结合依赖注入(如 Spring)管理具体工厂,实现工厂的动态切换。

工厂方法模式不仅是一种创建对象的技巧,更是一种 “面向抽象” 的设计思维 —— 通过抽象定义接口,由具体实现完成细节,使系统在变化中保持稳定,是构建可扩展框架和大型系统的重要工具。

最近更新:: 2025/8/28 23:18
Contributors: 罗凯文, luokaiwen