工厂模式是一种在软件设计中广泛应用的设计模式,它解决的问题是当系统需要创建一系列相关的对象,而这些对象的类型在运行时才确定,或者我们希望为库或框架提供扩展其内部组件的灵活性时。工厂方法模式的核心思想是将对象的创建过程从客户端代码中分离出来,通过定义一个抽象工厂接口来控制具体对象的创建。
1. 模式定义:
工厂方法模式定义了一个创建对象的接口,通常称为`Product`(产品),这个接口并不关心其实现细节。具体的产品类,如`ProductA`和`ProductA1`,实现这个接口,并各自提供特定的功能。客户端通过调用工厂类中的`createProduct()`方法,根据不同的参数(如字符串类型)动态地创建相应的产品对象。
例如,在上面的示例中,`SimpleFactory`就是一个简单的工厂类,它根据传入的字符串类型`type`返回不同产品的实例:
```java
public static Product createProduct(String type) {
if (type.equals("0")) {
return new ProductA();
} else if (type.equals("1")) {
return new ProductA1();
} else {
return null;
}
}
```
2. 优点:
- 解耦:工厂类与具体产品类解耦,允许客户端在不知道具体产品类的情况下创建对象,增强了系统的可维护性和灵活性。
- 符合单一职责原则:每个类只负责一件事,工厂类专注于对象的创建,产品类专注于自己的业务逻辑。
- 符合开闭原则:如果增加新的产品类型,只需要扩展工厂类或添加新的具体产品类,而不影响已有的代码,体现了“开-闭”原则,即软件对扩展开放,对修改关闭。
3. 应用场景:
- 当需要隐藏对象的创建细节时,避免客户端代码直接创建复杂对象。
- 当产品系列的扩展不明确,或者需要在运行时动态决定创建哪种产品时。
- 当想要为库或框架提供一个易于扩展的API,使得第三方开发者可以方便地添加新的产品类型。
4. 实现示例:
在`Application`抽象类中,定义了一个抽象的`createProduct()`方法,这是工厂方法的核心,具体的实现由子类`ConcreteProductA`和`ConcreteProductA1`完成:
```java
abstract class Application {
abstract Product createProduct();
// ...
}
class ConcreteProductA extends Application {
@Override
Product createProduct() {
return new ProductA();
}
}
class ConcreteProductA1 extends Application {
@Override
Product createProduct() {
return new ProductA1();
}
}
```
通过这种方式,客户端无需关心具体的产品是如何被创建的,只需与`Application`类交互即可,这样提高了代码的灵活性和模块化程度。