1. 概述
工厂模式(Factory Pattern)和策略模式(Strategy Pattern)都是软件设计中常用的行为型设计模式,它们在解决软件设计中的问题时,各有其特点和适用场景。
2. 工厂模式
工厂模式的核心目的是用于创建对象,而不将对象的创建逻辑暴露给客户端。客户端不需要直接实例化对象,而是通过一个共同的接口来获取对象。工厂模式通常用于以下场景:
- 当创建对象的逻辑比较复杂时。
- 当创建对象需要大量的参数,或者这些参数具有不同的数据类型时。
- 当对象的创建依赖于系统环境或者配置信息时。
- 当需要对创建的对象进行管理时。
工厂模式主要分为两种:简单工厂模式和工厂方法模式。简单工厂模式集中了所有对象的创建逻辑,而工厂方法模式将创建对象的具体逻辑推迟到子类中实现。
3. 策略模式
策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户。
策略模式通常用于以下场景:
- 系统中有很多类,它们之间的区别仅在于它们的行为。
- 需要使用组合而非继承的方式来实现算法的多样性。
- 需要动态地选择算法的行为。
策略模式通常涉及以下几个角色:策略接口、具体策略类、上下文环境和客户端。客户端可以根据需要选择具体策略类来实现策略接口。
4. 区别
- 核心思想不同:
工厂模式的核心是创建对象,而策略模式的核心是定义一系列可互相替换的算法。
工厂模式关注的是对象的创建过程,策略模式关注的是如何使用这些对象。 - 应用场景不同:
工厂模式通常用于对象的创建和管理。
策略模式用于定义算法族,让它们之间可以互相替换。 - 目的和结构:
工厂模式目的是为了降低对象创建的复杂性,结构上通常包含一个工厂类和多个产品类。
策略模式目的是为了定义策略的多样性,结构上包含策略接口、具体策略类、上下文环境和客户端。 - 使用时机:
工厂模式在对象创建时被调用。
策略模式在对象使用时被调用,以决定具体使用哪个策略。 - 灵活性和可扩展性:
工厂模式可以很容易地引入新的产品类型,但可能会导致工厂类的复杂性增加。
策略模式可以很容易地引入新的策略,而且不会影响到已有的策略实现。
总的来说,工厂模式和策略模式都是为了提高代码的灵活性和可维护性,但它们适用的场景和解决的问题不同。工厂模式侧重于创建对象,而策略模式侧重于定义行为的多样性。
5. 代码实现
5.1 工厂模式
假设我们有一个简单的例子,需要根据不同的参数来创建不同类型的 Car 对象。
// Car 接口
public interface Car {
void drive();
}
// 具体 Car 类
public class Sedan implements Car {
@Override
public void drive() {
System.out.println("Sedan is driving");
}
}
public class Truck implements Car {
@Override
public void drive() {
System.out.println("Truck is driving");
}
}
// 工厂类
public class CarFactory {
public static Car createCar(String type) {
if ("sedan".equalsIgnoreCase(type)) {
return new Sedan();
} else if ("truck".equalsIgnoreCase(type)) {
return new Truck();
}
throw new IllegalArgumentException("Unknown car type: " + type);
}
}
// 客户端代码
public class FactoryPatternDemo {
public static void main(String[] args) {
Car car = CarFactory.createCar("sedan");
car.drive(); // 输出 "Sedan is driving"
}
}
5.2 策略模式
假设我们有一个需要进行计算的例子,根据不同的策略来计算数值。
// 策略接口
public interface Strategy {
double doOperation(double num1, double num2);
}
// 具体策略类
public class Addition implements Strategy {
@Override
public double doOperation(double num1, double num2) {
return num1 + num2;
}
}
public class Subtraction implements Strategy {
@Override
public double doOperation(double num1, double num2) {
return num1 - num2;
}
}
public class Multiplication implements Strategy {
@Override
public double doOperation(double num1, double num2) {
return num1 * num2;
}
}
// 上下文环境
public class Context {
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public double executeStrategy(double num1, double num2) {
return strategy.doOperation(num1, num2);
}
}
// 客户端代码
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new Addition());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context.setStrategy(new Subtraction());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context.setStrategy(new Multiplication());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
区别说明
-
工厂模式 关注于对象的创建,客户端代码不直接创建对象,而是通过工厂类来创建。在工厂模式中,客户端只需要知道传入工厂类的参数,而不需要关心对象的创建细节。
-
策略模式 关注于定义一系列可互相替换的算法,客户端代码在运行时可以根据需要选择具体的算法。策略模式将算法的选择与算法的实现分离开来,使得算法可以独立于使用它们的客户变化。
在代码实现上,工厂模式通常包含一个或多个工厂类和多个产品类,而策略模式则包含一个策略接口、多个具体策略类、一个上下文环境和客户端。工厂模式在编译时确定具体产品的类型,而策略模式在运行时根据需要切换策略。
5.3 简单工厂模式 + 策略模式
- 首先,我们定义一个交通工具接口和它的实现类,这些类将作为策略模式中的算法。
- 接下来,我们实现简单工厂模式,用于创建不同的交通工具对象。
- 创建一个上下文环境,它将使用简单工厂模式来获取交通工具对象,并使用策略模式来选择不同的移动方式。
- 编写客户端代码来使用这个上下文环境。
// 交通工具接口
public interface Vehicle {
void move();
}
// 具体交通工具类
public class Car implements Vehicle {
@Override
public void move() {
System.out.println("Car is moving");
}
}
public class Train implements Vehicle {
@Override
public void move() {
System.out.println("Train is moving");
}
}
// 工厂接口
public interface VehicleFactory {
Vehicle create();
}
// 具体工厂类
public class CarFactory implements VehicleFactory {
@Override
public Vehicle create() {
return new Car();
}
}
public class TrainFactory implements VehicleFactory {
@Override
public Vehicle create() {
return new Train();
}
}
// 工厂管理类
public class VehicleFactoryManager {
private final Map<String, VehicleFactory> factories = new HashMap<>();
public void registerFactory(String type, VehicleFactory factory) {
factories.put(type, factory);
}
public Vehicle createVehicle(String type) {
VehicleFactory factory = factories.get(type);
if (factory == null) {
throw new IllegalArgumentException("Unknown vehicle type: " + type);
}
return factory.create();
}
}
// 上下文环境
public class Context {
private Vehicle vehicle;
public Context(Vehicle vehicle) {
this.vehicle = vehicle;
}
public void setVehicle(Vehicle vehicle) {
this.vehicle = vehicle;
}
public void executeMove() {
vehicle.move();
}
}
// 客户端代码
public class SimpleFactoryStrategyDemo {
public static void main(String[] args) {
// 创建工厂管理实例
VehicleFactoryManager manager = new VehicleFactoryManager();
// 注册工厂
manager.registerFactory("car", new CarFactory());
manager.registerFactory("train", new TrainFactory());
// 使用工厂管理实例创建交通工具
Vehicle car = manager.createVehicle("car");
Vehicle train = manager.createVehicle("train");
// 将交通工具设置到上下文环境中
Context carContext = new Context(car);
Context trainContext = new Context(train);
// 执行移动操作
carContext.executeMove(); // 输出 "Car is moving"
trainContext.executeMove(); // 输出 "Train is moving"
}
}