美文网首页
6.JAVA策略方法模式总结

6.JAVA策略方法模式总结

作者: ironman327 | 来源:发表于2018-10-08 22:07 被阅读0次

    0.抛出问题

    在软件构建过程中,某些对象使用的算法可能多种多样,经常改变。如果将这些算法都编码在一个对象中,会使得对象变得异常复杂,而且支持不使用的算法也是一个性能负担。如何在运行时候根据需要更改对象的算法,将算法和对象本身解耦?

    1.具体场景

    假设我们现在有一家跨国公司需要计算每个国家的关税(目前业务涉及中国、美国、法国),设计软件

    第一版代码

    //枚举类型定义三个参数
    public enum TaxBase {
        CN_TAX,
        US_TAX,
        FR_TAX
    }
    
    public class SalesOrder {
        TaxBase taxBase;
        public void CalculateTax(){
            switch (taxBase){
               case CN_TAX:
                    System.out.println("假设这是一堆很复杂的算法");
                    System.out.println("中国关税");
                    break;
                case FR_TAX:
                    System.out.println("假设这是一堆很复杂的算法");
                    System.out.println("法国关税");
                    break;
                case US_TAX:
                    System.out.println("假设这是一堆很复杂的算法");
                    System.out.println("美国关税");
                    break;
            }
        }
    
        public void setTaxBase(TaxBase taxBase) {
            this.taxBase = taxBase;
        }
    }
    
    public class Main {
        public static void main(String[] args)
        {
            SalesOrder salesOrder = new SalesOrder();
            salesOrder.setTaxBase(TaxBase.CN_TAX);
            salesOrder.CalculateTax();
        }
    }
    
    //运行结果
    假设这是一堆很复杂的算法
    中国关税
    Process finished with exit code 0
    

    可以说上面的代码是非常非常的简单了,经过前几篇的文章的总结,这里面的设计缺陷已经被重复无数次了,代码复用性不够,要是业务有扩展添加英国关税后,需要修改SalesOrder类源代码,而且将所有的算法都写在同一个类里面,如果哪天公司业务遍布全球232个国家和地区,那这个类可太臃肿了。必须改改改!!!

    2.改进


    类图分析,定义一个Strategy接口(所有关税算法的抽象接口),然后在Context类中根据需要来创建具体的算法对象

    //公共接口
    public interface TaxStrategy {
        double calculate();
    }
    
    public class FRTaxStrategy implements TaxStrategy {
        @Override
        public double calculate() {
            System.out.println("假设这是一堆很复杂的算法");
            System.out.println("法国关税");
            return 0;
        }
    }
    
    public class CNTaxStrategy implements TaxStrategy {
        @Override
        public double calculate() {
            System.out.println("假设这是一堆很复杂的算法");
            System.out.println("中国关税");
            return 0;
        }
    }
    
    public class USTaxStrategy implements TaxStrategy {
        @Override
        public double calculate() {
            System.out.println("假设这是一堆很复杂的算法");
            System.out.println("美国关税");
            return 0;
        }
    }
    
    //上下文
    public class Context {
        private TaxStrategy taxStrategy;
        //根据传过来的字节码去反射创建相应对象
        public Context(Class<TaxStrategy> taxStrategyClass) {
            try {
                taxStrategy=taxStrategyClass.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        public void execute(){
            taxStrategy.calculate();
        }
    }
    
    public class Main {
        public static void main(String[] args)
        {
            Context context = new Context(CNTaxStrategy.class);
            context.execute();
        }
    }
    
    //运行结果
    假设这是一堆很复杂的算法
    中国关税
    
    Process finished with exit code 0
    

    这样写的话我们在需要添加新关税算法只需要用一个类去实现TaxStrategy接口就好了,问题被解决。

    2.总结

    上面的代码其实很像简单工厂模式,笔者在刚接触的时候觉得基本一模一样,现在细说一下他们的区别。

    简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建并且返回哪一 个产品类(这些产品类继承自一个父类或接口)的实例。
    那么也就是说:
    1、有已知的产品类
    2、你无法准确的知道编译哪个产品类
    3、需要在运行时决定创建哪个产品类
    4、产品类不多
    很明显看出,在创建对象上的灵活性高

    策略模式它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。在一段代码里,使用了逻辑控制(if-else,swich-case)来决定算法,算法有相似的方法和函数,就可以选择策略模式。
    那么也就是说:
    1、某方法里有多个条件语句,条件语句代码块里有许多行为过程。
    2、其算法能封装到策略类
    3、算法随意切换
    4、算法与客户端隔离
    这样一来,通过选择对应的策略类,作为参数传到Content类里,在运行时配置对应的算法。

    可以看出,两者解决的问题不同。简单工厂模式是解决产品类的统一分发、策略模式是为了解决策略的切换和扩展。

    相关文章

      网友评论

          本文标题:6.JAVA策略方法模式总结

          本文链接:https://www.haomeiwen.com/subject/dfwdaftx.html