在面向对象的设计中,工厂模式是一种创建型设计模式,它通过定义一个用于创建对象的接口,允许子类决定将哪一个类实例化。工厂方法使得类的实例化过程延迟到子类中进行,从而实现了对开放-封闭原则的遵循
工厂模式的核心思想
- 定义:工厂方法模式定义了一个用于创建对象的接口,但由子类来决定实例化哪一个类。工厂方法将对象的创建延迟到子类中进行。
- 关键点:核心在于将实例化的职责交给子类,这样可以减少客户端代码对具体类的依赖性。
工厂模式的使用场景
- 扩展性需求:当我们希望在系统中能够灵活地加入新的产品,而不需要修改现有代码时,工厂模式是一种很好的选择。
- 遵循开放-封闭原则:通过引入工厂方法,系统对扩展开放,但对修改关闭,从而更容易维护。
代码示例讲解
以下是一个工厂模式的简单实现,展示了如何通过工厂方法来创建不同的产品对象。
1. 产品接口
产品接口定义了所有产品必须实现的操作方法,所有具体产品都需要实现这个接口。
public interface Product {
void operation();
}
2. 具体产品(Concrete Products)
这是两个具体的产品类,分别实现了 Product
接口,定义了各自的操作行为。
public class ConcreteProductA implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductA operation");
}
}
public class ConcreteProductB implements Product {
@Override
public void operation() {
System.out.println("ConcreteProductB operation");
}
}
3. 工厂接口
工厂接口定义了一个抽象的工厂方法,返回一个 Product
对象,但具体创建什么样的产品由子类实现。
public abstract class Creator {
public abstract Product factoryMethod();
}
4. 具体工厂(Concrete Factories)
每个具体工厂实现了工厂方法,分别创建不同的产品。
public class ConcreteCreatorA extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductA();
}
}
public class ConcreteCreatorB extends Creator {
@Override
public Product factoryMethod() {
return new ConcreteProductB();
}
}
5. 客户端代码
客户端通过调用工厂方法获取产品,而不需要直接创建产品对象。这样,客户端代码无需依赖具体产品的类,只依赖抽象产品接口,从而实现了解耦。
public class Client {
public static void main(String[] args) {
Creator creator = new ConcreteCreatorA(); // 可以灵活切换工厂类
Product product = creator.factoryMethod(); // 通过工厂方法创建产品
product.operation(); // 调用产品的操作方法
}
}
运行结果
执行上述代码时,输出结果如下:
ConcreteProductA operation
通过切换 ConcreteCreatorA
到 ConcreteCreatorB
,可以轻松实现不同产品的创建,而无需修改客户端代码。
工厂模式的优点
- 遵循开放-封闭原则:工厂模式让代码能够轻松扩展新的产品,而无需修改现有系统。
- 解耦创建和使用:客户端不需要关心产品的具体实现,只需要使用工厂方法来获取对象,从而降低了耦合度。
- 更好的维护性:随着系统的扩展和变化,可以更容易地维护和管理代码。
工厂模式的缺点
- 增加复杂性:每新增一种产品,就需要新增一个具体工厂类,可能会增加系统的复杂性。
- 违背单一职责原则:工厂类不仅负责创建对象,还负责定义产品的种类,可能会违背单一职责原则。
总结
工厂模式在面对复杂的对象创建需求时,尤其适用于产品种类较多,且产品结构较为复杂的场景。它通过将对象的创建逻辑分离到专门的工厂类中,减少了客户端与具体产品的耦合,提升了系统的扩展性和维护性。