深入解析Java中的工厂模式:对象创建的优雅之道一、工厂模式概述工厂模式(Factory Pattern)是创建型设计模式中最常用的一种,它提供了一种创建对象的最佳方式。工厂模式的核心思想是将对象的创建与使用分离,客户端无需知道具体对象的创建细节,只需通过工厂获取所需对象。
1.1 模式定义工厂模式定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
1.2 模式分类工厂模式主要分为三种类型:
简单工厂模式(Simple Factory)工厂方法模式(Factory Method)抽象工厂模式(Abstract Factory)1.3 模式优点解耦对象创建与使用提高代码的可维护性和可扩展性符合开闭原则(对扩展开放,对修改关闭)降低代码重复率便于统一管理和控制对象创建过程二、简单工厂模式2.1 模式结构简单工厂模式包含以下角色:
工厂类(Factory):负责创建具体产品对象抽象产品(Product):定义产品的公共接口具体产品(ConcreteProduct):实现抽象产品接口的具体类2.2 代码实现代码语言:javascript复制// 抽象产品
public interface Product {
void use();
}
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品B");
}
}
// 简单工厂
public class SimpleFactory {
public static Product createProduct(String type) {
switch (type) {
case "A":
return new ConcreteProductA();
case "B":
return new ConcreteProductB();
default:
throw new IllegalArgumentException("未知产品类型");
}
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Product productA = SimpleFactory.createProduct("A");
productA.use();
Product productB = SimpleFactory.createProduct("B");
productB.use();
}
}2.3 优缺点分析优点:
客户端与具体产品解耦客户端无需知道具体产品类名实现简单缺点:
工厂类职责过重,违反单一职责原则添加新产品需要修改工厂类,违反开闭原则静态工厂方法无法形成继承等级结构三、工厂方法模式3.1 模式结构工厂方法模式包含以下角色:
抽象工厂(Factory):声明工厂方法具体工厂(ConcreteFactory):实现工厂方法,创建具体产品抽象产品(Product):定义产品接口具体产品(ConcreteProduct):实现产品接口3.2 代码实现代码语言:javascript复制// 抽象产品
public interface Product {
void use();
}
// 具体产品A
public class ConcreteProductA implements Product {
@Override
public void use() {
System.out.println("使用产品A");
}
}
// 具体产品B
public class ConcreteProductB implements Product {
@Override
public void use() {
System.out.println("使用产品B");
}
}
// 抽象工厂
public interface Factory {
Product createProduct();
}
// 具体工厂A
public class ConcreteFactoryA implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductA();
}
}
// 具体工厂B
public class ConcreteFactoryB implements Factory {
@Override
public Product createProduct() {
return new ConcreteProductB();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Factory factoryA = new ConcreteFactoryA();
Product productA = factoryA.createProduct();
productA.use();
Factory factoryB = new ConcreteFactoryB();
Product productB = factoryB.createProduct();
productB.use();
}
}3.3 优缺点分析优点:
完全符合开闭原则符合单一职责原则形成平行的工厂等级结构客户端只需知道抽象工厂和抽象产品缺点:
每增加一个产品就要增加一个具体工厂类增加了系统的抽象性和理解难度四、抽象工厂模式4.1 模式结构抽象工厂模式包含以下角色:
抽象工厂(AbstractFactory):声明创建一系列产品的方法具体工厂(ConcreteFactory):实现创建具体产品的方法抽象产品(AbstractProduct):为每种产品声明接口具体产品(ConcreteProduct):实现抽象产品接口4.2 代码实现代码语言:javascript复制// 抽象产品A
public interface ProductA {
void useA();
}
// 具体产品A1
public class ConcreteProductA1 implements ProductA {
@Override
public void useA() {
System.out.println("使用产品A1");
}
}
// 具体产品A2
public class ConcreteProductA2 implements ProductA {
@Override
public void useA() {
System.out.println("使用产品A2");
}
}
// 抽象产品B
public interface ProductB {
void useB();
}
// 具体产品B1
public class ConcreteProductB1 implements ProductB {
@Override
public void useB() {
System.out.println("使用产品B1");
}
}
// 具体产品B2
public class ConcreteProductB2 implements ProductB {
@Override
public void useB() {
System.out.println("使用产品B2");
}
}
// 抽象工厂
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// 具体工厂1
public class ConcreteFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA1();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂2
public class ConcreteFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new ConcreteProductA2();
}
@Override
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
// 使用第一个工厂族
AbstractFactory factory1 = new ConcreteFactory1();
ProductA productA1 = factory1.createProductA();
ProductB productB1 = factory1.createProductB();
productA1.useA();
productB1.useB();
// 使用第二个工厂族
AbstractFactory factory2 = new ConcreteFactory2();
ProductA productA2 = factory2.createProductA();
ProductB productB2 = factory2.createProductB();
productA2.useA();
productB2.useB();
}
}4.3 优缺点分析优点:
保证客户端始终只使用同一个产品族中的对象产品族内的约束对客户端透明符合开闭原则(增加新的产品族容易)缺点:
难以支持新种类的产品(需要修改抽象工厂接口)系统抽象性增加,理解难度加大五、工厂模式的应用场景5.1 简单工厂模式适用场景工厂类负责创建的对象比较少客户端只需要传入参数,不关心对象创建过程需要集中管理对象的创建逻辑5.2 工厂方法模式适用场景一个类不知道它所需要的对象的类一个类希望由其子类来指定创建的对象需要灵活、可扩展的框架5.3 抽象工厂模式适用场景系统需要多个产品族,但每次只使用其中某一族产品系统需要提供一个产品类的库,所有产品以同样的接口出现产品族中的对象被设计成一起工作六、工厂模式在Java中的典型应用6.1 JDK中的工厂模式Collection.iterator():工厂方法模式Calendar.getInstance():简单工厂模式NumberFormat.getInstance():工厂方法模式6.2 Spring框架中的工厂模式BeanFactory:工厂方法模式ApplicationContext:抽象工厂模式FactoryBean:特殊的工厂模式实现七、工厂模式的最佳实践合理选择工厂模式类型:
简单工厂:对象创建逻辑简单工厂方法:需要灵活扩展抽象工厂:处理产品族考虑使用静态工厂方法:
代码语言:javascript复制public class Product {
private Product() {}
public static Product create() {
return new Product();
}
}结合单例模式:
代码语言:javascript复制public class SingletonFactory {
private static final Product INSTANCE = new Product();
public static Product getInstance() {
return INSTANCE;
}
}使用依赖注入框架:
Spring框架的IoC容器本质上是一个超级工厂命名规范:
工厂方法通常命名为createXxx()或getXxx()静态工厂方法通常命名为valueOf()、of()、getInstance()等八、工厂模式与其他模式的比较8.1 工厂方法 vs 抽象工厂工厂方法:创建单一产品,通过子类决定实例化哪个类抽象工厂:创建产品族,通过子类决定实例化哪个产品族8.2 工厂模式 vs 建造者模式工厂模式:关注创建什么产品建造者模式:关注如何创建复杂对象8.3 工厂模式 vs 原型模式工厂模式:通过工厂创建新对象原型模式:通过克隆已有对象创建新对象九、实战案例:日志记录器工厂9.1 需求分析我们需要一个日志系统,可以支持多种日志记录方式(文件、数据库、控制台),并且可以方便地扩展新的日志记录方式。
9.2 使用工厂方法模式实现代码语言:javascript复制// 日志记录器接口
public interface Logger {
void log(String message);
}
// 文件日志记录器
public class FileLogger implements Logger {
@Override
public void log(String message) {
System.out.println("文件日志: " + message);
}
}
// 数据库日志记录器
public class DatabaseLogger implements Logger {
@Override
public void log(String message) {
System.out.println("数据库日志: " + message);
}
}
// 控制台日志记录器
public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("控制台日志: " + message);
}
}
// 日志记录器工厂接口
public interface LoggerFactory {
Logger createLogger();
}
// 文件日志记录器工厂
public class FileLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
return new FileLogger();
}
}
// 数据库日志记录器工厂
public class DatabaseLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
return new DatabaseLogger();
}
}
// 控制台日志记录器工厂
public class ConsoleLoggerFactory implements LoggerFactory {
@Override
public Logger createLogger() {
return new ConsoleLogger();
}
}
// 客户端
public class Client {
public static void main(String[] args) {
LoggerFactory factory = new FileLoggerFactory();
Logger logger = factory.createLogger();
logger.log("这是一个测试消息");
// 可以轻松切换日志方式
factory = new DatabaseLoggerFactory();
logger = factory.createLogger();
logger.log("这是一个测试消息");
}
}9.3 使用抽象工厂模式扩展如果需要同时支持不同级别的日志记录(如Info、Error),可以使用抽象工厂模式:
代码语言:javascript复制// 抽象产品:Info日志
public interface InfoLogger {
void info(String message);
}
// 抽象产品:Error日志
public interface ErrorLogger {
void error(String message);
}
// 抽象工厂
public interface LoggerAbstractFactory {
InfoLogger createInfoLogger();
ErrorLogger createErrorLogger();
}
// 文件日志具体工厂
public class FileLoggerFactory implements LoggerAbstractFactory {
@Override
public InfoLogger createInfoLogger() {
return new FileInfoLogger();
}
@Override
public ErrorLogger createErrorLogger() {
return new FileErrorLogger();
}
}
// 数据库日志具体工厂
public class DatabaseLoggerFactory implements LoggerAbstractFactory {
@Override
public InfoLogger createInfoLogger() {
return new DatabaseInfoLogger();
}
@Override
public ErrorLogger createErrorLogger() {
return new DatabaseErrorLogger();
}
}
// 客户端使用
public class Client {
public static void main(String[] args) {
LoggerAbstractFactory factory = new FileLoggerFactory();
InfoLogger infoLogger = factory.createInfoLogger();
ErrorLogger errorLogger = factory.createErrorLogger();
infoLogger.info("普通信息");
errorLogger.error("错误信息");
// 切换日志方式
factory = new DatabaseLoggerFactory();
infoLogger = factory.createInfoLogger();
errorLogger = factory.createErrorLogger();
infoLogger.info("普通信息");
errorLogger.error("错误信息");
}
}十、总结工厂模式是面向对象设计中最重要的模式之一,它通过将对象的创建与使用分离,提高了系统的灵活性和可维护性。三种工厂模式各有适用场景:
简单工厂模式:适用于对象创建逻辑简单的场景工厂方法模式:适用于需要灵活扩展的场景抽象工厂模式:适用于产品族的创建在实际开发中,我们应该根据具体需求选择合适的工厂模式。同时,现代Java开发中,我们可以结合Spring等IoC容器,更优雅地实现工厂模式的功能。
理解并掌握工厂模式,能够帮助我们设计出更加灵活、可扩展的系统架构,是每一位Java开发者必备的技能。