Java行为参数化的演进
首先感谢《java8实战》一书作者某某某。
需求场景:
为一位果农设计一款软件,可以根据果农的需求筛选出相应的水果。
例如:
- 根据颜色筛选
- 根据重量筛选
- 根据颜色和重量筛选
准备工作
定义Apple类
public class Apple
{
String color;
double weight; public Apple(String color,double weight)
{
this.color=color;
this.weight=weight;
}
}
创建苹果库存
List<Apple> inventory=new ArrayList<Apple>()
{
{
add(new Apple("红色",200));
add(new Apple("绿色",80));
add(new Apple("红色",100));
add(new Apple("绿色",210));
add(new Apple("红色",105));
add(new Apple("黄色",180));
add(new Apple("红色",202));
add(new Apple("红色",99));
}
};
阶段1:值参数化 - 为每一种行为定义一个单独的方法
筛选绿苹果
List<Apple> filterGreenApple(List<Apple> inventory)
{
List<Apple> res=new ArrayList<Apple>();
for(Apple apple: inventory)
{
if("绿色".equals(apple.color))
{
res.add(apple);
}
}
return res;
}
筛选红苹果
List<Apple> filterHeavyApple(List<Apple> inventory)
{
List<Apple> res=new ArrayList<Apple>();
for(Apple apple: inventory)
{
if("红色".equals(apple.color))
{
res.add(apple);
}
}
return res;
}
无需多言,这种方式很糟糕,如果再有其它需求,还得定义更多的这种方法,其中大部分的代码都是重复的。
阶段2:值参数化 - 将条件作为参数
根据颜色筛选苹果
List<Apple> filterAppleByColor(List<Apple> inventory,String color)
{
List<Apple> res=new ArrayList<Apple>();
for(Apple apple: inventory)
{
if(color.equals(apple.color))
{
res.add(apple);
}
}
return res;
}
根据重量筛选苹果
List<Apple> filterAppleByWeight(List<Apple> inventory,double weight)
{
List<Apple> res=new ArrayList<Apple>();
for(Apple apple: inventory)
{
if(apple.weight>=weight)
{
res.add(apple);
}
}
return res;
}
这种为每一种属性定义一个方法的写法,一定程度上解决了代码重复的问题。但是,还不够。
阶段3: 值参数化 - 为属性设置标志
根据颜色或重量筛选苹果
List<Apple> filterApple(List<Apple> inventory,String color,boolean flag)
{
List<Apple> res=new ArrayList<Apple>();
for(Apple apple: inventory)
{
if(flag && color.equals(apple.color) || (!flag && apple.weight>=150))
{
res.add(apple);
}
}
return res;
}
这种方式解决了代码重复的问题,但是,当要筛选的属性很多时,需要添加过多的标志参数,使得单个方法中的代码过于复杂,容易出错。
阶段4: 行为参数化 - 使用接口对选择标准建模
定义行为接口
public interface IApplePredicate
{
boolean test(Apple apple);
}
定义筛选绿色苹果的行为类
public class GreenApplePredicate implements IApplePredicate
{
public boolean test(Apple apple)
{
return "绿色".equals(apple.color);
}
}
定义筛选重量大于150克的苹果的行为类
public class HeavyApplePredicate implements IApplePredicate
{
public boolean test(Apple apple)
{
return apple.weight>=150;
}
}
定义筛选方法,接收行为接口的实例作为参数
List<Apple> filterApples(List<Apple> inventory,IApplePredicate predicate)
{
List<Apple> res=new ArrayList<Apple>();
for(Apple apple: inventory)
{
if(predicate.test(apple))
{
res.add(apple);
}
}
return res;
}
筛选的时候,只需要传递行为类对象即可
List<Apple> greenApples=filterApples(inventory,new GreenApplePredicate());
List<Apple> heavyApples=filterApples(inventory,new HeavyApplePredicate());
通过上面这种方式,可以重复使用同一个方法,给她不同的行为来实现不同的目的。
代码结构清晰,很好。但是,必须为每一种行为定义一个类,还是比较繁琐。
阶段5: 行为参数化 - 使用匿名类避免单独定义行为类
不必为每一种行为都定义一个行为类,然后在使用具体方法的时候,传递它的对象。可以使用匿名类实现同样的效果
List<Apple> greenApples=filterApples(inventory,new IApplePredicate()
{
public boolean test(Apple apple)
{
return "绿色".equals(apple.color);
}
});
List<Apple> heavyApples=filterApples(inventory,new IApplePredicate()
{
public boolean test(Apple apple)
{
return apple.weight>=150;
}
});
阶段6: 行为参数化 - 使用lambda表达式代替匿名类
匿名类固然不错,但是,语法很是丑陋。在java8中,可以使用lambda表达式代替匿名类
List<Apple> greenApples=filterApples(inventory,apple->"绿色".equals(apple.color));
List<Apple> heavyApples=filterApples(inventory,apple -> apple.weight>=150);
阶段7: 行为参数化 - 使用泛型扩展行为的适用范围
目前为止,只能用来过滤苹果,如果想过滤梨子,就得重新定义梨的行为接口。
这样很不方便。这时,就可以使用泛型来解决这个问题。
定义泛型行为接口
public interface IPredicate<T>
{
boolean test(T t);
}
将筛选方法改造为泛型方法
<T> List<T> filter(List<T> elements,IPredicate<T> predicate)
{
List<T> res=new ArrayList<>();
for(T t: elements)
{
if(predicate.test(t))
{
res.add(t);
}
}
return res;
}
这样,筛选方法不止适用于苹果,还适用于梨子,甚至数字类型。
至此,使用行为参数化,完美的解决了需求多变的问题。
Java行为参数化的演进的更多相关文章
- 第一章 Java的I/O演进之路
I/O基础入门 Java的I/O演进 第一章 Java的I/O演进之路 1.1 I/O基础入门 1.1.1 Linux网络I/O模型简介 根据UNIX网络编程对I/O模型的分类,UNIX提供了5中I/ ...
- (基础篇 走进javaNIO)第一章-java的i/o演进之路
Java 是由 SUN公司在 1995 年首先发布 的编程语 言和计算平 台.这基础技术 支持最新 的程序 ,包括 实用程序 .游 戏和业 务应用程序 .J ava 在世界各地 的 8.5 亿 多 ...
- Java IO编程全解(一)——Java的I/O演进之路
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7419117.html JDK1.4之前的早期版本,Java对I/O的支持并不完善,开发人员在开发高性能I/O ...
- 性能测试十二:jmeter进阶之java请求参数化
如项目中的ip.端口号之类的,都可以在此代码中定义 public Arguments getDefaultParameters() { // TODO Auto-generated method st ...
- JAVA BIO至NIO演进
主要阐述点: 1.同步/异步 or 阻塞/非阻塞 2.网络模型演进 3.NIO代码示例 一.同步/异步 or 阻塞/非阻塞 同步/异步:核心点在于是否等待结果返回.同步即调用者必须等到结果才返回, ...
- Java Socket Server的演进 (一)
最近在看一些网络服务器的设计, 本文就从起源的角度介绍一下现代网络服务器处理并发连接的思路, 例子就用java提供的API. 1.单线程同步阻塞式服务器及操作系统API 此种是最简单的socket服务 ...
- JAVA分布式架构的演进
系统架构演化历程-初始阶段架构 初始阶段 的小型系统 应用程序.数据库.文件等所有的资源都在一台服务器上通俗称为LAMP 特征:应用程序.数据库.文件等所有的资源都在一台服务器上. 描述:通常服务器操 ...
- eventloop & actor模式 & Java线程模型演进 & Netty线程模型 总结
eventloop的基本概念可以参考:http://www.ruanyifeng.com/blog/2013/10/event_loop.html Eventloop指的是独立于主线程的一条线程,专门 ...
- Java模块化规范之争(转载)
经过近20年的发展,Java语言已成为今日世界上最成功.使用的开发者人数最多的语言之一,Java世界中无数商业的或开源的组织.技术和产品共同构成了一个无比庞大的生态系统. 与大多数开发人员的普遍认知不 ...
随机推荐
- Mybatis-Plus的应用场景及注入SQL原理分析
一.背景 1.1 传统Mybatis的弊端 1.1.1 场景描述 假设有两张表:一张商品表.一张订单表,具体表的字段如下: 现有如下需求: 分别根据id查询商品表和订单表所有信息 根据支付状态和通知状 ...
- CSS变量和浏览器前缀
一.CSS变量 CSS变量是CSS的新特性,大多数浏览器都实现了这个功能,使用CSS变量有利代码复用,而且当我们修改变量值时,所有引用该变量的属性都会发生改变. 定义变量后可以有两种使用方法,第一种时 ...
- nginx负载均衡搭建phpmyadmin加入redis了解session会话原理
myphpadmin项目理解cookie和session 当我们平时上网的时候,在刷新之后或者退出浏览器再次打开浏览器不需要登陆网页了,这就是利用了cookie和session: 环境配置 hostn ...
- Yarn 集群环境 HA 搭建
环境准备 确保主机搭建 HDFS HA 运行环境 步骤一:修改 mapred-site.xml 配置文件 [root@node-01 ~]# cd /root/apps/hadoop-3.2.1/et ...
- shell基础之EOF的用法
一.EOF的用法 EOF是(END Of File)的缩写,表示自定义终止符.既然自定义,那么EOF就不是固定的,可以随意设置别名,在linux按ctrl-d 就代表EOF. EOF一般会配合cat能 ...
- 10.16-17 mailq&mail:显示邮件传输队列&发送邮件
mailq命令 是mail queue(邮件队列)的缩写,它会显示待发送的邮件队列,显示的条目包括邮件队列ID.邮件大小.加入队列时间.邮件发送者和接受者.如果邮件进行最后一次尝试后还没有将邮件投递出 ...
- SystemVerilog MCDF检测器
Monitor:检测DUT的边界信号或者内部信号,并且经过打包整理传送给其他的验证平台的组件(例如checker). 一:大的monitor方案 二:分布式的 两个monitor的比较: 比较下来,选 ...
- SpringBoot基础学习(二) SpringBoot全局配置文件及配置文件属性值注入
全局配置文件 全局配置文件能够对一些默认配置值进行修改.SpringBoot 使用一个名为 application.properties 或者 application.yaml的文件作为全局配置文件, ...
- GO学习-(18) Go语言基础之并发
Go语言基础之并发 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微 ...
- PCB的IPC标准是什么
PCB的IPC标准是什么 印刷电路研究所成立于1957年,有6家印刷电路板制造商.1977年,许多电子公司与工控机联合起来,以实现电子电路的互连和封装.1998年,IPC协会创建了一个"连接 ...