工厂模式(Factory Pattern)
设计意图
工厂模式的主要目的是将对象的创建与使用分离,通过一个工厂类来负责创建实例。这样,当我们需要创建新的对象时,不需要直接使用构造函数,而是通过工厂类来生成对象。这种模式在需要生成复杂对象或者未来需要扩展时非常有用。
适用场景
- 类不知道它所需要的对象的确切类型时。例如,一个应用程序可能需要在运行时根据配置文件的输入决定创建哪个类的实例。
- 系统不依赖于产品类实例如何被创建、组合和表示的细节时。
- 一个类希望将它所创建的对象的职责委托给一个专门的子类时。
结构
- 产品接口(Product Interface):定义产品的共同行为。
- 具体产品(Concrete Product):实现产品接口,提供不同的产品实现。
- 工厂接口(Factory Interface):定义创建产品的方法。
- 具体工厂(Concrete Factory):实现工厂接口,具体生产产品。
优点
- 封装性:将具体产品的创建封装在工厂类中,用户无需知道产品的具体类名。
- 扩展性:可以通过扩展工厂类,增加新的产品创建逻辑,而不修改现有代码。
缺点
- 如果需要支持更多的产品类型,可能需要创建大量的工厂类,增加系统的复杂性。
Java实现案例
// 产品接口
interface Product {
void use();
}
// 具体产品A
class ProductA implements Product {
@Override
public void use() {
System.out.println("Using Product A");
}
}
// 具体产品B
class ProductB implements Product {
@Override
public void use() {
System.out.println("Using Product B");
}
}
// 抽象工厂接口
interface ProductFactory {
Product createProduct();
}
// 具体工厂A
class ProductAFactory implements ProductFactory {
@Override
public Product createProduct() {
return new ProductA();
}
}
// 具体工厂B
class ProductBFactory implements ProductFactory {
@Override
public Product createProduct() {
return new ProductB();
}
}
// 客户端
public class FactoryPatternExample {
public static void main(String[] args) {
// 使用工厂A创建产品A
ProductFactory factoryA = new ProductAFactory();
Product productA = factoryA.createProduct();
productA.use();
// 使用工厂B创建产品B
ProductFactory factoryB = new ProductBFactory();
Product productB = factoryB.createProduct();
productB.use();
}
}
策略模式(Strategy Pattern)
设计意图
策略模式的主要目的是定义一系列算法,并将它们封装在独立的类中,使得它们可以互换使用。策略模式通过将算法的选择和使用分离开来,使得可以在运行时根据不同的需求选择合适的算法。
适用场景
- 需要动态选择算法时。例如,某个功能需要支持多种不同的算法,并且这些算法可以在运行时动态切换。
- 多种算法只是在具体行为上有所不同。策略模式可以避免通过条件语句选择不同算法的繁琐过程。
- 需要避免使用多个条件判断来选择算法时。这不仅简化了代码结构,还提高了系统的可扩展性。
结构
- 策略接口(Strategy Interface):定义所有支持的算法或行为。
- 具体策略(Concrete Strategy):实现策略接口,提供具体的算法实现。
- 上下文类(Context):使用策略接口来调用具体的算法,且可以动态更改策略。
优点
- 算法可以自由切换:通过设置不同的策略实现类,可以在运行时自由切换不同的算法。
- 避免多重条件判断:策略模式通过将算法封装到独立的类中,避免了使用复杂的条件语句来选择算法。
- 扩展性强:可以通过添加新的策略类来增加新的算法,实现开闭原则。
缺点
- 客户端必须知道所有的策略类,并自行决定使用哪一个策略类,这对客户端来说增加了使用难度。
- 如果策略过多,增加了系统中类的数量,复杂性增加。
Java实现案例
// 策略接口
interface Strategy {
int execute(int a, int b);
}
// 具体策略:加法
class AddStrategy implements Strategy {
@Override
public int execute(int a, int b) {
return a + b;
}
}
// 具体策略:减法
class SubtractStrategy implements Strategy {
@Override
public int execute(int a, int b) {
return a - b;
}
}
// 具体策略:乘法
class MultiplyStrategy implements Strategy {
@Override
public int execute(int a, int b) {
return a * b;
}
}
// 上下文类
class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}
// 客户端
public class StrategyPatternExample {
public static void main(String[] args) {
// 使用加法策略
Context context = new Context(new AddStrategy());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
// 动态切换到减法策略
context.setStrategy(new SubtractStrategy());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
// 动态切换到乘法策略
context.setStrategy(new MultiplyStrategy());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
对比总结
设计模式 | 工厂模式 | 策略模式 |
---|---|---|
目的 | 通过工厂类创建对象,将对象创建过程与使用分离 | 定义一系列算法,允许在运行时选择并使用不同的算法 |
主要角色 | 产品接口、具体产品、工厂接口、具体工厂 | 策略接口、具体策略、上下文类 |
使用场景 | 需要生成复杂对象或创建过程需要灵活时 | 需要动态选择算法或避免使用多重条件判断时 |
优点 | 提高封装性,增强代码的扩展性和可维护性 | 算法可以互换使用,扩展性强,避免多重条件判断 |
缺点 | 可能导致过多的工厂类增加复杂性 | 增加了客户端的使用复杂度,策略类过多会增加系统复杂性 |
总之,工厂模式更多用于对象的创建,而策略模式则用于行为或算法的选择。两者在设计思想上都有助于使系统更加灵活和可扩展,但它们的应用场景和方式有所不同。