美文网首页
利用Lambda重构

利用Lambda重构

作者: PawsUp | 来源:发表于2019-03-04 12:55 被阅读0次
    • 环绕执行:重用准备和清理阶段的逻辑,减少重复冗余的代码。

      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<Customer> 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<Observer> 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<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);
      } 
      

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

    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");
       }
    } 
    
    ProcessingObject<String> p1 = new HeaderTextProcessing();
    ProcessingObject<String> 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<String> headerProcessing =
           (String text) -> "From Raoul, Mario and Alan: " + text;
    
    UnaryOperator<String> spellCheckerProcessing =
           (String text) -> text.replaceAll("labda", "lambda");
    
    Function<String, String> pipeline =
           headerProcessing.andThen(spellCheckerProcessing);
    
    String result = pipeline.apply("Aren't labdas really sexy?!!");
    

    注:
    UnaryOperator<T>的函数描述符为 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>的函数描述符 () -> T必须返回一个结果为空的supplier

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

    利用Lambda重构之前的代码:

    final static Map<String, Supplier<Product>> 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<Product> p = map.get(name);
         if(p != null) return p.get();
         throw new IllegalArgumentException("No such product " + name);
    } 
    

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

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

    相关文章

      网友评论

          本文标题:利用Lambda重构

          本文链接:https://www.haomeiwen.com/subject/oiygsqtx.html