java设计模式:工厂方法
工厂方法模式是一种广泛使用的创建型设计模式,它的核心思想是将对象的实例化过程推迟到子类中,从而使代码更加灵活和符合开闭原则。
下面用一个清晰的对比表格来展示工厂方法模式的核心角色及其职责,帮助你快速把握其结构。
角色名称
职责描述
抽象产品
定义产品的通用接口。
具体产品
实现抽象产品接口,是工厂方法要创建的具体对象。
抽象工厂
声明工厂方法,该方法返回一个抽象产品类型的对象。
具体工厂
实现抽象工厂的工厂方法,负责实例化特定的具体产品对象
。
💻 代码示例:日志记录器
假设我们需要一个日志系统,可以灵活地选择将日志记录到文件或数据库中。
首先,定义抽象产品 Logger接口和两个具体产品 FileLogger、DatabaseLogger:
// 抽象产品:日志记录器接口
public interface Logger {void log(String message);
}// 具体产品:文件日志记录器
public class FileLogger implements Logger {@Overridepublic void log(String message) {System.out.println("记录到文件:" + message);}
}// 具体产品:数据库日志记录器
public class DatabaseLogger implements Logger {@Overridepublic void log(String message) {System.out.println("记录到数据库:" + message);}
}
接着,定义抽象工厂 LoggerFactory和两个具体工厂 FileLoggerFactory、DatabaseLoggerFactory:
// 抽象工厂
public interface LoggerFactory {Logger createLogger(); // 工厂方法
}// 具体工厂:创建文件日志记录器
public class FileLoggerFactory implements LoggerFactory {@Overridepublic Logger createLogger() {// 这里可能包含复杂的初始化逻辑return new FileLogger();}
}// 具体工厂:创建数据库日志记录器
public class DatabaseLoggerFactory implements LoggerFactory {@Overridepublic Logger createLogger() {// 例如,需要先获取数据库连接等return new DatabaseLogger();}
}
最后,在客户端代码中,通过选择不同的具体工厂来获得不同的产品:
public class Main {public static void main(String[] args) {// 根据需要配置或切换工厂LoggerFactory factory = new FileLoggerFactory();// LoggerFactory factory = new DatabaseLoggerFactory(); // 切换时只需修改这一行Logger logger = factory.createLogger();logger.log("这是一条日志信息");}
}
✅ 模式优势
工厂方法模式的主要优点包括:
良好的扩展性:当需要增加新的产品(如网络日志记录器 NetworkLogger)时,只需创建新的具体产品类和具体工厂类,无需修改任何现有代码,完全符合开闭原则。
客户端与具体实现解耦:客户端代码只依赖于抽象接口(Logger和 LoggerFactory),不关心具体产品的创建细节,降低了模块间的耦合度。
将对象的创建与使用分离:使代码结构更清晰,创建逻辑集中在工厂中,便于统一管理和维护。
⚠️ 潜在缺点
该模式的一个主要缺点是会增加系统中类的数量。每个具体产品都对应一个具体工厂类,当产品种类非常多时,会使得系统结构变得复杂。
🌍 典型应用场景
工厂方法模式特别适用于以下情况:
客户端无法预知具体对象的类型,只知道创建对象的接口。
希望将产品的创建过程与使用过程分离开,以便于管理和扩展。
系统需要在未来容易地扩展新的产品种类。
🔄 与简单工厂模式的区别
简单工厂模式通过一个工厂类,根据传入的参数不同来创建不同的产品。虽然结构简单,但在新增产品时需要修改这个工厂类的逻辑,违反了开闭原则。工厂方法模式则通过抽象的工厂接口和多个具体的工厂类完美地解决了这个问题,是简单工厂模式的进一步深化。