策略模式(Strategy Pattern)
1.定义
策略模式(Strategy Pattern)是一种行为设计模式,它使你能在运行时改变对象的行为。在策略模式中,一个类的行为或其算法可以在其运行时更改。这种类型的设计模式属于行为模式。
策略模式的主要优点是:
- 算法可以自由切换:策略模式使得算法可以独立于使用它的客户端变化。
- 简化单元测试:策略模式使得每一个算法都有自己的类,这样我们可以通过自己的接口单独测试每一个算法。
- 开闭原则:策略模式对扩展开放,对修改封闭。
策略模式的缺点是:
- 客户端必须知道不同策略的存在:这使得客户端可以自行决定使用哪一个策略,这可能导致客户端代码变得复杂。
- 增加系统复杂性:由于策略模式将算法的使用与算法的实现分离,系统中会增加许多策略类。当策略过多时,可能会导致系统变得难以维护。
策略模式通常适用于以下场景:
- 许多相关的类仅仅是行为有异。
- 需要使用一个算法的不同变体。
- 算法使用客户不应该知道的数据。
- 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的策略类中替换这些条件语句。
2.实现
策略模式的实现主要包括以下步骤:
- 定义策略接口:首先,需要创建一个策略接口,该接口定义了一个或多个方法,这些方法会在具体的策略类中被实现。这些方法代表了某种行为或算法。
- 创建策略类:然后,创建多个实现了策略接口的类,每个类代表一种具体的策略或算法。这些类应该实现接口中定义的方法,并在方法内部提供具体的算法实现。
- 创建上下文类:上下文类(或称为策略使用者)是一个持有策略接口的引用,并调用策略接口中定义的方法的类。上下文类不需要知道它所使用的具体策略类的类型,它只需要知道策略接口。
- 在客户端代码中使用策略模式:客户端代码创建上下文类的一个实例,并通过构造函数或其他方法将所需策略的一个实例传递给上下文类。然后,客户端代码可以调用上下文类的方法来执行策略。
下面使用策略模式实现日志记录级别的改变:
1.UML类图:
2.代码实现
要使用策略模式实现日志记录级别的改变,首先需要定义一个日志策略接口,然后为每种日志级别创建相应的策略实现类。接着,创建一个上下文类来管理这些策略,并在客户端代码中根据需要切换日志级别。
以下是一个简单的Java示例:
- 定义日志策略接口:
public interface LoggingStrategy {
void log(String message);
}
- 创建具体的日志策略类:
public class DebugLoggingStrategy implements LoggingStrategy {
@Override
public void log(String message) {
System.out.println("[DEBUG] " + message);
}
}
public class InfoLoggingStrategy implements LoggingStrategy {
@Override
public void log(String message) {
System.out.println("[INFO] " + message);
}
}
public class WarningLoggingStrategy implements LoggingStrategy {
@Override
public void log(String message) {
System.out.println("[WARNING] " + message);
}
}
// 还可以添加其他日志级别,比如ERROR、FATAL等
- 创建上下文类:
public class LoggingContext {
private LoggingStrategy loggingStrategy;
public LoggingContext(LoggingStrategy loggingStrategy) {
this.loggingStrategy = loggingStrategy;
}
public void setLoggingStrategy(LoggingStrategy loggingStrategy) {
this.loggingStrategy = loggingStrategy;
}
public void log(String message) {
loggingStrategy.log(message);
}
}
- 在客户端代码中使用策略模式:
public class Client {
public static void main(String[] args) {
LoggingContext loggingContext = new LoggingContext(new DebugLoggingStrategy()); // 初始设置为DEBUG级别
loggingContext.log("This is a debug message."); // 输出: [DEBUG] This is a debug message.
// 改变日志级别为INFO
loggingContext.setLoggingStrategy(new InfoLoggingStrategy());
loggingContext.log("This is an info message."); // 输出: [INFO] This is an info message.
// 可以根据需要继续切换日志级别
// loggingContext.setLoggingStrategy(new WarningLoggingStrategy());
// loggingContext.log("This is a warning message.");
}
}
在这个例子中,LoggingContext 类管理了日志策略,客户端代码可以根据需要设置不同的日志策略。通过调用 setLoggingStrategy 方法,可以很容易地改变当前的日志级别。每次调用 log 方法时,LoggingContext 都会委托给当前设置的日志策略对象来执行实际的日志记录操作。
这种设计使得日志级别的改变变得非常灵活,客户端代码不需要关心具体的日志实现细节,只需要通过更改策略对象即可实现日志级别的动态切换。