用Lambda重构责任模式链

19-01-27 banq
                   

责任链模式是创建处理对象链(例如一系列操作)的通用解决方案。一个处理对象可以做一些工作并将结果传递给另一个对象,然后该对象也做一些工作并将其传递给另一个处理对象,依此类推。

责任链模式:不使用Lambda表达式

步骤1:通常,通过定义表示处理对象的抽象类来实现该模式,该处理对象定义用于跟踪后继的字段。一旦完成工作,  处理对象将其工作交给其继任者。在代码中它看起来像这样:

public abstract class ProcessingObject<T> {
 protected ProcessingObject<T> successor;

 public void setSuccessor(ProcessingObject<T> successor) {
  this.successor = successor;
 }

 public T handle(T input) {
  T r = handleWork(input);
  if (successor != null) {
   return successor.handle(r);
  }
  return r;
 }

 abstract protected T handleWork(T input);
}

方法handle提供了如何处理一项工作的概述。通过继承类ProcessingObject并为方法handleWork提供实现,可以创建不同类型的处理对象  。

让我们看一个如何使用这种模式的例子。您可以创建两个处理对象进行一些文本处理:

public class HeaderTextProcessing
  extends ProcessingObject<String> {
 public String handleWork(String text) {
  return "From Raoul, Mario and Alan: " + text;
 }
}

public class SpellCheckerProcessing
  extends ProcessingObject<String> {
 public String handleWork(String text) {
  return text.replaceAll("labda", "lambda");
 }
}

让我们编写代码来测试上面没有lambda表达式的代码:

public static void main(String[] args) {
 ProcessingObject<String> p1 = new HeaderTextProcessing();
 ProcessingObject<String> p2 = new SpellCheckerProcessing();
 p1.setSuccessor(p2);
 String result1 = p1.handle("Aren't labdas really sexy?!!");
 System.out.println(result1);
}

责任链模式:使用Lambda表达式

通过使用lambda表达式,我们可以避免创建子类来实现handleWork()方法。我们可以将处理对象表示为Function <String,String> 的实例,   或者更确切地说是 UnaryOperator <String> 。要链接它们,我们只需要使用andThen  方法来组合这些函数  。

public static void main(String[] args) {

 // First processing object
 UnaryOperator<String> headerProcessing =
   (String text) -> "From Raoul, Mario and Alan: " + text;
   
 //Second processing object
 UnaryOperator<String> spellCheckerProcessing =
   (String text) -> text.replaceAll("labda", "lambda");
   
 // Compose the two functions resulting in a chain of operations.
 Function<String, String> pipeline = headerProcessing.andThen(spellCheckerProcessing);
 String result2 = pipeline.apply("Aren't labdas really sexy?!!");
 System.out.println(result2);
}