策略模式

策略模式定义:

定义了策略族,可以理解成各种算法,然后把每个策略(算法)封装起来,让它们之间可以互换。此模式让算法独立于使用他的客户。

设计模式之禅上用了下文的故事,讲述策略模式:

在三国演义中,我最佩服诸葛亮的地方不是因为他未出茅庐而有三分天下的预测,也不是他在赤壁鏖战中借东风的法术,更不是他七擒七纵孟获的策略。那是什么呢?是他“气死周瑜,骂死王朗”的气度和风范!想想看,你用“气”能把一个轮胎打爆,用“气”枪能够把路灯打碎,但是要把跟你没有任何血缘关系的人气死有多困难呀,更何况是周瑜这种智慧型人物!

在诸葛亮气周瑜的过程中,有一件事情:那就是周瑜赔了夫人又折兵这件事情。事情经过是这样的:孙权看刘备有雄起之意,杀是不能杀了,那会惹天下人唾弃,就想个招儿挫他一下,那有什么办法呢?孙权有个妹妹——孙尚香,准备招刘备做女婿,然后孙权想办法把刘备软禁起来,孙权的想法还是很单纯的嘛,就是不让你刘备回西川,然后我东吴想干啥就干啥,夺荆州,吞西川也不是不可能的。东吴的想法是好的,无奈中间多了智谋无敌的诸葛亮,他早就预测了东吴有此招数,于是在刘备去东吴招亲之前,特授以伴郎赵云三个锦囊,说是按天机拆开解决棘手问题。

这三个妙计分别是:找乔国老帮忙(也就是走后门了),求吴国太放行(诉苦)以及孙夫人断后,对这三个妙计不熟悉的读者可以去温习一下《三国演义》,这里就不多说了。想想看,这三个计谋有什么相似之处,他们都是告诉赵云要怎么执行,也就是说这三个计谋都有一个方法是执行,具体执行什么内容,每个计谋当然不同了,分析到这里,我们是不是就有这样一个设计思路:三个妙计应该实现的是同一个接口?聪明!

类图如下:

image.png

代码:

策略接口

public interface IStrategy {
//每个锦囊妙计都是一个可执行的算法
public void operate();
}

策略一

public class BackDoor implements IStrategy {
public void operate() {
System.out.println("找乔国老帮忙,让吴国太给孙权施加压力");
}

策略二

public class GivenGreenLight implements IStrategy {
public void operate() {
System.out.println("求吴国太开绿灯,放行!");
}

策略三

public class BlockEnemy implements IStrategy {
public void operate() {
  System.out.println("孙夫人断后,挡住追兵");
}

通过组合的方式把策略包裹,为使用人提供方便使用的类。在使用人使用策略时,方便动态设定策略,并通过调用策略接口的统一方法触发策略,这同时暴露了策略模式的弱点,他要求使用者清楚每一个策略的运用时机。在上面的故事中是有漏洞的,赵云并不知道何时应该使用哪个策略,是诸葛亮提前设定好的。

public class Context {
//构造函数,你要使用哪个妙计
private IStrategy straegy;
public Context(IStrategy strategy){
      this.straegy = strategy;
}
//使用计谋了,看我出招了
public void operate(){
        this.straegy.operate();
}
}

使用者

public class ZhaoYun {
//赵云出场了,他根据诸葛亮给他的交代,依次拆开妙计
public static void main(String[] args) {
Context context;
//刚刚到吴国的时候拆第一个
System.out.println("---刚刚到吴国的时候拆第一个---");
context = new Context(new BackDoor()); //拿到妙计
context.operate(); //拆开执行
System.out.println("\n\n\n\n\n\n\n\n");
//刘备乐不思蜀了,拆第二个了
System.out.println("---刘备乐不思蜀了,拆第二个了---");
context = new Context(new GivenGreenLight());
context.operate(); //执行了第二个锦囊
System.out.println("\n\n\n\n\n\n\n\n");
//孙权的小兵追来了,咋办?拆第三个
System.out.println("---孙权的小兵追来了,咋办?拆第三个---");
context = new Context(new BlockEnemy());
context.operate(); //孙夫人退兵
System.out.println("\n\n\n\n\n\n\n\n");
}
}

整个故事的类图

image.png

策略模式优点

  1. 可以自由切换算法
  2. 避免了多条件的判断
  3. 扩展性好可以定义新的算法提供给使用者

策略模式缺点

  1. 算法类数量增多,每个算法都是一个类
  2. 算法要对外安全暴露,因为使用者来决定是用哪个算法,必然要了解算法内部做了什么。
可以使用其他模式来修正这个缺陷,如工厂方法模式、代理模式或享元模式。(书上写的,还不了解实际结合)

策略模式相对简单。运用感悟以后再更新吧。

你可能感兴趣的:(策略模式)