6.JAVA策略方法模式总结

2018-10-08  本文已影响0人  ironman327

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类里,在运行时配置对应的算法。

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

上一篇下一篇

猜你喜欢

热点阅读