六、策略模式

策略模式

一、什么是策略模式

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。

策略模式(Strategy),定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。

UML结构图如下:

png

其中,Context是上下文,维护了一个对Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。

1. Context上下文

Context上下文角色,也叫Context封装角色,起承上启下的作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化。

public class Context {
    
    Strategy strategy;
    
    public Context(Strategy strategy) {
        this.strategy = strategy;
    }
    
    //上下文接口
    public void contextInterface() {
        strategy.algorithmInterface();
    }

}

2. 策略角色

抽象策略角色,是对策略、算法家族的抽象,通常为接口,定义每个策略或算法必须具有的方法和属性。algorithm是“运算法则”的意思。

public abstract class Strategy {
    //算法方法
    public abstract void algorithmInterface();
}

3. 具体策略角色

用于实现抽象策略中的操作,即实现具体的算法,下方用print代替。测试类共3个ConcreteStrategy,其它两个类与ConcreteStrategyA同理,就不再赘述了。

public class ConcreteStrategyA extends Strategy {

    @Override
    public void algorithmInterface() {
        System.out.println("算法A实现");
    }

}

4. Client客户端

下面依次更换策略,测试一下策略模式。

public class Client {
    
    public static void main(String[] args) {
        Context context;
        
        context = new Context(new ConcreteStrategyA());
        context.contextInterface();
        
        context = new Context(new ConcreteStrategyB());
        context.contextInterface();
        
        context = new Context(new ConcreteStrategyC());
        context.contextInterface();
    }
}

/**测试结果
算法A实现
算法B实现
算法C实现
*/

二、策略模式的应用及优缺点

应用场景

  • 多个类只有算法或行为上稍有不同的场景
  • 算法需要自由切换的场景
  • 需要屏蔽算法规则的场景

优点:

  1. 算法可以自由切换
  2. 避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护)
  3. 扩展性良好,增加一个策略只需实现接口即可

缺点:

  1. 策略类数量会增多,每个策略都是一个类,复用的可能性很小
  2. 所有的策略类都需要对外暴露

三、策略模式案例

我们来模拟一个下班回家的场景,需要自己选择不同的交通工具来回家

1、上下文类

首先声明一个TravelContext对象,通过构造方法,传入具体的交通工具。

public class TravelContext {
    private Vehicle vehicle;

    public TravelContext(Vehicle vehicle){
        this.vehicle = vehicle;
    }

    public void goHome(){
        if (vehicle!=null){
            vehicle.travel();
        }
    }
}

2、交通工具抽象类

public interface Vehicle {
    void travel();
}

3、不同的交通工具类

public class Bus implements Vehicle {
    public void travel() {
        System.out.println("乘坐巴士");
    }
}

public class Car implements Vehicle {
    public void travel() {
        System.out.println("乘坐小汽车");
    }
}

public class Taxi implements Vehicle {
    public void travel() {
        System.out.println("乘坐出租车");
    }
}

4、Client客户端

下面写一个简单的程序测试一下上方编写的代码。

public class Client {
    public static void main(String[] args) {
        TravelContext travelContext = null;
        System.out.println("请选择回家乘坐的交通工具:1.小汽车 2.出租车 3.巴士");
        Scanner scanner = new Scanner(System.in);
        int input = scanner.nextInt();
        switch (input){
            case 1:
                travelContext = new TravelContext(new Car());
                travelContext.goHome();
                break;
            case 2:
                travelContext = new TravelContext(new Taxi());
                travelContext.goHome();
                break;
            case 3:
                travelContext = new TravelContext(new Bus());
                travelContext.goHome();
                break;
            default:
                System.out.println("请输入1/2/3");
                break;
        }
    }
}

/**测试结果
请选择回家乘坐的交通工具:1.小汽车 2.出租车 3.巴士
3
乘坐巴士
*/
posted @ 2019-11-19 20:40  ねぇ  阅读(548)  评论(0编辑  收藏  举报