工厂方法模式(Factory Method Pattern) 是设计模式中的一种创建型模式,它定义了一个用于创建对象的接口,但让子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类中进行。工厂方法模式是一种非常实用的模式,特别是在处理大量具有共同接口的类时,系统要基于多个扩展类的类型来决定实例化哪一个类。

一、工厂方法模式概述

1. 模式动机

在软件系统中,经常面临着“某个对象”的创建工作,由于需求的变化,这个对象的创建逻辑可能经常变化,但它却拥有比较稳定的接口。如何应对这种变化?如何设计出满足需求的类结构?工厂方法模式提供了一种解决方案。

2. 模式定义

工厂方法模式(Factory Method Pattern)又称为多态性工厂模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

3. 模式结构

工厂方法模式包含以下四个角色:
Product(抽象产品):定义产品的接口,是工厂方法模式所创建对象的超类型,也就是产品对象的共同父类或接口。
ConcreteProduct(具体产品):实现了抽象产品接口的具体产品对象,被具体的工厂类所创建。
Creator(抽象工厂):声明了工厂方法(Factory Method),用于返回一个产品。工厂方法是一个返回抽象产品类型的方法,其子类可以覆盖该方法以返回不同的具体产品类型。
ConcreteCreator(具体工厂):实现了抽象工厂中的工厂方法,通过客户调用以返回具体产品类的实例。

4. 优缺点

优点:

用户只需要知道具体工厂类的名称就可得到所要的产品,无须知道产品的具体创建过程。
灵活性增强,对于新产品的创建,只需继承一个具体工厂类或者添加一个具体工厂类,就可以实现扩展。

缺点:

类的个数容易过多,增加系统的复杂度,因为每增加一个产品,就需要增加一个具体产品类和一个具体工厂类。
系统扩展繁琐,如果要增加一个新的产品,除了增加新的产品类外,还需要增加新的具体工厂类,并在客户端中增加新的工厂类的实例。

二、工厂方法模式实现

1. 示例场景

假设我们有一个日志系统,需要支持多种日志记录方式(如文件日志、数据库日志、控制台日志等)。每种日志记录方式都有自己特定的实现,但对外都提供一个统一的接口。我们可以使用工厂方法模式来设计这个日志系统。

2. 角色定义

Log(抽象产品):定义日志记录的接口。
FileLog(具体产品):实现文件日志记录。
DatabaseLog(具体产品):实现数据库日志记录。
LogFactory(抽象工厂):声明创建日志记录的工厂方法。
FileLogFactory(具体工厂):实现创建文件日志记录的工厂。
DatabaseLogFactory(具体工厂):实现创建数据库日志记录的工厂。

3. Java代码实现

// 抽象产品:日志记录接口  
interface Log {  
    void writeLog(String message);  
}  
  
// 具体产品:文件日志记录  
class FileLog implements Log {  
    @Override  
    public void writeLog(String message) {  
        System.out.println("FileLog: " + message);  
    }  
}  
  
// 具体产品:数据库日志记录  
class DatabaseLog implements Log {  
    @Override  
    public void writeLog(String message) {  
        System.out.println("DatabaseLog: " + message);  
    }  
}  
  
// 抽象工厂:日志工厂接口  
interface LogFactory {  
    Log createLog();  
}  
  
// 具体工厂:文件日志工厂  
class FileLogFactory implements LogFactory {  
    @Override  
    public Log createLog() {  
        return new FileLog();  
    }  
}  
  
// 具体工厂:数据库日志工厂  
class DatabaseLogFactory implements LogFactory {  
    @Override  
    public Log createLog() {  
        return new DatabaseLog();  
    }  
}  
  
// 客户端代码  
public class Client {  
    public static void main(String[] args) {  
        // 使用文件日志  
        LogFactory fileLogFactory = new FileLogFactory();  
        Log fileLog = fileLogFactory.createLog();  
        fileLog.writeLog("This is a file log.");  
  
        // 使用数据库日志  
        LogFactory databaseLogFactory = new DatabaseLogFactory();  
        Log databaseLog = databaseLogFactory.createLog();  
        databaseLog.writeLog("This is a database log.");  
    }  
}

三、工厂方法模式的应用场景

当一个类不知道它所必须创建的对象的类的时候。
当一个类希望由它的子类来指定它所创建的对象的时候。
当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

四、工厂方法模式的扩展

1. 工厂方法模式的变体

简单工厂模式:简单工厂模式不属于GOF的23种设计模式之一,但它是一种非常常用的实例化对象的模式。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例,类似于一个工厂类负责创建所有实例。
抽象工厂模式:抽象工厂模式提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。

2. 工厂方法模式与其他模式的结合

与单例模式结合:在某些情况下,工厂类本身就是一个单例,负责创建和管理所有的产品对象。
与策略模式结合:工厂方法模式可以与策略模式结合使用,将不同的算法封装成不同的产品类,由工厂类根据需求创建相应的算法对象。

五、总结

工厂方法模式是一种非常实用的设计模式,它通过定义一个用于创建对象的接口,让子类决定实例化哪一个类。这种方式将对象的创建逻辑封装在工厂类中,使得客户端代码与具体的产品类解耦,提高了系统的灵活性和可扩展性。同时,工厂方法模式也具有一定的局限性,如类的个数容易过多、系统扩展繁琐等。因此,在设计系统时,需要根据实际情况选择合适的设计模式。

09-15 14:49