1. 工厂模式概述
工厂模式是一种创建型设计模式 ,它提供了一种封装对象实例化过程的方法。在软件开发中,我们经常需要创建对象,但直接使用new操作符会导致代码耦合度增高,维护成本加大。工厂模式通过定义一个创建对象的接口,但让子类决定实例化哪个类,从而解决了这个问题。
工厂模式的核心思想是将对象的创建与使用分离,客户端不需要知道具体产品的类名,只需要知道对应的工厂即可。这种解耦使得代码更加灵活,易于扩展和维护。
工厂模式主要分为三种类型:简单工厂模式 、工厂方法模式 和抽象工厂模式。这三种模式从上到下逐步抽象,应用场景也逐渐复杂。
2. 简单工厂模式
简单工厂模式是最基础的工厂模式,它通过一个工厂类负责创建多种类型的对象。该模式中,工厂类根据传入的参数不同返回不同的产品实例。
2.1 结构与实现
简单工厂模式包含三个核心角色:
-
工厂类:负责创建所有类型的产品实例
-
抽象产品接口:定义产品的公共方法
-
具体产品类:实现抽象产品接口的具体类
以下是一个汽车生产的简单工厂模式示例:
// 抽象产品接口
public interface ICar {
public void name();
}
// 具体产品类
public class Xiaopeng implements ICar {
@Override
public void name() {
System.out.println("小鹏汽车创建完成!");
}
}
public class Weilai implements ICar {
@Override
public void name() {
System.out.println("蔚来汽车创建完成!");
}
}
// 简单工厂类
public class CarFactory {
public static ICar createCar(String car) {
if (car.equals("小鹏")) {
return new Xiaopeng();
} else if (car.equals("蔚来")) {
return new Weilai();
} else {
return null;
}
}
}
// 客户端使用
public class Consumer {
public static void main(String[] args) {
ICar car0 = CarFactory.createCar("小鹏");
ICar car1 = CarFactory.createCar("蔚来");
car0.name();
car1.name();
}
}
2.2 优缺点分析
优点:
-
代码结构简单,易于理解和实现
-
客户端与具体产品类解耦
缺点:
-
违反开闭原则:当需要添加新产品时,必须修改工厂类的代码
-
工厂类职责过重,产品过多时会导致工厂类复杂臃肿
简单工厂模式适用于产品种类较少且不太可能频繁变化的场景。
3. 工厂方法模式
工厂方法模式是针对简单工厂模式缺点的改进,它定义了一个创建对象的抽象方法,由子类决定要实例化的类。这样,系统的扩展性得到了大大提高。
3.1 结构与实现
工厂方法模式包含四个核心角色:
-
抽象工厂:声明工厂方法,返回产品对象
-
具体工厂:实现工厂方法,创建具体产品
-
抽象产品:定义产品接口
-
具体产品:实现抽象产品接口
以下是工厂方法模式的实现示例:
// 抽象产品接口
public interface ICar {
public void name();
}
// 具体产品类
public class Xiaopeng implements ICar {
@Override
public void name() {
System.out.println("小鹏汽车创建完成!");
}
}
// 抽象工厂类
public abstract class CarFactory {
public abstract ICar createCar();
}
// 具体工厂类
public class XiaopengFactory extends CarFactory {
@Override
public ICar createCar() {
return new Xiaopeng();
}
}
// 客户端使用
public class Consumer {
public static void main(String[] args) {
CarFactory factory = new XiaopengFactory();
ICar car = factory.createCar();
car.name();
}
}
3.2 优缺点分析
优点:
-
符合开闭原则:增加新产品时只需添加新工厂类,无需修改已有代码
-
符合单一职责原则:每个工厂只负责创建一种产品
缺点:
-
类的数量增多,增加系统复杂性
-
增加了系统的抽象性和理解难度
工厂方法模式适用于产品结构复杂且可能需要频繁扩展的场景。
4. 抽象工厂模式
抽象工厂模式是工厂方法模式的进一步推广,它提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
4.1 结构与实现
抽象工厂模式包含以下角色:
-
抽象工厂:声明创建一系列产品的方法
-
具体工厂:实现抽象工厂接口,创建具体产品族
-
抽象产品:定义产品接口
-
具体产品:实现抽象产品接口
以下是一个电子产品生产的抽象工厂模式示例:
// 抽象产品接口
public interface IPhone {
void start();
void shutdown();
}
public interface IRouter {
void openWifi();
void setting();
}
// 具体产品类
public class HuaweiPhone implements IPhone {
@Override
public void start() { System.out.println("华为手机开机"); }
@Override
public void shutdown() { System.out.println("华为手机关机"); }
}
public class HuaweiRouter implements IRouter {
@Override
public void openWifi() { System.out.println("华为路由器打开WiFi"); }
@Override
public void setting() { System.out.println("华为路由器设置"); }
}
// 抽象工厂
public interface IProductFactory {
IPhone createPhone();
IRouter createRouter();
}
// 具体工厂
public class HuaweiFactory implements IProductFactory {
@Override
public IPhone createPhone() {
return new HuaweiPhone();
}
@Override
public IRouter createRouter() {
return new HuaweiRouter();
}
}
// 客户端使用
public class Consumer {
public static void main(String[] args) {
HuaweiFactory factory = new HuaweiFactory();
IPhone phone = factory.createPhone();
IRouter router = factory.createRouter();
phone.start();
router.openWifi();
}
}
4.2 优缺点分析
优点:
-
保证产品族内产品的兼容性
-
符合开闭原则(增加产品族时)
-
符合单一职责原则
缺点:
-
产品族扩展困难(需要修改所有工厂类)
-
增加了系统的抽象性和理解难度
抽象工厂模式适用于需要创建相关或依赖对象族的系统。
5. 三种工厂模式对比
为了更清晰地理解三种工厂模式的差异,以下是它们的对比表格:
| 特性 | 简单工厂模式 | 工厂方法模式 | 抽象工厂模式 |
|---|---|---|---|
| 复杂度 | 低 | 中 | 高 |
| 开闭原则支持 | 违反 | 支持 | 支持(产品族) |
| 产品数量 | 可创建多种产品 | 一个工厂创建一种产品 | 一个工厂创建一族产品 |
| 适用场景 | 产品种类少且稳定 | 产品种类多且可能扩展 | 产品族多且需要兼容性 |
| 类数量 | 少 | 多 | 最多 |
表:三种工厂模式特性对比
从结构复杂度来看,简单工厂模式最简单,抽象工厂模式最复杂。从扩展性来看,工厂方法模式和抽象工厂模式都支持开闭原则,但抽象工厂模式在产品族扩展上较为困难。
6. 工厂模式的应用场景
工厂模式在以下场景中特别有用:
-
对象创建过程复杂:当对象的创建需要一系列复杂步骤或依赖多个辅助对象时,使用工厂模式可以封装这些复杂性。
-
需要减少耦合:当希望将对象创建与使用解耦时,工厂模式提供了一个优雅的解决方案。
-
系统需要支持多种产品变体:当系统需要支持不同系列的相关产品时,抽象工厂模式特别有用。
-
动态选择实现:当需要在运行时根据条件选择不同的产品实现时,工厂模式提供了灵活性。
-
框架设计:在框架设计中,工厂模式允许框架定义接口,而将具体实现留给用户。
7. 工厂模式在框架中的应用
工厂模式在主流框架中有着广泛的应用:
7.1 Spring框架
Spring框架使用工厂模式管理对象的创建和生命周期。其中,BeanFactory和ApplicationContext是工厂模式的典型实现。
// Spring中的BeanFactory是工厂模式的体现
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
MyService service = context.getBean(MyService.class);
7.2 Hibernate框架
Hibernate中的SessionFactory是工厂模式的实现,它负责创建Session对象,而Session是数据库交互的主要接口。
7.3 Java集合框架
Java集合框架中的Collections类提供了多种静态工厂方法,如unmodifiableList()、synchronizedList()等,这些方法返回特定功能的集合对象。
8. 最佳实践与注意事项
在使用工厂模式时,需要注意以下几点:
-
避免过度设计:如果对象创建逻辑简单,直接使用构造函数可能更合适,不要为了使用模式而使用模式。
-
结合依赖注入:在现代框架中,工厂模式常与依赖注入结合使用,进一步提高灵活性和可测试性。
-
考虑使用静态工厂方法:在简单场景下,静态工厂方法比单独创建工厂类更简洁。
-
注意性能开销:工厂模式会引入额外的间接层,在性能敏感的场景需要权衡。
-
合理选择工厂类型:根据具体需求选择合适的工厂模式变体,不要盲目选择最复杂的方案。
结论
工厂模式是面向对象设计中极其重要的创建型模式,它通过将对象的创建与使用分离,提高了代码的灵活性、可维护性和可扩展性。三种工厂模式各有适用场景:简单工厂模式适用于简单场景,工厂方法模式适用于需要扩展性的场景,而抽象工厂模式适用于产品族创建的复杂场景。
在实际开发中,我们需要根据具体需求选择合适的工厂模式变体,避免过度设计,同时也要注意工厂模式可能带来的复杂性增加。当正确应用时,工厂模式能够显著提高软件的质量和可维护性。
工厂模式体现了依赖倒置原则,是面向对象设计原则的具体实现。通过深入理解和合理应用工厂模式,开发者可以编写出更加灵活、可扩展的软件系统。