深圳幻海软件技术有限公司 欢迎您!

Strategy Pattern 教你秒变“神枪手”

2023-02-28

作者案:本文介绍的是StrategyPattern(策略模式)。干货满满,希望阅读后你能有所收获~目的做一件事情有不同的实现方式,可以将变化的部分和不变的部分剥离开,去除大量的if/else,提供高扩展性。例子代码比如我们想要带妹吃鸡,就要成为一个神枪手。在各种枪战游戏中,有各种不同的枪,我们要根据

作者案:本文介绍的是 Strategy Pattern (策略模式)。干货满满,希望阅读后你能有所收获~

目的

做一件事情有不同的实现方式,可以将变化的部分和不变的部分剥离开,去除大量的 if/else,提供高扩展性。

例子代码

比如我们想要带妹吃鸡,就要成为一个神枪手。在各种枪战游戏中,有各种不同的枪,我们要根据射程的不同选择不同的枪进行射击。

如果枪的子弹数量都不富裕,我们要用最少的子弹,最合适的方法达到最强伤害,最终大吉大利。

当我们距离对手:

  • 1米以内,使用平底锅(想我当时三级头三级甲,手持 AKM,满血满状态,三级包里药包无数,到了决赛圈被平底锅堵在墙角打死啦😢 );
  • 100 米左右,使用冲锋枪;
  • 超过 1000 米,使用狙击枪(对于我这样的小菜鸡,基本流程是开一枪没打中,暴露位置,被别人一狙打死...囧)。
/**
 * 面条式代码判断最强武器
 */
public class NoodlesKillProcessor {    


    /**
     * 根据距离判断最好的武器击杀对手
     * @param distance
     */
    @BadSmell
    public static void killByDistance(int distance) {        


        if(distance < 0) {            
            throw new RuntimeException("距离咋还能是负数呢?");
        }        


        if(distance >= 0 && distance < 1) {
            System.out.println("发现敌人");
            System.out.println("两步快速走过去");
            System.out.println("掏出平底锅呼他");         
            return;
        }        


        if(distance >= 1 && distance < 10) {
            System.out.println("发现敌人");
            System.out.println("快速走过去");
            System.out.println("掏出手枪打他");           
            return;
        }        


        if(distance >= 10 && distance < 100) {
            System.out.println("发现敌人");
            System.out.println("身体站直, 心态稳住");
            System.out.println("掏出冲锋枪打他");         
            return;
        }        


        if(distance >= 100 && distance < 1000) {
            System.out.println("发现敌人");
            System.out.println("身体蹲下降低后坐力");
            System.out.println("掏出步枪");
            System.out.println("打开 3 倍镜");
            System.out.println("开枪射击");            
            return;
        }        


        if(distance >= 1000) {
            System.out.println("发现敌人");
            System.out.println("趴在草丛里苟着");
            System.out.println("掏出狙击枪");
            System.out.println("打开 8 倍镜");
            System.out.println("开枪射击");            
            return;
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.

问题分析

我觉得这有 3 个问题,具体分析如下:

01 可读性问题

我看这么多 if/else 语句,里面的 sout 语句目前三四行也还好,如果我们有上百行的语句,里面也有很多 if/else,这样都不知道下个主 if 跑哪去啦 😳

02 重复性问题

全都需要发现敌人,如果发现敌人是个成百上千行代码,就很麻烦啦。

03 可维护性问题

如果这时候我们新增了一种枪,比如是霰弹枪,适用 10 到 20 的时候使用,这时候我们就需要在加一个 if 语句如下:

/**
 * 面条式代码判断最强武器
 */
 public class NoodlesKillProcessor {    


    /**
     * 根据距离判断最好的武器击杀对手
     * @param distance
     */
    @BadSmell
    public static void killByDistance(int distance) {        


        if(distance < 0) {            
            throw new RuntimeException("距离咋还能是负数呢?");
        }        


        if(distance >= 0 && distance < 1) {
            System.out.println("发现敌人");
            System.out.println("两步快速走过去");
            System.out.println("掏出平底锅呼他");         
            return;
        }        


        if(distance >= 1 && distance < 10) {
            System.out.println("发现敌人");
            System.out.println("快速走过去");
            System.out.println("掏出手枪打他");           
            return;
        }        


        if(distance >= 10 && distance < 20) {
            System.out.println("发现敌人");
            System.out.println("身体站直, 瞄准");
            System.out.println("打一枪算一枪");           
            return;
        }        


        if(distance >= 20 && distance < 100) {
            System.out.println("发现敌人");
            System.out.println("身体站直, 心态稳住");
            System.out.println("掏出冲锋枪打他");         
            return;
        }        


        if(distance >= 100 && distance < 1000) {
            System.out.println("发现敌人");
            System.out.println("身体蹲下降低后坐力");
            System.out.println("掏出步枪");
            System.out.println("打开 3 倍镜");
            System.out.println("开枪射击");            
            return;
        }        


        if(distance >= 1000) {
            System.out.println("发现敌人");
            System.out.println("趴在草丛里苟着");
            System.out.println("掏出狙击枪");
            System.out.println("打开 8 倍镜");
            System.out.println("开枪射击");            
            return;
        }
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.

这个看着也没啥大问题的样子,不就是加了个 if 么,但是由于我们改动了这个文件,测试同学问我们需要测试哪些功能,说是测一种枪需要 5 天。

问题来啦,本来说是你增加一种枪, 需要测 5 天,但是现在你说改了这文件,上下可能有些局部变量共享的,或者有些方法可能改了入参的值,这些有负作用的方法被调用啦,所以可能狙击枪也得测一测,可能手枪也得测一测。

测试同学崩了,本来 5 天的工作量,搞成了 5 * 6 天,一个月都在测枪。

QQ6lKoM" id="hdf2c2dd-2QQ6lKoM">初步尝试解决

我们先定义好一个基础类,解决一下可读性问题和重复性问题。

定义一个基础武器类:

/**
 * 抽象的枪
 */
public abstract class Weapon {    


    /**
     * 发现敌人
     */
    protected void findEnemy() {
        System.out.println("发现敌人");
    }    


    /**
     * 开枪前的动作
     */
    protected abstract void preAction();    


    /**
     * 开枪
     */
    protected abstract void shoot();    


    /**
     * 整体的动作
     */
    public void kill() {
        findEnemy();
        preAction();
        shoot();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

逐个实现武器的具体类、平底锅、冲锋枪、步枪等类如下:

/**
 * 平底锅
 */
public class Pan extends Weapon {    


    @Override


    protected void preAction() {
        System.out.println("两步快速走过去");
    }    


    @Override


    protected void shoot() {
        System.out.println("掏出平底锅呼他");
    }
}


/**
 * 手枪类
 */
public class Pistol extends Weapon {    


    @Override


    protected void preAction() {
        System.out.println("快速走过去");
    }    


    @Override


    protected void shoot() {
        System.out.println("掏出手枪打他");
    }
}


/**
 * 霰弹枪
 */
public class Shotgun extends Weapon {    


    @Override


    protected void preAction() {
        System.out.println("身体站直, 瞄准");
    }    


    @Override


    protected void shoot() {
        System.out.println("打一枪算一枪");
    }
}


/**
 * 狙击枪
 */
public class SniperRifle extends Weapon {    


    @Override


    protected void preAction() {
        System.out.println("趴在草丛里苟着");
        System.out.println("掏出狙击枪");
        System.out.println("打开 8 倍镜");
    }    
    @Override
    protected void shoot() {
        System.out.println("开枪射击");
    }
}


/**
 * 冲锋枪
 */
public class SubmachineGun extends Weapon {    


    @Override


    protected void preAction() {
        System.out.println("身体站直, 心态稳住");
    }    


    @Override


    protected void shoot() {
        System.out.println("掏出冲锋枪打他");
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.

我们的方法就可以改动得更清晰啦。

/**
 * 抽象出类代码判断最强武器
 */
public class WeaponKillProcessor {    


    /**
     * 根据距离判断最好的武器击杀对手
     * @param distance
     */
    @BadSmell
    public static void killByDistance(int distance) {        


        if (distance < 0) {            


            throw new RuntimeException


            ("距离咋还能是负数呢?");


        }
        Weapon weapon = null;        


        if (distance >= 0 && distance < 1) {
            weapon = new Pan();
        } else if (distance >= 1 && distance < 10) {
            weapon = new Pistol();
        } else if (distance > 10 && distance < 20) {
            weapon = new Shotgun();
        } else if (distance >= 20 && distance < 100) {
            weapon = new SubmachineGun();
        } else if (distance >= 100 && distance < 1000) {
            weapon = new Rifle();
        } else if (distance >= 1000) {
            weapon = new SniperRifle();
        }
        weapon.kill();
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.

类图如下:

使用策略模式

上面的代码没有解决最根本的问题,也就是去除 if/else,所用的方法其实就是将 if else 转换为 for,这样的代码后续添加枪就不需要再增加新的类型啦。

我们先定义一个通用的策略模式接口如下:

/**
 * 策略模式
 */
public interface Strategy


<T extends AbstractStrategyRequest,


R extends AbstractStrategyResponse> {    
    /* 
     * 执行策略
     * @param request
     * @return
     */
    R executeStrategy(T request);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

入参和出参都是基本的抽象类:

/**
 * 策略模式抽象入参
 */
public abstract class AbstractStrategyRequest {
}
/**
 * 策略模式抽象出参
 */
public abstract class AbstractStrategyResponse {
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

实现一个武器抽象类实现接口:

public abstract class WeaponStrategy implements 


Strategy<WeaponStrategyRequest,


AbstractStrategyResponse> {    


    /**
     * 发现敌人
     */
    protected void findEnemy() {
        System.out.println("发现敌人");
    }    


    /**
     * 开枪前的动作
     */
    protected abstract void preAction();    


    /**
     * 开枪
     */
    protected abstract void shoot();    


    /**
     * 获取距离范围
     * @return
     */
    protected abstract Range<Integer> queryDistanceRange();    


    /**
     * 整体的动作
     */
    public void kill() {
        findEnemy();
        preAction();
        shoot();
    }    


    @Override


    public AbstractStrategyResponse


        executeStrategy(WeaponStrategyRequest request) {


        System.out.println("距离敌人 " + request.getDistance());


        kill();        


        return null;


    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.

其中的 Range 类实现如下:

/**
 * 范围类
 * @param <T>
 */
@Data
@AllArgsConstructor
public class Range<T extends Comparable<T>> {    


    private T start;    


    private T end;    


    public Range(T start, T end) {        


        this.start = start;        


        this.end = end;


    }    


    private boolean isIncludeStart = true;    


    private boolean isIncludeEnd = false;    


    /**
     * 判断是否在范围内
     * @param target
     * @return
     */
    public boolean inRange(T target) {        


        if(isIncludeStart) {            


            if(start.compareTo(target) > 0) {                


                return false;


            }
        } else {            


            if(start.compareTo(target) >= 0) {                


                return false;


            }
        }        


        if(isIncludeEnd) {            


            if(end.compareTo(target) < 0) {                


                return false;


            }
        } else {            


            if(end.compareTo(target) <= 0) {                


                return false;


            }
        }        


        return true;


    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.

依次实现这个抽象武器策略类:

/**
 * 平底锅
 */
public class PanStrategy extends WeaponStrategy {    
    @Override


    protected void preAction() {
        System.out.println("二步快速走过去");
    }    
    @Override
    protected void shoot() {
        System.out.println("掏出平底锅呼他");
    }    
    @Override
    protected Range<Integer> queryDistanceRange() {     
        return new Range<>(0, 1);
    }
}


/**
 * 手枪类
 */
public class PistolStrategy extends WeaponStrategy {    


    @Override


    protected void preAction() {
        System.out.println("快速走过去");
    }    


    @Override


    protected void shoot() {
        System.out.println("掏出手枪打他");
    }    


    @Override


    protected Range<Integer> queryDistanceRange() {     
        return new Range<>(1, 10);
    }
}


/**
 * 步枪
 */
public class RifleStrategy extends WeaponStrategy {    


    @Override


    protected void preAction() {
        System.out.println("身体蹲下降低后坐力");
        System.out.println("掏出步枪");
        System.out.println("打开 3 倍镜");
    }    


    @Override


    protected void shoot() {
        System.out.println("开枪射击");
    }    


    @Override


    protected Range<Integer> queryDistanceRange() {     
        return new Range<>(100, 1000);
    }
}


/**
 * 霰弹枪
 */
public class ShotgunStrategy extends WeaponStrategy {    


    @Override


    protected void preAction() {
        System.out.println("身体站直, 瞄准");
    }    


    @Override


    protected void shoot() {
        System.out.println("打一枪算一枪");
    }    


    @Override


    protected Range<Integer> queryDistanceRange() {     
        return new Range<>(10, 20);
    }
}


/**
 * 狙击枪
 */
public class SniperRifleStrategy extends WeaponStrategy {    


    @Override


    protected void preAction() {
        System.out.println("趴在草丛里苟着");
        System.out.println("掏出狙击枪");
        System.out.println("打开 8 倍镜");
    }    


    @Override


    protected void shoot() {
        System.out.println("开枪射击");
    }    


    @Override


    protected Range<Integer> queryDistanceRange() {     
        return new Range<>(1000, Integer.MAX_VALUE);
    }
}


/**
 * 冲锋枪
 */
public class SubmachineGunStrategy extends WeaponStrategy {    


    @Override


    protected void preAction() {
        System.out.println("身体站直, 心态稳住");
    }    


    @Override


    protected void shoot() {
        System.out.println("掏出冲锋枪打他");
    }    


    @Override


    protected Range<Integer> queryDistanceRange() {     
        return new Range<>(20, 100);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.

定义一个上下文类来对入参进行路由:

/**
 * 策略上下文, 用来路由策略
 */
public class StrategyContext {
    public static final List<WeaponStrategy>


        WEAPON_STRATEGYS = new ArrayList<>();




    static {
        WEAPON_STRATEGYS.add(new PanStrategy());
        WEAPON_STRATEGYS.add(new PistolStrategy());
        WEAPON_STRATEGYS.add(new RifleStrategy());
        WEAPON_STRATEGYS.add(new ShotgunStrategy());
        WEAPON_STRATEGYS.add(new SniperRifleStrategy());
        WEAPON_STRATEGYS.add(new SubmachineGunStrategy());
    }


    public static void execute(Integer distance) {
        WEAPON_STRATEGYS.stream().
        filter((weaponStrategy -> {
            Range<Integer> integerRange =
                weaponStrategy.queryDistanceRange();
            return integerRange.inRange(distance);
        })).
        findAny().
        get().
        executeStrategy(
            new WeaponStrategyRequest(distance));
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.

最后在主方法里面调用就好啦:

public class App {    


public static void main(String[] args) {        
        StrategyContext.execute(89);
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

结果如下:

距离敌人 89

发现敌人

身体站直,心态稳住

掏出冲锋枪打他

类图如下: