扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
本篇内容介绍了“java8怎么通过行为参数化传递代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
成都创新互联公司服务项目包括监利网站建设、监利网站制作、监利网页制作以及监利网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,监利网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到监利省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
编写能够应对变化的需求的代码并不容易。让我们来看一个例子,我们会逐步改进这个例子,
以展示一些让代码更灵活的最佳做法。就农场库存程序而言,你必须实现一个从列表中筛选绿苹
果的功能。听起来很简单吧?
第一个解决方案可能是下面这样的:
/** *筛选绿苹果 * @param inventory 苹果仓库 * @return public static ListfilterGreenApples(List inventory){ List result = new ArrayList<>(); for(Apple apple:inventory){ if ("green".equals(apple.getColor())){ result.add(apple); } } return
现在农民改主意了,他还想要筛选红苹果。
你该怎么做呢?简单的解决办法就是复制这个方法,把名字改成 filterRedApples ,然后更改
if 条件来匹配红苹果。然而,要是农民想要筛选多种颜色:浅绿色、暗红色、黄色等,这种方法
就应付不了了。一个良好的原则是在编写类似的代码之后,尝试将其抽象化。
/** * 把颜色参数化,应对颜色变化的需求 * @param inventory * @param color * @return public static ListfilterApplesByColor(List inventory, String color) { List result = new ArrayList (); for (Apple apple: inventory){ if ( apple.getColor().equals(color) ) { result.add(apple); } } return
这时,农民不断提新需求,按重量刷选,按装量和颜色筛选,于是你不断修改代码,粘贴复制,
一种把所有属性结合起来的笨拙尝试如下所示:
public static ListfilterApples(List inventory, String color, int weight, boolean flag) { List result = new ArrayList (); for (Apple apple: inventory){ if ( (flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight) ){ result.add(apple); } } return
这个解决方案再差不过了。首先,客户端代码看上去糟透了。 true 和 false 是什么意思?此
外,这个解决方案还是不能很好地应对变化的需求。如果这位农民要求你对苹果的不同属性做筛
选,比如大小、形状、产地等,又怎么办?而且,如果农民要求你组合属性,做更复杂的查询,
比如绿色的重苹果,又该怎么办?你会有好多个重复的 filter 方法,或一个巨大的非常复杂的
方法。
但如今这种情况下,你需要一种更好的方式,来把
苹果的选择标准告诉你的 filterApples 方法
你需要一种比添加很多参数更好的方法来应对变化的需求。让
我们后退一步来看看更高层次的抽象。
一种可能的解决方案是对你的选择标准建模:你考虑的
是苹果,需要根据 Apple 的某些属性(比如它是绿色的吗?重量超过150克吗?)来返回一个
boolean 值。我们把它称为谓词(即一个返回 boolean 值的函数)。让我们定义一个接口来对选
择标准建模:
public interface ApplePredicate boolean
现在你就可以用 ApplePredicate 的多个实现代表不同的选择标准了.
/** * 选出重苹果的实现类 * * @author itguang * @create public class AppleHeavyWeightPredicate implements ApplePredicate{ @Override public boolean test(Apple apple) { return apple.getWeight()>150; } }
/** * 选出绿苹果的实现类 * * @author itguang * @create public class AppleGreenColorPredicate implements ApplePredicate @Override public boolean test(Apple apple) { return "green".equals(apple.getColor()); } }
你可以把这些实现类看做filter方法的不同行为,刚做的这些和策略设计模式相关,他让你定义一簇算法(称为 :策略),然后在运行时选择一个算法。在这里,
算法族就是 ApplePredicate ,不同的策略就是 AppleHeavyWeightPredicate 和 AppleGreen-ColorPredicate 。
但是,该怎么利用 ApplePredicate 的不同实现呢?
你需要 filterApples 方法接受
ApplePredicate 对象,对 Apple 做条件测试。这就是行为参数化:让方法接受多种行为(或战
略)作为参数,并在内部使用,来完成不同的行为。
filter 方法看起来是这样的:
“`java /** * 根据抽象条件进行筛选 * @param inventory * @param applePredicate * @return */ public static List filter(List inventory, ApplePredicate applePredicate){ ArrayList list = new ArrayList<>(); for (Apple apple:list){ if(applePredicate.test(apple)){ list.add(apple); } } return list;}
“`
* 1. 传递代码/行为:
这里值得停下来小小地庆祝一下。这段代码比我们第一次尝试的时候灵活多了,读起来、用
起来也更容易!现在你可以创建不同的 ApplePredicate 对象,并将它们传递给 filterApples
方法.
你已经做成了一件很酷的事: filterApples 方法的行为取决于你通过 ApplePredicate 对象传递的代码。换句话说,你把 filterApples 方法的行为参数化了!
请注意,在上一个例子中,唯一重要的代码是 test 方法的实现,如图2-2所示;正是它定义
了 filterApples 方法的新行为。但令人遗憾的是,由于该 filterApples 方法只能接受对象,
所以你必须把代码包裹在 ApplePredicate 对象里。你的做法就类似于在内联“传递代码”,因
为你是通过一个实现了 test 方法的对象来传递布尔表达式的
这就是说行为参数化是一个有用的概念的原因。你应该把它放进你的工具箱里,用来编写灵
活的API
到此,我们觉得已经做的很好了,我们使用行为参数化解决了一些棘手的问题.
但是,目前来说,当要把新的行为传递给
filterApples 方法的时候,你不得不声明好几个实现 ApplePredicate 接口的类,然后实例化
好几个只会提到一次的 ApplePredicate 对象。
Java有一个机制称为匿名类,它可以让你同时
声明和实例化一个类。它可以帮助你进一步改善代码,让它变得更简洁。但这也不完全令人满意。它往往很笨重,因为它占用了很多空间。
“`java //将 List 类型抽象化 public static List filter(List list, Predicate p){ List result = new ArrayList<>(); for(T e: list){ if(p.test(e)){ result.add(e); } } return result; }
/** * 用Lambda表达式对仓库的苹果按重量升序排序 */ @Test public void test3(){ Listinventory = initInventory(); inventory.sort((Apple o1,Apple o2)->o1.getWeight().compareTo(o2.getWeight())); System.out.println(inventory); }
现在暂时不用担心这个新语法,下一章我们会详细讲解如何编写和使用Lambda表达式。
线程就像是轻量级的进程:它们自己执行一个代码块。但是,怎么才能告诉线程要执行哪块
代码呢?多个线程可能会运行不同的代码。我们需要一种方式来代表稍候执行的一段代码。在
Java里,你可以使用 Runnable 接口表示一个要执行的代码块。请注意,代码不会返回任何结果
(即 void ):
// java.lang.Runnable public interface Runnable{ public void run(); }
你可以像下面这样,使用这个接口创建执行不同行为的线程:
Thread t = new Thread(new Runnable() { public void run(){ System.out.println("Hello world"); } });
用Lambda表达式的话,看起来是这样:
Thread t = new Thread(() -> System.out.println("Hello world"));
“java8怎么通过行为参数化传递代码”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流