做招工的网站排名,一般注册公司要多少钱,网站建设的目标人群是什么,杭州产品推广服务公司Java8实战-总结33 重构、测试和调试使用 Lambda 重构面向对象的设计模式策略模式模板方法 重构、测试和调试
使用 Lambda 重构面向对象的设计模式
新的语言特性常常让现存的编程模式或设计黯然失色。比如#xff0c; Java 5中引入了for-each循环#xff0c;由于它的稳健性和… Java8实战-总结33 重构、测试和调试使用 Lambda 重构面向对象的设计模式策略模式模板方法 重构、测试和调试
使用 Lambda 重构面向对象的设计模式
新的语言特性常常让现存的编程模式或设计黯然失色。比如 Java 5中引入了for-each循环由于它的稳健性和简洁性已经替代了很多显式使用迭代器的情形。Java 7中推出的菱形操作符让大家在创建实例时无需显式使用泛型一定程度上推动了Java程序员们采用类型接口type interface进行程序设计。
对设计经验的归纳总结被称为设计模式。设计软件时可以复用这些方式方法来解决一些常见问题。这看起来像传统建筑工程师的工作方式对典型的场景比如悬挂桥、拱桥等都定义有可重用的解决方案。例如访问者模式常用于分离程序的算法和它的操作对象。单例模式一般用于限制类的实例化仅生成一份对象。
Lambda表达式为程序员的工具箱又新添了一件利器。它们为解决传统设计模式所面对的问题提供了新的解决方案不但如此采用这些方案往往更高效、更简单。使用Lambda表达式后很多现存的略显臃肿的面向对象设计模式能够用更精简的方式实现了。下面会针对五个设计模式展开讨论分别是
策略模式模板方法观察者模式责任链模式工厂模式
策略模式
策略模式代表了解决一类算法的通用解决方案可以在运行时选择使用哪种方案。例如使用不同的条件比如苹果的重量或者颜色来筛选库存中的苹果。可以将这一模式应用到更广泛的领域比如使用不同的标准来验证输入的有效性使用不同的方式来分析或者格式化输入。 策略模式包含三部分内容
一个代表某个算法的接口它是策略模式的接口。一个或多个该接口的具体实现它们代表了算法的多种实现比如实体类ConcreteStrategyA或者ConcreteStrategyB。一个或多个使用策略对象的客户。 假设希望验证输入的内容是否根据标准进行了恰当的格式化比如只包含小写字母或数字。可以从定义一个验证文本以String的形式表示的接口入手
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); //返回false
Validator lowerCaseValidator new Validator(new IsAllLowerCase());
boolean b2 lowerCaseValidator.validate(bbbb); //返回true使用Lambda表达式 ValidationStrategy是一个函数接口除此之外它还与PredicateString具有同样的函数描述。这意味着不需要声明新的类来实现不同的策略通过直接传递Lambda表达式就能达到同样的目的并且还更简洁
Validator numericValidator new Validator((String s) - s.matches([a-z]));
boolean b1 numericValidator.validate(aaaa); //直接传递Lambda表达式
Validator lowerCaseValidator new Validator((String s) - s.matches(\\d)); //直接传递Lambda表达式
boolean b2 lowerCaseValidator.validate(bbbb); Lambda表达式避免了采用策略设计模式时僵化的模板代码。如果仔细分析一下个中缘由会发现Lambda表达式实际已经对部分代码或策略进行了封装而这就是创建策略设计模式的初衷。因此建议对类似的问题应该尽量使用Lambda表达式来解决。
模板方法
如果需要采用某个算法的框架同时又希望有一定的灵活度能对它的某些部分进行改进那么采用模板方法设计模式是比较通用的方案。换句话说模板方法模式在你“希望使用这个算法但是需要对其中的某些行进行改进才能达到希望的效果”时是非常有用的。
从一个例子着手看看这个模式是如何工作的。假设需要编写一个简单的在线银行应用。通常用户需要输入一个用户账户之后应用才能从银行的数据库中得到用户的详细信息最终完成一些让用户满意的操作。不同分行的在线银行应用让客户满意的方式可能还略有不同比如给客户的账户发放红利或者仅仅是少发送一些推广文件。可能通过下面的抽象类方式来实现在线银行应用
abstract class OnlineBanking { public void processCustomer(int id){ Customer c Database.getCustomerWithId(id); makeCustomerHappy(c); }abstract void makeCustomerHappy(Customer c);
} processCustomer方法搭建了在线银行算法的框架获取客户提供的ID然后提供服务让用户满意。不同的支行可以通过继承OnlineBanking类对该方法提供差异化的实现。
使用Lambda表达式 使用Lambda表达式同样也可以解决这些问题创建算法框架让具体的实现插入某些部分。你想要插入的不同算法组件可以通过Lambda表达式或者方法引用的方式实现。
这里向processCustomer方法引入了第二个参数它是一个ConsumerCustomer类型的参数与前文定义的makeCustomerHappy的特征保持一致
public void processCustomer(int id, ConsumerCustomer makeCustomerHappy) { Customer c Database.getCustomerWithId(id); makeCustomerHappy.accept(c);
} 现在可以很方便地通过传递Lambda表达式直接插入不同的行为不再需要继承OnlineBanking类了
new OnlineBankingLambda().processCustomer(1337, (Customer c) - System.out.println(Hello c.getName());