当前位置: 首页 > news >正文

Java8实战-总结33

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是一个函数接口(除此之外,它还与Predicate<String>具有同样的函数描述)。这意味着不需要声明新的类来实现不同的策略,通过直接传递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方法引入了第二个参数,它是一个Consumer<Customer>类型的参数,与前文定义的makeCustomerHappy的特征保持一致:

public void processCustomer(int id, Consumer<Customer> makeCustomerHappy) { Customer c = Database.getCustomerWithId(id); makeCustomerHappy.accept(c); 
} 

现在,可以很方便地通过传递Lambda表达式,直接插入不同的行为,不再需要继承OnlineBanking类了:

new OnlineBankingLambda().processCustomer(1337, (Customer c) -> System.out.println("Hello " + c.getName()); 
http://www.lryc.cn/news/172355.html

相关文章:

  • Postman 的使用教程(详细)
  • 单元测试 —— JUnit 5 参数化测试
  • uview组件库的安装
  • skywalking入门
  • 【Java 基础篇】Java多线程实现文件上传详解
  • 【计算机基础】VS断点调试,边学边思考
  • BD就业复习第五天
  • ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the ‘ssl‘
  • Qt5开发及实例V2.0-第十二章-Qt多线程
  • Windows 修改系统默认字体
  • 图像处理软件Photoshop 2024 mac新增功能
  • JavaScript之观察者模式
  • 深入了解ln命令:创建硬链接和符号链接的实用指南
  • 虚拟IP技术
  • 蓝桥杯 题库 简单 每日十题 day5
  • 【计算机网络】图解路由器(一)
  • C语言文件的相关操作
  • Java入门级简单定时任务TimerTask
  • Linux命令行教程:使用head和tail命令快速查看文件的开头和结尾
  • [CISCN 2019 初赛]Love Math 通过进制转换执行命令
  • 【Linux】系统编程生产者消费者模型(C++)
  • 【数据结构】图的应用:最小生成树;最短路径;有向无环图描述表达式;拓扑排序;逆拓扑排序;关键路径
  • 大数据驱动业务增长:数据分析和洞察力的新纪元
  • 科技云报道:分布式存储红海中,看天翼云HBlock如何突围?
  • Java高级-动态代理
  • 时序预测 | MATLAB实现POA-CNN-LSTM鹈鹕算法优化卷积长短期记忆神经网络时间序列预测
  • n个不同元素进栈,求出栈元素的【不同排列】以及【排列的数量】?
  • Python中TensorFlow的长短期记忆神经网络(LSTM)、指数移动平均法预测股票市场和可视化...
  • 多线程的学习第二篇
  • git之撤销工作区的修改和版本回溯