首页 > 代码库 > 重构,测试和调试

重构,测试和调试

  利用Lambda表达式,方法引用以及Stream改善程序代码的可读性:

    重构代码,用Lambda表达式取代匿名类

    用方法引用重构Lambda表达式

    用Stream API重构命令式的数据结构

 

  从匿名类道Lambda表达式的转换

    Runnable runner = new Runnble(){

      public void run(){

        System.out.println("Hello");

      }

    };  

    --> Runnable runner = () -> System.out.println("Hello");  

    匿名类和Lambda表达式中的this和super的含义是不同的。在匿名类中,this代表的是类自身,但在Lambda中,它代表的是包含类。其次匿名类可以屏蔽包含类的变量,而Lambda表达式则会报编译错误。

    在涉及重载的上下文里,将匿名类转换为Lambda表达式可能导致最终的代码加晦涩。实际上匿名类的类型是在初始化时确定的,而Lambda的类型取决于它的上下文。

    interface Task{

      public void execute();

    }

    public static void doSomething(Runnable r){ r.run();}

    public staitc void doSomething(Task t){ t.execute();};

    -->

    doSomething() -> System.out.println("Danger"); //此时两个类都是合法的目标类型

    doSomething(Task) -> System.out.println("Danger"); //显式指定了需要使用的类型

 

  采用函数式接口

    可以采用有条件的延迟执行和环绕执行这两种模式重构代码,利用Lambda表达式带来灵活性。当需要从客户端代码频繁的去查询一个对象的状态是为了传递参数,调用该对象的一个方法,那么可以考虑实现一个新的方法,以Lambda或者方法表达式作为参数,新方法在检查完该对象的状态后才调用原来的方法。

    有条件的延迟执行

      Java8 API的log新添了一个log的重载方法,接受了一个Supplier作为参数。

        public void log(Level level, Supplier<String> msgSupplier);

        -->

        public void log(Level level, Supplier<String> msgSupplier){

          if(logger.isLoggable(level)){

            log(level, msgSupplier.get());

          }

        }

    环绕执行

      当业务具有同样的准备和清理阶段,可以将这部分代码用Lambda表达式实现,这种方式的好处是可以重用准备和清理阶段的逻辑,减少重复冗余的代码。

      String oneline = processFile((BufferedReader b) -> b.readLine());

      String twoline = processFile((BufferedReader b) -> b.readLine() + b.readLine());

      public static String processFile(BufferedReaderProcessor p) throws IOException{

        try(BufferedReader br = new BufferedReader(new FileReader("text.txt"))){

          return p.process(br);

        }

      }

      public interface BufferReaderProcessor{

        String process(BufferReader b) throws IOException;

      }

 

   访问者模式常用于分离程序的算法和它的操作对象。单例模式一般用于限制类的实例话,仅生成一个对象。

   

  策略模式

    策略模式代表了解决一类算法的通用解决方案,可以在运行时选择使用哪种方案。策略模式包含三部分内容:一个代表某个算法的接口;一个或多个该接口的具体实现,它们代表了算法的多种实现;一个或多个使用策略对象的客户。

 

  模板方法

    若需要采用某个算法的框架,同时又希望有一定的灵活度,能对它的某些部分进行改进,采用模版方法设计模式是比较通用的方案。

 

  观察者模式

    某些事件发生h时,主题需要自动地通知其他多个观察者。

 

  责任链模式

    责任链模式是一种创建成立对象序列的通用方案。一个处理对象可能需要在完成一些工作之后,将结果传递给另一个对象,这个对象接着做一些工作幕后再转交给下一处对象,以此类推。这种模式是通过定义一个代表处理对象的抽象类实现的,在抽象类中会定义一个字段来记录后续对象。一旦对象完成它的工作,处理对象就会将它的工作转交给它的后继。

 

  工厂模式

    无需向客户端暴漏实例化逻辑就能完成对象的创建.

 

  因为lambda表达式没有名字,所以对lambda表达式进行调试是十分困难的。在程序异常时,编译器只能为它们指定一个名字,若方法引用指的是同一个类中生命的方法,那么它的名称是可以在栈跟踪中显示的。

  对流操作中的流水线进行调试是可以调用peek方法。peek在流的每个元素恢复运行之前插入一个动作。

  numbers.stream().peek(x -> System.out.println("from stream: " + x))

          .map(x -> x + 7)

          .peek(x -> System.out.println("after map"))

          .collect(toList());    

重构,测试和调试