文章目录
- 策略模式
- 定义
- 英文原话
- 直译
- 角色
- 类图
- 策略接口`Strategy`:
- 具体策略类
- 上下文类Context
- 测试类
- 策略模式的应用
- 策略模式的优点
- 策略模式的缺点
- 策略模式的使用场景
策略模式
策略模式(Strategy Pattern)
Strategy策略也称作Policy政策。
想象一下我们正在玩一个角色扮演游戏。在游戏中,我们的角色有多种技能可以选择,比如“火球术”、“冰霜箭”和“治愈术”。每种技能都有不同的效果和用途。现在,游戏设计师希望让我们能够随时切换这些技能以适应不同的战斗场景。
策略模式就是这样一种设计思想。它允许我们定义不同的“技能”(即策略),然后在游戏中根据需要随时切换使用哪种技能。这样,我们就可以更加灵活地应对各种战斗情况了。
同样地,在计费系统或商城促销活动中,策略模式也允许我们根据不同的条件选择不同的计费方式或优惠策略,使得系统更加灵活和可配置。
定义
英文原话
Define a family of algorithms, encapsulate each one, and make them interchangeable.
直译
定义一系列的算法,把它们一个个封装起来,并且是他们可相互替换(必然实现了相同的接口,不然无法相互替换,该接口就是策略接口)
本模式使得算法可独立于使用它的客户而变化。
角色
- 策略接口(Strategy):定义所有支持的算法的公共接口。
- 具体策略(ConcreteStrategy):实现策略接口的类,具体策略类实现了算法的具体逻辑。
- 上下文(Context):使用策略接口的类,也称为“上下文”或“客户端”。上下文类内部持有一个策略对象的引用,并且负责在需要的时候调用策略对象的算法。
类图
在策略模式中,我们可以将这三个角色用Java类来具体实现。以下是一个简化的策略模式示例,其中包含了Strategy
(策略接口)、ConcreteStrategy
(具体策略类)和Context
(上下文类)的实现。
策略接口Strategy
:
// Strategy.java
public interface Strategy {
void executeStrategy();
}
具体策略类
这里假设有两个具体策略类ConcreteStrategyA
和ConcreteStrategyB
:
// ConcreteStrategyA.java
public class ConcreteStrategyA implements Strategy {
@Override
public void executeStrategy() {
System.out.println("执行策略A");
// 策略A的具体实现
}
}
// ConcreteStrategyB.java
public class ConcreteStrategyB implements Strategy {
@Override
public void executeStrategy() {
System.out.println("执行策略B");
// 策略B的具体实现
}
}
上下文类Context
它持有一个策略对象的引用,并提供了设置策略和执行策略的方法:
// Context.java
public class Context {
private Strategy strategy;
// 构造函数
public Context(Strategy strategy) {
this.strategy = strategy;
}
// 设置策略
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
// 执行策略
public void executeStrategy() {
strategy.executeStrategy();
}
}
测试类
现在,我们可以编写一个示例来展示如何使用策略模式:
// StrategyPatternDemo.java
public class StrategyPatternDemo {
public static void main(String[] args) {
// 创建策略对象
Strategy strategyA = new ConcreteStrategyA();
Strategy strategyB = new ConcreteStrategyB();
// 创建上下文对象并设置策略
Context context = new Context(strategyA);
context.executeStrategy(); // 输出:执行策略A
// 修改策略
context.setStrategy(strategyB);
context.executeStrategy(); // 输出:执行策略B
}
}
/* Output:
执行策略A
执行策略B
*///~
在这个示例中,
Context
类可以根据需要改变其内部持有的Strategy
对象,从而改变其行为。这是策略模式的核心思想:将算法的使用与算法的实现分离开来,使得算法可以独立于使用它的客户端变化。
策略模式的应用
策略模式是一种行为型设计模式,它定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。在软件系统中,策略模式使得算法可以独立于使用它的客户端变化。
策略模式的优点
- 算法自由切换:由于策略类实现了同一个接口,因此它们之间可以自由切换,这使得系统更加灵活和可维护。
- 易于扩展:当需要增加新的算法时,只需要实现该接口即可,符合开闭原则。
- 避免使用多重条件语句:使用策略模式可以避免在代码中出现大量的if-else语句,使代码更加清晰、简洁和易于维护。
- 提高算法的保密性和安全性:客户端只需要知道它使用了哪些算法,而不需要知道这些算法的具体实现细节,这有助于保护算法的安全性和保密性。
策略模式的缺点
- 客户端必须知道所有的策略类:客户端需要了解并决定使用哪一个策略类,这可能会增加客户端的复杂性。
- 可能造成策略类过多:当系统中存在大量的策略时,可能会导致策略类过多,增加了系统的复杂性。
策略模式的使用场景
- 计费系统:对于不同用户类型和消费金额采用不同的计费方式,可以使用策略模式来定义不同的计费策略。
- 游戏开发中的角色技能系统:不同角色拥有不同的技能,可以根据角色的选择使用不同的技能策略进行攻击或防御。
- 商城促销活动:根据不同的促销活动采取不同的优惠方式,如打折、满减等,策略模式可以方便地管理和切换这些优惠策略。
- 需要动态选择算法的场景:当系统中需要根据不同的条件选择不同的算法进行计算时,策略模式可以提供一个灵活的解决方案。