定义
策略模式定义了一系列的算法,将每个算法封装在独立的类中,并使他们可以相互替换。这样,算法的选择或者变更就可以独立于使用算法的客户端进行,从而使系统更灵活、提高可扩展性和可维护性。
策略模式通常包括以下角色:
- 上下文(Context):客户端代码和策略模式之间的接口。它持有一个策略对象的引用,并在运行时将调用委托给策略对象。
- 策略(Strategy):策略是定义一系列算法的接口,通常以接口或者抽象类的形式实现。具体的策略类实现了这个接口
- 具体策略(Concrete Strategy):具体策略类是策略的具体实现。每个具体策略类实现了策略接口或者继承了抽象策略类,并实现了自己的算法逻辑
使用策略模式,客户端可以在运行时选择不同的策略,并且可以轻松地添加新的策略或修改现有的策略(或算法),而不需要修改客户端代码。这使得策略模式成为一种非常有用的设计模式,特别是在需要灵活处理算法变化的情况下。
场景
举个栗子,传闻梅西如天神下凡,回首过往梅开二度、帽子戏法、五子登科的好戏仍然历历在目。
以下是梅西常用的一些技术:
蝎子摆尾
大力抽射
圆月弯刀
油炸丸子
抽象策略
/**
* @deprecated 给出策略的接口
*/
public interface IStrategy {
void warMethod();
}
具体策略
/**
* @description 蝎子摆尾
*/
public class ScorpionTailPendulumStrategy implements IStrategy{
@Override
public void footballSkills() {
System.out.println("【蝎子摆尾】");
}
}
/**
* @Description 大力抽射
*/
public class VolleyStrategy implements IStrategy{
@Override
public void footballSkills() {
System.out.println("【大力抽射】");
}
}
/**
* @Description 圆月弯刀
*/
public class TulwarStrategy implements IStrategy{
@Override
public void footballSkills() {
System.out.println("【圆月弯刀】");
}
}
/**
* @Description 油炸丸子
*/
public class BallStrategy implements IStrategy{
@Override
public void footballSkills() {
System.out.println("【油炸丸子】");
}
}
封装类
梅西将的所有神技贡献给FIFA,我们在FIFA的世界,任何球员可以都可以使用这些神技。球员持有策略的引用,他可以使用梅西所有的技能,也不会影响其他功能,经过球员自身的加工,可以将这些技能表现出不同的效果。
public class General {
private IStrategy mStrategy;
public General(IStrategy strategy) {
this.mStrategy = strategy;
}
public void useAbility() {
System.out.println("准备使用技能");
mStrategy.footballSkills();
}
}
实战结果
我们一口气来new4个技能给这位幸运的球员:
General general;
general = new General(new ScorpionTailPendulumStrategy());
general.useAbility();
System.out.println("\n------------------------------------\n");
general = new General(new VolleyStrategy());
general.useAbility();
System.out.println("\n------------------------------------\n");
general = new General(new TulwarStrategy());
general.useAbility();
System.out.println("\n------------------------------------\n");
general = new General(new BallStrategy());
general.useAbility();
System.out.println("\n------------------------------------\n");
输出:
准备使用技能
【蝎子摆尾】
------------------------------------
准备使用技能
【大力抽射】
------------------------------------
准备使用技能
【圆月弯刀】
------------------------------------
准备使用技能
【油炸丸子】
------------------------------------
总结
策略模式优点
- 灵活性: 各种策略切换自如,使得算法可以独立于客户端而变化。客户端可以根据需要在运行时选择不同的算法,而不需要修改原有的代码。
- 可扩展性:新的策略可以很方便的添加,也不会影响到已有的代码结构。维护也比较方便,可扩展性和可维护性较强。
- 复用性: 策略模式将算法封装在独立的策略类中,这些策略类可以被不同的客户端重复使用,提高了代码的复用性。
- 降低耦合度: 策略模式将策略或者算法的实现与客户端的调用解耦,使得系统各部分之间的依赖关系更加松散,降低了模块之间的耦合度。
策略模式缺点
- 类数量增加: 使用策略模式会增加系统中类的数量,因为每个具体策略都需要一个独立的类来实现,这可能会增加代码的复杂度。
- 客户端必须知道所有策略: 客户端需要了解所有的策略,并且在运行时选择合适的策略,这可能增加了客户端的复杂度。因为你必须了解各种策略【球技】的用法
- 增加了对象间的调用关系: 策略模式将算法封装成独立的对象,增加了对象间的调用关系,可能会增加系统的运行开销。