拿出一个代码块,把它准备好不去执行它。这个代码块可以被程序的其他部分调用,推迟这段代码块的执行,可以将它作为参数传递给另一个方法,然后再去执行它,这个方法的行为就基于那个代码块被参数化了。
生活场景:
比如人们的工作,领导安排一个更新SQL脚本的任务,我们去执行并完成,executeSQlTask,过了一会儿又来个新需求,听需求会议,executeReqirementTask…
那么应对这种复杂的变化,我们可以提供一个方法:executeTask ,接受不同的行为参数传递进来,收到后去执行不同的任务
通过一个代码的演变过程来展示它的使用
我们可以拿电商中的交易订单来举例说明这个行为参数化在JAVA8中实现的优势
查询我的订单:
菜鸟版:估计没人会这么写
public static List filterMyOrder(List orderlist){
List resultList = new ArrayList();
for (Order order :orderlist ) {
if ("1001".equals(order.getUser().getUserId()) ){
resultList.add(order);
}
}
return resultList;
}
再展身手:将userId作为参数传进来,增加了灵活性
public static List filterOrderByUser(List orderlist,String userId){
List resultList = new ArrayList();
for (Order order :orderlist ) {
if (userId.equals(order.getUser().getUserId()) ){
resultList.add(order);
}
}
return resultList;
}
看起来太简单了,此时可以灵活的查询任何一个用户的订单
此时又增加了新的需求点,查询用户今日的订单,于是乎增加个根据date来查询的方法满足当下的需求
public static List filterOrderByDate(List orderlist,String orderDate){
List resultList = new ArrayList();
for (Order order :orderlist ) {
if (orderDate.equals(order.getOrderDate()) ){
resultList.add(order);
}
}
return resultList;
}
此时代码看起来冗余量很多,对orderList的遍历很是消耗性能的,并且打破了DRY(Don’t Repeat Yourself)这一软件工程原则,于是乎:
public static List filterOrder(List orderlist,String userId,String orderDate,boolean flag){
List resultList = new ArrayList();
for (Order order :orderlist ) {
if ( (flag && userId.equals(order.getUser().getUserId())||
(!flag && orderDate.equals(order.getOrderDate())) ){
resultList.add(order);
}
}
return resultList;
}
//可以这么实现,但是怎么看怎么蹩脚
List resultList = filterOrder(orderlist,"1001","",true);
List resultList = filterOrder(orderlist,"","2019-06-23",false);
第三次尝试,可以对这些order的条件进行建模,
定义一个条件筛选的接口,写实现类
OrderPredicate
OrderUserPredicate
OrderDatePredicate
public interface OrderPredicate{
public boolean test(Order order);
}
public OrderUserPredicate implements OrderPredicate{
public boolean test(Order order){
return "1001".equals(order.getUser().getUserId())
}
}
public OrderDatePredicate implements OrderPredicate{
public boolean test(Order order){
return "2019-06-23".equals(order.getOrderDate())
}
}
通过这种策略初步实现了行为参数化,只需要把OrderPredicate传递给filterOrder方法做条件筛选
第四次尝试:根据抽象条件筛选
public static List filterOrder(List orderlist,OrderPredicate orderPredicate){
List resultList = new ArrayList();
for (Order order :orderlist ) {
if ( orderPredicate.test(order)){
resultList.add(order);
}
}
return resultList;
}
//这里值得停下来小小地庆祝一下。这段代码比我们第一次尝试的时候灵活多了,读起来、用
//起来也更容易!
此时如果在增加新的筛选需求,只需要增加一个新的筛选策略即可,费了这么大劲儿,那么还能不能更加简便些呢?
第五次尝试:Java提供了匿名内部类
List myOrderList = filterOrder(orderlist,new OrderPredicate(){
public boolean test(Order order){
return "1001".equals(order.getUser().getUserId())
}
})
看起来不啰嗦了,总之,啰嗦就是不好;编写和维护啰嗦的代码也很耗时。
第六次尝试:lambda表达式
List myOrderList = filterOrder(orderlist,(Order order) -> "1001".equals(order.getUser().getUserId()))
这一行代码看起来就更酷了,并且理解起来更符合需求的陈述:筛选我(userid=“1001”)的订单列表
可以应对不断变化的需求
使得代码理解起来更符合需求的陈述
简洁不啰嗦