博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
通过行为参数化传递代码
阅读量:6007 次
发布时间:2019-06-20

本文共 3961 字,大约阅读时间需要 13 分钟。

应对不断变化的需求

在实际的工作中我们会将现实问题抽象成对象并对其进行处理,比如需要对一堆颜色和重量不同的苹果进行过滤分类。

1、苹果实体类

public class Apple {    // 颜色    private String color;    // 重量    private Integer weight;    // Getter and Setter}

2、过滤方法

public static List
filter(List
appleList, String color, int weight) { // 符合条件的苹果集合 List
result = new ArrayList<>(); for (Apple apple : appleList) { // 如果颜色和重量符合条件就存入 if (color.equalsIgnoreCase(apple.getColor()) && weight == apple.getWeight()) { result.add(apple); } } return result; }

通过定制过滤方法,比如后期苹果可能会有其他的属性,是否成熟、产地等。我们可以在过滤方法的入参加上对应的属性并在内部进行判断。这就是通过修改过滤方法来 应对不断变化的需求。但这样有其局限性,如果需求不断地更改,那么就需要重写很多相似的方法。这违背了

DRY(Don't Repeat Yourself)

的软件工程原则。

行为参数化

我们其实可以通过标准建模来定义一个过滤接口,让其比重写很多次过滤方法更好地 应对不断变化的需求

1、建立苹果谓词接口

// predicate:谓词,即一个返回 boolean 值的接口public interface ApplePredicate {    boolean test(Apple apple);}

2、运用策略模式思想来构建具体算法(策略)实现

public class AppleColorPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        // 选出绿色的苹果        return "green".equalsIgnoreCase(apple.getColor());    }}public class AppleWeightPredicate implements ApplePredicate {    @Override    public boolean test(Apple apple) {        // 选出重量大于1的苹果        return 1 < apple.getWeight();    }}

策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

  • 定义了一族算法(业务规则);
  • 封装了每个算法;
  • 这族的算法可互换代替(interchangeable)——

我们可以将 AppleColorPredicateAppleWeightPredicate 看作是 过滤方法 的不同行为,需要 过滤方法 接收 ApplePredicate 对象对苹果进行过滤。这就是 行为参数化:让方法接收多种行为(或策略)作为参数,并在内部使用,来完成不同的行为。

1、修改过滤方法让其能够接收苹果谓词接口对象

public static List
filter(List
appleList, ApplePredicate applePredicate) { // 符合条件的苹果集合 List
result = new ArrayList<>(); for (Apple apple : appleList) { // 如果符合条件就存入 if (applePredicate.test(apple)) { result.add(apple); } } return result; }

2、调用过滤方法进行过滤

public class Main {    public static void main(String[] args) {        List
appleList = new ArrayList<>(); Apple apple = new Apple(); apple.setColor("red"); apple.setWeight(1); appleList.add(apple); apple = new Apple(); apple.setColor("green"); apple.setWeight(2); appleList.add(apple); List
result = filter(appleList, new AppleWeightPredicate()); }}

result 中就会只有重量大于1的苹果集合了。行为参数化 的好处在于我们可以把过滤的逻辑 boolean test() 与应用过滤的行为 public static List<Apple> filter() 解耦。这样在需求不断更改时,只需要新增 ApplePredicate 实现再调用就行。

对付啰嗦

然而按照以上方式使用 ApplePredicate 依然有一个问题,那就是我们还是得不断地新增 ApplePredicate 的实现。本质上只是把重写过滤方法的代价转移到了新增谓词实现上。这个时候我们可以换一个思路出发,使用 匿名类 来随用随建谓词实现。

使用匿名类实现谓词接口

List
result = filter(appleList, new ApplePredicate() { @Override public boolean test(Apple apple) { // 选出绿苹果且重量为2 return "green".equalsIgnoreCase(apple.getColor()) && 2 == apple.getWeight(); } });

现在,我们只需要每次去匿名实现谓词接口就行,然而这样的写让人觉得很臃肿,而且看起来很让人费解。接下来看看 Lambda 是怎么让其变得简洁又友好的。

通过 Lambda 简化匿名实现

List
result = filter(appleList, (Apple apple1) -> "green".equalsIgnoreCase(apple1.getColor()) && 2 == apple1.getWeight());

是不是简洁得有点看不懂了?没关系,先细细品味,下一章我们会详细了解 Lambda。

我们还可以进一步抽象。目前 ApplePredicate 还只适用于苹果,而我想要其他对象进行过滤呢?可以使用泛型来定义需要处理的对象。

1、修改 ApplePredicate 成 Predicate

public interface Predicate
{ boolean test(T t);}

2、修改过滤方法

public static 
List
filter(List
list, Predicate
predicate) { // 符合条件的集合 List
result = new ArrayList<>(); for (T t : list) { // 如果符合条件就存入 if (predicate.test(t)) { result.add(t); } } return result; }

这样我们就能将过滤方法用在其他对象上了。下一章我们会更加深入地理解 Lambda 是什么,能干什么。

Java 8 实战 第二章 通过行为参数化传递代码 读书笔记

这是我第一篇文章,欢迎加入咖啡馆的春天(338147322)。

转载地址:http://nspmx.baihongyu.com/

你可能感兴趣的文章
ios25---图片拉伸
查看>>
php有效防止同一用户多次登录
查看>>
Advanced Installer 安装前卸载旧版本的办法
查看>>
互联网产品研发策略演化
查看>>
(一)研究方法入门
查看>>
三大关系数据库字段值超长的一个有趣对比
查看>>
QT4.8.5+qt-vs-addin-1.1.11+VS2010安装配置和QT工程的新建和加载
查看>>
min宏的学习
查看>>
Qt之HTTP上传/下载
查看>>
故障排除:无法启动、访问或连接到 Azure 虚拟机上运行的应用程序
查看>>
TPshop添加后台菜单
查看>>
最全三大框架整合(使用映射)——applicationContext.xml里面的配置
查看>>
详解派生类构造函数与析构函数
查看>>
linux下获取服务器硬件信息的脚本
查看>>
apache2.4多站点配置
查看>>
[转]微信支付 支付结果通用通知
查看>>
阿里Dubbo疯狂更新,关Spring Cloud什么事?
查看>>
Java提高合集(转载)
查看>>
Android应用程序使用两个LinearLayout编排5个Button控件
查看>>
不等双十二,先入手EasyRecovery!
查看>>