用Lambdas重构策略设计模式

19-01-28 banq
                   

策略模式是表示一系列算法的通用解决方案,并允许您在运行时选择它们。您可以将此模式应用于多种方案,例如使用不同的解析方式或格式化输入来验证具有  不同条件的输入。

策略设计模式:不使用Lambda表达式

假设我们验证文本输入是否针对不同的标准进行了适当的格式化(例如,它只包含小写字母或数字)。首先定义一个接口来验证文本(表示为String):

 interface ValidationStrategy {
        public boolean execute(String s);
    }

其次,让我们定义该接口的一个或多个实现:

pulic class IsAllLowerCase implements ValidationStrategy {
      public boolean execute(String s){
          return s.matches("[a-z]+");
      }
}
pulic class IsNumeric implements ValidationStrategy {
      public boolean execute(String s){
          return s.matches("\\d+");
      }
}

我们在程序中使用这些不同的验证策略。

 public class Validator{
        private final ValidationStrategy strategy;
        public Validator(ValidationStrategy v){
            this.strategy = v;
        }
        public boolean validate(String s){
            return strategy.execute(s); }
    }

让我们使用main方法测试这个Pattern。

public static void main(String[] args) {
        // old school
        Validator v1 = new Validator(new IsNumeric());
        System.out.println(v1.validate("aaaa"));
        Validator v2 = new Validator(new IsAllLowerCase ());
        System.out.println(v2.validate("bbbb"));

  }

请注意,为了应用lambda表达式,Strategy接口应该是  Functional Interfaces

策略设计模式:使用Lambda表达式

到目前为止,我们应该认识到ValidationStrategy是一个函数接口(此外,它具有与Predicate <String>相同的函数描述符)。这意味着我们可以直接传递lambda表达式,而不是声明新类来实现不同的策略,这些表达式更简洁:

// with lambdas
 Validator v3 = new Validator((String s) -> s.matches("\\d+"));
 System.out.println(v3.validate("aaaa"));
 Validator v4 = new Validator((String s) -> s.matches("[a-z]+"));
 System.out.println(v4.validate("bbbb"));

如您所见,lambda表达式删除了策略设计模式固有的样板代码。如果你考虑一下,lambda表达式封装了一段代码(或策略),这就是创建策略设计模式的原因,所以我建议你使用lambda表达式代替类似的问题。