利用Lambda重构

  • 环绕执行:重用准备和清理阶段的逻辑,减少重复冗余的代码。

    String oneLine =
         processFile((BufferedReader b) -> b.readLine());
    String twoLines =
         processFile((BufferedReader b) -> b.readLine() + b.readLine());
    
    public static String processFile(BufferedReaderProcessor p) throws
           IOException {
         try(BufferedReader br = new BufferedReader(new FileReader("java8inaction/
           chap8/data.txt"))){
               return p.process(br);//将BufferedReaderProcessor作为执行参数传入
         }
    }
    public interface BufferedReaderProcessor{
          String process(BufferedReader b) throws IOException;
    } 
    
  • 策略模式

  1. 一个代表某个算法的接口(它是策略模式的接口)。

  2. 一个或多个该接口的具体实现,它们代表了算法的多种实现。

  3. 一个或多个使用策略对象的客户。
    例如:对输入的内容是否根据标准进行了恰当的格式化

     //声明一个函数式接口
     public interface ValidationStrategy {
          boolean execute(String s);
     } 
    //定义了该接口的一个或多个具体实现:
     public class IsAllLowerCase implements ValidationStrategy {
          public boolean execute(String s){
                return s.matches("[a-z]+");
         }
     }
     public 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);
        }
     }
    
     Validator numericValidator = new Validator(new IsNumeric());
     boolean b1 = numericValidator.validate("aaaa");
     Validator lowerCaseValidator = new Validator(new IsAllLowerCase ());
     boolean b2 = lowerCaseValidator.validate("bbbb"); 
     //使用Lambda表达式
     Validator numericValidator =
            new Validator((String s) -> s.matches("[a-z]+"));
     boolean b1 = numericValidator.validate("aaaa");
     Validator lowerCaseValidator =
            new Validator((String s) -> s.matches("\\d+"));
     boolean b2 = lowerCaseValidator.validate("bbbb"); 
    
  • 模块方法
    模板方法模式在你“希望使用这个算法,但是需要对其中的某些行进行改进,才能达到希望的效果”时是非常有用的。
    例如:一个在线银行,输入账号之后可以从数据库查询到用户的详细信息,最终完成一些操作。

    abstract class OnlineBanking {
        
       //获取客户提供的id,提供服务让用户满意,不同的支付通过继承OnlineBanking类,对该方法提供差异化的体现。
       public void processCustomer(int id){
           Customer c = Database.getCustomerWithId(id);
           makeCustomerHappy(c); 
       }  
       abstract void makeCustomerHappy(Customer c); 
    }
    //或者
    public void processCustomer(int id, Consumer makeCustomerHappy){
       Customer c = Database.getCustomerWithId(id);
       makeCustomerHappy.accept(c);
    } 
    
    
    new OnlineBankingLambda().processCustomer(1337, (Customer c) ->
           System.out.println("Hello " + c.getName()); 
    
  • 观察者模式:
    某些事件发生时(比如状态转变),如果一个对象(通常称之为主题)需要自动地通知其他多个对象(称为观察者),就会采用该方案。
    例如:
    设计并实现一个定制化的通知系统。想法很简单:好几家报纸机构,比如《纽约时报》《卫报》以及《世界报》都订阅了新闻,他们希望当接收的新闻中包含他们感兴趣的关键字时,能得到特别通知。

    定义一个观察者接口,它将不同的观察者聚合在一起。它仅有一个名为notify的方法,一旦接收到一条新的新闻,该方法就会被调用:

    interface Observer {
     void notify(String tweet);
    } 
    interface Subject{
     void registerObserver(Observer o);//注册新的观察者
     void notifyObservers(String tweet);//通知它的观察者一个新闻的到来
    } 
    

    声明不同的观察者,根据关键字不同定义不同的行为:

    class NYTimes implements Observer{
       public void notify(String tweet) {
           if(tweet != null && tweet.contains("money")){
               System.out.println("Breaking news in NY! " + tweet);
       }
     }
    }
    class Guardian implements Observer{
       public void notify(String tweet) {
           if(tweet != null && tweet.contains("queen")){
               System.out.println("Yet another news in London... " + tweet);
       }
     }
    }
    class LeMonde implements Observer{
       public void notify(String tweet) {
           if(tweet != null && tweet.contains("wine")){
               System.out.println("Today cheese, wine and news! " + tweet);
       }
     }
    } 
    

    实现Subject

    class Feed implements Subject{
    
    private final List observers = new ArrayList<>();
    
    public void registerObserver(Observer o) {
       this.observers.add(o);
      }
    
    public void notifyObservers(String tweet) {
       observers.forEach(o -> o.notify(tweet));
      }
    } 
    

    Feed类在内部维护了一个观察者列表,一条新闻到达时,它就进行通知。

    Feed f = new Feed();
    f.registerObserver(new NYTimes());
    f.registerObserver(new Guardian());
    f.registerObserver(new LeMonde());
    f.notifyObservers("The queen said her favourite book is Java 8 in Action!"); 
    

    由于,Observer接口的所有实现类都提供了一个方法:notify。新闻到达时,它们都只是对同一段代码封装执行。使用Lambda表达式后,你无需显式地实例化三个观察者对象,直接传递Lambda表达式表示需要执行的行为即可:

    f.registerObserver((String tweet) -> {
       if(tweet != null && tweet.contains("money")){
               System.out.println("Breaking news in NY! " + tweet);
       }
    });
    
    f.registerObserver((String tweet) -> {
      if(tweet != null && tweet.contains("queen")){
               System.out.println("Yet another news in London... " + tweet);
       }
    }); 
    
  • 责任链模式
    责任链模式是一种创建处理对象序列(比如操作序列)的通用方案。一个处理对象可能需要在完成一些工作之后,将结果传递给另一个对象,这个对象接着做一些工作,再转交给下一个处理对象,以此类推。
    这种模式是通过定义一个代表处理对象的抽象类来实现的,在抽象类中会定义一个字段来记录后续对象。一旦对象完成它的工作,处理对象就会将它的工作转交给它的后继。

    public abstract class ProcessingObject {
    
         protected ProcessingObject successor;
         public void setSuccessor(ProcessingObject 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);
    } 
    

例如:定义两个对象,它们的功能是处理一些文本处理工作

public class HeaderTextProcessing extends ProcessingObject {
   public String handleWork(String text){
       return "From Raoul, Mario and Alan: " + text;
   }
}
public class SpellCheckerProcessing extends ProcessingObject {
   public String handleWork(String text){
       return text.replaceAll("labda", "lambda");
   }
} 

ProcessingObject p1 = new HeaderTextProcessing();
ProcessingObject p2 = new SpellCheckerProcessing();
p1.setSuccessor(p2);
String result = p1.handle("Aren't labdas really sexy?!!");
System.out.println(result); //打印输出“From Raoul, Marioand Alan: Aren't lambdas reallysexy?!!”

//Lambda
UnaryOperator headerProcessing =
       (String text) -> "From Raoul, Mario and Alan: " + text;

UnaryOperator spellCheckerProcessing =
       (String text) -> text.replaceAll("labda", "lambda");

Function pipeline =
       headerProcessing.andThen(spellCheckerProcessing);

String result = pipeline.apply("Aren't labdas really sexy?!!");

注:
UnaryOperator的函数描述符为 T -> T

  • 工厂模式
    无需向客户暴露实例化的逻辑就能完成对象的创建。比如,我们假定你为一家银行工作,他们需要一种方式创建不同的金融产品:贷款、期权、股票,等等。

    public class ProductFactory {
         public static Product createProduct(String name){
                 switch(name){
                     case "loan": return new Loan();
                     case "stock": return new Stock();
                     case "bond": return new Bond();
                     default: throw new RuntimeException("No such product " + name);
             }
         }
    } 
    

    createProduct方法可以通过附加的逻辑来设置每个创建的产品。但是带来的好处也显而易见,你在创建对象时不用再担心会将构造函数或者配置暴露给客户,这使得客户创建产品时更加简单:

    Product p = ProductFactory.createProduct("loan"); 
    

    使用Lambda表达式: Supplier的函数描述符 () -> T必须返回一个结果为空的supplier

    Supplier loanSupplier = Loan::new;
    Loan loan = loanSupplier.get(); 
    

利用Lambda重构之前的代码:

final static Map> map = new HashMap<>();
static {
   map.put("loan", Loan::new);
   map.put("stock", Stock::new);
   map.put("bond", Bond::new);
} 
//实例化不同产品
public static Product createProduct(String name){
     Supplier p = map.get(name);
     if(p != null) return p.get();
     throw new IllegalArgumentException("No such product " + name);
} 

若需要多个参数的构造函数,则需要自定义函数式接口:

  public interface TriFunction{
       R apply(T t, U u, V v);
  }
  Map> map
         = new HashMap<>(); 

你可能感兴趣的:(利用Lambda重构)