zoukankan      html  css  js  c++  java
  • 简单工厂搭配策略模式

    简单介绍一下这两个设计模式。

    策略模式的思想就是,当你要根据特定场景使用特定算法时,可以把用一个接口提供这个算法,不同的场景对他进行不同的实现。主流程通过不同的实现类

    来完成这个功能。

    简单工厂就是根据一个type返回对应的对象。

    简单工厂+策略模式就可以实现根据调用方传过来的type通过简单工厂获取到对数据操作的实现类,然后操作数据返回,当新增一个type时,可以很清晰解决,避免误改。

    下面以一个计算器举例,其实这不是一个很好的例子。

    public class CalculatorTest {
        /**
         * 调用方
         */
        @Test
        public void test() {
            double num1 = 1.1;
            double num2 = 2.0;
            double result = calculate(num1, num2, CaculatorType.ADD);
            System.out.println(result);
        }
    
        /**
         * 接收方
         * @param type 计算方法类型,是一个枚举值
         * @return 计算结果
         */
        public double calculate(double num1, double num2, CaculatorType type) {
            CalculatorFactory calculatorFactory = new CalculatorFactory();
         //根据type获取计算器 Calculator calculator
    = calculatorFactory.getCalculator(type); return calculator.caculate(num1, num2); } }

     这样做的好处就是未来新曾别的计算方法时,例如减法。思路很清晰,增加一个枚举值,增加一个减法的算法,

    calculate 这个方法完全不需要动,在实际的开发过程中,我们应该尽量保证主流程不被修改,这样才会减少Bug,故障的发生。
    下面看一下这个工厂类。
    public class CalculatorFactory {
        private EnumMap<CaculatorType,Calculator> typeToCalculator = Maps.newEnumMap(CaculatorType.class);
    
        {
            //当方法容易实现时,可以用lambda表达式实现策略模式从而避免每次都要新建一个类
            typeToCalculator.put(CaculatorType.ADD, (num1, num2) -> num1 + num2);
            typeToCalculator.put(CaculatorType.SUB, (num1, num2) -> num1 - num2);
            typeToCalculator.put(CaculatorType.MUL, (num1, num2) -> num1 * num2);
            typeToCalculator.put(CaculatorType.DIV, (num1, num2) -> num1 / num2);
        }
        public  Calculator getCalculator(CaculatorType type){
            return typeToCalculator.get(type);
        }
    }

    常见的工厂类可能会用switch,但是个人感觉用map的形式更好,首先时间复杂度为O(1)当然,实现类的数量不可能太多,性能提升不会很明显。

    但是可读性会高,根据类型去容器里取对象,新增或删除时,加一行或者删一行代码即可,还有两点可能与其他看过的版本不同。

    1.使用了java8支持的lambda表达式代替了实现类,如果代码较短,不必新增一个类,用lambda表达式比较方便。

    2.我这里用的map是EnumMap,当然也可以用TreeMap和HashMap也可以,用EnumMap的原因是EnumMap底层会创建一个与CaculatorType实例

    个数相等的数组来存储。如果是hashmap会创建一个2的n次方的数组,浪费空间,并且hashmap还需要hash寻找数据存放位置,并且有可能hash冲突。

    使用TreeMap的话插入和查找的时间复杂度是O(logn)。而EnumMap的最大时间复杂度就是O(1),因为EnumMap底层创建一个和它元素数

    一样大的数组,当put时,如果put的是CaculatorType.ADD,会将它放入底层数组索引为CaculatorType.ADD.ordinal()的位置,也就是0,ordinal()

    代表第几个实例,取得时候也是取索引为0的对象,不通过任何计算,直接从数组拿,所以如果想用map可以考虑一下key适不适合用枚举,如果

    适合用枚举,果断采用并且用EnumMap。

  • 相关阅读:
    linux 进程操作脚本
    go 项目监听重启
    go 小题
    beego 基础
    beego 接口开发
    beego 安装
    mongo curd
    html的学习(一)
    ssl
    java编码的学习
  • 原文地址:https://www.cnblogs.com/zhandouBlog/p/10151994.html
Copyright © 2011-2022 走看看