1. 策略模式概述
在策略模式中,一个类的行为或其算法可以在运行时更改。
比如说,在执行一个方法时,我们需要动态地改变其实现逻辑,这里就可以用到策略模式。
(1) 适用情况
某一个方法根据不同的情况需要用到多种执行逻辑时,不要总想着if else,可以优先考虑使用策略模式。
(2) 优点
自由切换执行逻辑,避免代码中出现多重条件判断,用起来感觉很舒服。
(3) 缺点
要实现所有的策略类并向外暴露。
2. 策略模式实例
读过《三国演义》的同学应该还记得这么一段故事:
刘备丧偶之后,周瑜心生一计:用孙权的妹妹向刘备招亲,把他骗到江东,然后软禁起来,逼他拿荆州来换自己。
刘备认为这是个骗局,想要拒绝,诸葛亮却让他安心前去,并给了同去接亲的赵云三个锦囊,让他到时候依次打开。
果然,刘备在江东遇到了各种问题和危险,但由于赵云打开了诸葛亮的锦囊,依计而行,最终都化险为夷。
最后,刘备安然无恙的返回了荆州,而周瑜却“赔了夫人又折兵”。
这就是锦囊妙计的故事,而三个锦囊中的三条计谋,就可以看做是三条策略。
(1) 声明锦囊妙计接口
public interface SilkBagStrategy {
// 锦囊妙计
void todo();
}
(2) 实现锦囊中具体的计谋
public class FirstStrategy implements SilkBagStrategy{
@Override
public void todo() {
System.out.println("敲锣打鼓,大肆宣扬接亲的消息。\n");
}
}
public class SecondStrategy implements SilkBagStrategy{
@Override
public void todo() {
System.out.println("向刘备报告:曹操兴兵来报赤壁之仇,请主公速回荆州!\n");
}
}
public class ThirdStrategy implements SilkBagStrategy {
@Override
public void todo() {
System.out.println("让刘备向夫人哭诉周瑜施美人计诱杀自己的阴谋。\n");
}
}
(3) 实现怀揣锦囊的赵云类
public class ZhaoYun {
private Map<String, SilkBagStrategy> silkBagStrategy = new HashMap<>();
public ZhaoYun() {
silkBagStrategy.put("初到江东", new FirstStrategy());
silkBagStrategy.put("纸醉金迷", new SecondStrategy());
silkBagStrategy.put("情势危急", new ThirdStrategy());
}
/**
* 该怎么办?
*/
public void howTodo(String solution) {
SilkBagStrategy silkBagStrategy = this.silkBagStrategy.get(solution);
silkBagStrategy.todo();
}
}
(4) 依计而行
public class StrategyDemo {
public static void main(String[] args) {
ZhaoYun zhaoYun = new ZhaoYun();
System.out.println("刘备一行到了江东,但却无人迎接。");
zhaoYun.howTodo("初到江东");
System.out.println("刘备纸醉金迷,不肯回荆州。");
zhaoYun.howTodo("纸醉金迷");
System.out.println("周瑜出兵追赶,情势危急。");
zhaoYun.howTodo("情势危急");
}
}
运行结果:
3. 一些思考
赵云每次调用的都是howTodo方法,只不过根据不同的情况传参不同,就可以得到不同的锦囊妙计。
如果需要增加更多的计谋,则只需要创建新的策略类,然后让赵云带上就可以了。
还有一种常用的模式 —— 委派/委托模式,它并不属于23种经典模式中,我个人认为,它其实只是策略模式的变体而已。下面用另一个例子来说明。
在《三国演义》中,还有另一个脍炙人口的故事:
赤壁之战之后,曹操仓皇逃窜,并在途中三次大笑,分别引来了赵云、张飞和关羽,原来他们早就被诸葛亮安排好了。最后关羽念及旧日恩情,义释曹操,放了他一条生路。
这就是“华容道”的故事,而关张赵三位将军,就可以看作是诸葛亮使用了委派模式。
(1) 声明一个将军接口
public interface General {
// 将军出兵
void attack();
}
(2) 实现具体的将军类
public class ZhaoYun implements General {
@Override
public void attack() {
System.out.println("曹操第一次笑时,赵云杀出。");
}
}
public class ZhangFei implements General {
@Override
public void attack() {
System.out.println("曹操第二次笑时,张飞杀出。");
}
}
public class GuanYu implements General {
@Override
public void attack() {
System.out.println("曹操第三次笑时,关羽杀出。");
}
}
(3) 实现刘备类,也就是委派者
public class LiuBei {
ZhuGeLiang zhuGeLiang = new ZhuGeLiang();
/**
* 刘备下令进攻,实际上是委派给诸葛亮去安排
*/
public void command() {
zhuGeLiang.scheme();
}
}
(4) 实现诸葛亮类,也就是被委派者
public class ZhuGeLiang {
private Map<String, General> generals = new HashMap<>();
public ZhuGeLiang() {
generals.put("第一次笑", new ZhaoYun());
generals.put("第二次笑", new ZhangFei());
generals.put("第三次笑", new GuanYu());
}
/**
* 委派给传
*/
public void scheme() {
System.out.println("\n曹操第一次笑...");
generals.get("第一次笑").attack();
System.out.println("\n曹操第二次笑...");
generals.get("第二次笑").attack();
System.out.println("\n曹操第三次笑...");
generals.get("第三次笑").attack();
}
}
(5) 委派者刘备下令出兵
public class DelegatingDemo {
public static void main(String[] args) {
LiuBei liuBei = new LiuBei();
// 刘备下令出兵
liuBei.command();
}
}
运行结果:
在“华容道”中,刘备只下令出兵,但是具体怎么发动攻击他不管,而是委派给了诸葛亮,由诸葛亮给关张赵三位将军下令。 而诸葛亮下令的时候,就用到了策略模式。
参考引用
策略模式:www.runoob.com/design-patt…
委派模式:www.cnblogs.com/ZekiChen/p/…