13-策略模式

策略模式

一、定义

定义一组算法,将每个算法搜封装起来,并且使他们之间可以互换。

策略模式的通用类图
在这里插入图片描述
Context是封装角色,起承上启下作用,屏蔽高层模块对策略、算法的直接访问,封装可能存在的变化;Strategy是抽象策略角色,抽象策略算法,通常为接口,定义每个策略或算法必须具有的方法和属性;ConcreteStrategy是具体策略角色,实现抽象策略中的操作;

策略模式的通用源码

  1. 抽象的策略角色

    public interface Strategy {
        //策略模式的运算法则
        public void doSomething();
    }
    
  2. 具体策略角色

    public class ConcreteStrategy1 implements Strategy {
        public void doSomething() {
        	System.out.println("具体策略1的运算法则");
        }
    }
    
    public class ConcreteStrategy2 implements Strategy {
         public void doSomething() {
            System.out.println("具体策略2的运算法则");
        }
    }
    
  3. 封装角色

    public class Context {
        //抽象策略
        private Strategy strategy = null;
        
        //构造函数设置具体策略
        public Context(Strategy _strategy){
        	this.strategy = _strategy;
        }
        //封装后的策略方法
        public void doAnythinig(){
        	this.strategy.doSomething();
        }
    }
    
  4. 高层模块

    public class Client {
        public static void main(String[] args) {
            //声明一个具体的策略
            Strategy strategy = new ConcreteStrategy1();
            //声明上下文对象
            Context context = new Context(strategy);
            //执行封装后的方法
            context.doAnythinig();
        }
    }
    

二、策略模式的优点

  • 算法可以自由切换

    只要实现抽象策略,它就成为策略家族的一个成员,通过封装角色对其进行封装,保证对外提供“可自由切换”的策略

  • 避免使用多重条件判断

    使用策略模式后,可以由其他模块决定采用何种策略,策略家族对外提供的访问接口就是封装类,简化了操作,同时避免了条件语句判断

  • 扩展性良好

    在现有的系统中增加一个策略,只要实现接口就可以了,其他都不用修改,类似于一个可反复拆卸的插件,符合了OCP原则。

三、策略模式的缺点

  • 策略类数量增多

    每个策略都要建立一个类,复用的可能性小,类数量增多

  • 所有的策略类搜需要对外暴露

    上层模块必须知道有哪些策略,然后才能决定使用哪一个策略,与迪米特法则是相违背的

四、策略模式的使用场景

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

注意:如果系统中的一个策略家族的具体策略数量超过4个,则需要考虑使用混合模式,解决
策略类膨胀和对外暴露的问题,否则日后的系统维护困难。

扩展:策略枚举

原有定义在抽象策略中的方法移植到枚举中,每个枚举成员就成为一个具体策略。

public enum Calculator {
    //加法运算
    ADD("+"){
        public int exec(int a,int b){
        return a+b;
    }
    },
    //减法运算
    SUB("-"){
        public int exec(int a,int b){
        return a - b;
    }
    };
    
    String value = "";
    
    //定义成员值类型
    private Calculator(String _value){
    	this.value = _value;
    }
    
     //获得枚举成员的值
    public String getValue(){
    	return this.value;
    }
    
    //声明一个抽象函数
    public abstract int exec(int a,int b);
}
public class Client {
public static void main(String[] args) {
    //输入的两个参数是数字
    int a = Integer.parseInt(args[0]);
    String symbol = args[1]; //符号
    int b = Integer.parseInt(args[2]);
    System.out.println("输入的参数为:"+Arrays.toString(args));
    if("+".equest(symbol){
    	System.out.println("运行结果为:"+a+symbol+b+"="+Calculator.ADD.exec(a,b));
    }else{
        System.out.println("运行结果为:"+a+symbol+b+"="+Calculator.SUB.exec(a,b));
    }
}

注意 策略枚举是一个非常优秀和方便的模式,但是它受枚举类型的限制,每个枚举项都是public、final、static的,扩展性受到了一定的约束,因此在系统开发中,策略枚举一般担当不经常发生变化的角色。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值