定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。——《设计模式:可复用面向对象软件的基础》
角色
策略模式有三个角色,分别是:
抽象策略角色(Strategy):是所有具体策略类共同的接口
具体策略角色(ConcreteStrategy):是实现了抽象策略接口的具体实现类
上下文角色(Context):拥有Strategy的引用,提供具体策略。
代码示例
抽象策略角色(TaoLu.java):
// 套路
public interface TaoLu {
void taoLu();
}
具体策略角色(RichTaoLu.java、TalentedTaoLu.java):
// 有钱人套路
public class RichTaoLu implements TaoLu {
@Override
public void taoLu() {
System.out.println("为她买金");
System.out.println("为她买银");
System.out.println("为她买包包");
}
}
// 有才套路
public class TalentedTaoLu implements TaoLu {
@Override
public void taoLu() {
System.out.println("为她写诗");
System.out.println("为她弹琴写词");
System.out.println("为她摘星星月亮");
}
}
上下文角色(KuiHuaBaoDian.java):
// 葵花宝典
public class KuiHuaBaoDian {
// 持有套路(Strategy)的引用
private TaoLu taoLu;
public KuiHuaBaoDian(TaoLu taoLu) {
this.taoLu = taoLu;
}
public void toGetTheGirlIntoBed(String girl) {
taoLu.taoLu();
System.out.println("你得到了" + girl + "的心");
}
}
测试类(ZhaNan.java):
// 渣男
public class ZhaNan {
public static void main(String[] args) {
KuiHuaBaoDian kuiHuaBaoDian;
String girl1 = "拜金女";
// 选择策略
TaoLu taoLu1 = new RichTaoLu();
// 创建上下文
kuiHuaBaoDian = new KuiHuaBaoDian(taoLu1);
kuiHuaBaoDian.toGetTheGirlIntoBed(girl1);
String girl2 = "爱才女";
// 选择策略
TaoLu taoLu2 = new TalentedTaoLu();
// 创建上下文
kuiHuaBaoDian = new KuiHuaBaoDian(taoLu2);
kuiHuaBaoDian.toGetTheGirlIntoBed(girl2);
}
}
测试结果如下:
策略模式使用场景有:
在一个系统里面有许多类,它们之间的区别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多行为中选择一种行为;(追女孩子可以选择有钱或者有才)
一个系统需要动态地在几种算法中选择一种;
避免使用难以维护的多重条件选择语句;
希望在具体策略类中封装算法和与相关的数据结构(有钱可以买金卖银,有才可以写诗写词)
优点
符合开闭原则,增加策略只需要增加具体策略实现类即可
避免(if-else if-else)多重选择语句
封装了具体算法,客户端不需要知道具体算法
缺点
客户端需要知道使用哪种具体策略(对不同的女性采取不同的策略)
策略模式会产生很多策略类,多后期学习维护增加一定难度
总结
策略模式封装算法,提供给上下文选择使用,客户端无需关心算法具体逻辑,无需关系关系算法更替,但是使用前需要知道具体策略类。