Java8怎么实现通过行为参数传递代码

本篇内容主要讲解“Java8怎么实现通过行为参数传递代码”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java8怎么实现通过行为参数传递代码”吧!

成都创新互联专业为企业提供龙井网站建设、龙井做网站、龙井网站设计、龙井网站制作等企业网站建设、网页设计与制作、龙井企业网站模板建站服务,10余年龙井做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

应对不断变化的需求

通过筛选苹果阐述通过行为参数传递代码

初试牛刀:筛选绿苹果

public static List filterGreenApples(List inventory){
	List result = new ArrayList<>();
	for(Apple apple: inventory){
		if("green".equals(apple.getColor())){
			result.add(apple);
		}
	}
	return result;
}

要是农民想要筛选多种颜色:浅绿色、暗红色、黄色等,这种方法就应付不了了。一个良好的原则是在编写类似的代码之后,尝试将其抽象化。

再展身手:把颜色作为参数

public static List filterApplesByColor(List inventory, String color){
	List result = new ArrayList<>();
	for(Apple apple: inventory){
		if(apple.getColor().equals(color)){
			result.add(apple);
		}
	}
	return result;
}

运用

List greenApples = filterApplesByColor(inventory, "green");
List redApples = filterApplesByColor(inventory, "red");

“要是能区分轻的苹果和重的苹果就太好了。重的苹果一般是重量大于150克。”

public static List filterApplesByWeight(List inventory, int weight){
	List result = new ArrayList<>();
	for(Apple apple: inventory){
		if(apple.getWeight() > weight){
			result.add(apple);
		}
	}
	return result;
}

发现有重复代码,打破DRY(Don't Repeat Yourself)原则

第三次尝试:对你能想到的每个属性做筛选

public static List filterApples(List inventory, int weight, String color, boolean flag){
	List result = new ArrayList();
	for (Apple apple: inventory){
		if ( (flag && apple.getColor().equals(color)) || (!flag && apple.getWeight() > weight) ){
			result.add(apple);
		}
	}
	return result;
}

你可以这么用(但真的很笨拙)

List greenApples = filterApples(inventory, "green", 0, true);
List heavyApples = filterApples(inventory, "", 150, false);

行为参数化

定义一个接口来对选择标准建模:

interface ApplePredicate{
	public boolean test(Apple a);
}

现在你就可以用ApplePredicate的多个实现代表不同的选择标准了

public class AppleWeightPredicate implements ApplePredicate{
	public boolean test(Apple apple){
		return apple.getWeight() > 150; 
	}
}

public class AppleColorPredicate implements ApplePredicate{
	public boolean test(Apple apple){
		return "green".equals(apple.getColor());
	}
}

这里有 策略模式的影子

策略模式:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

该怎么利用ApplePredicate的不同实现呢?你需要filterApples方法接受ApplePredicate对象,对Apple做条件测试。这就是行为参数化:让方法接受多种行为(或战略)作为参数,并在内部使用,来完成不同的行为。

第四次尝试:根据抽象条件筛选

public static List filter(List inventory, ApplePredicate p){
	List result = new ArrayList<>();
	for(Apple apple : inventory){
		if(p.test(apple)){
			result.add(apple);
		}
	}
	return result;
}
传递代码/行为
public class AppleRedAndHeavyPredicate implements ApplePredicate{
	public boolean test(Apple apple){
		return "red".equals(apple.getColor()) 
				&& apple.getWeight() > 150; 
	}
}

List redAndHeavyApples = filter(inventory, new AppleRedAndHeavyPredicate());

filterApples方法的行为取决于你通过ApplePredicate对象传递的代码。换句话说,你把filterApples方法的行为参数化了!

多种行为,一个参数

行为参数化的好处在于你可以把迭代要筛选的集合的逻辑与对集合中每个元素应用的行为区分开来。这样你可以重复使用同一个方法,给它不同的行为来达到不同的目的。

编写灵活的prettyPrintApple方法

编写一个prettyPrintApple方法,它接受一个Apple的List,并可以对它参数化,以多种方式根据苹果生成一个String输出

public static void prettyPrintApple(List inventory, ???){
	for(Apple apple: inventory) {
		String output = ???.???(apple);
		System.out.println(output);
	}
}

首先

public interface AppleFormatter{
	String accept(Apple a);
}

然后

public class AppleFancyFormatter implements AppleFormatter{
	public String accept(Apple apple){
		String characteristic = apple.getWeight() > 150 ? "heavy" : "light";
		return "A " + characteristic + " " + apple.getColor() +" apple";
	}
}

public class AppleSimpleFormatter implements AppleFormatter{
	public String accept(Apple apple){
		return "An apple of " + apple.getWeight() + "g";
	}
}

最后

public static void prettyPrintApple(List inventory, AppleFormatter formatter){
	for(Apple apple: inventory){
		String output = formatter.accept(apple);
		System.out.println(output);
	}
}

运用

prettyPrintApple(inventory, new AppleFancyFormatter());
prettyPrintApple(inventory, new AppleSimpleFormatter());

输出

A light green apple
A heavy red apple
…

An apple of 80g
An apple of 155g
…

对付啰嗦

人们都不愿意用那些很麻烦的功能或概念。目前,当要把新的行为传递给filterApples方法的时候,你不得不声明好几个实现ApplePredicate接口的类,然后实例化好几个只会提到一次的ApplePredicate对象。这真是很啰嗦,很费时间

匿名类

匿名类和你熟悉的Java局部类(块中定义的类)差不多,但匿名类没有名字。它允许你同时声明并实例化一个类。换句话说,它允许你随用随建。

第五次尝试:使用匿名类

List redApples = filterApples(inventory, new ApplePredicate() {
	public boolean test(Apple apple){
		return "red".equals(apple.getColor());
	}
});

但匿名类还是不够好。第一,它往往很笨重,因为它占用了很多空间。第二,很多程序员觉得它用起来很让人费解。

鼓励程序员使用行为参数化模式,通过引入Lambda表达式——一种更简洁的传递代码的方式。

第六次尝试:使用Lambda表达式

List result = filterApples(inventory, (Apple apple) -> "red".equals(apple.getColor()));

第七次尝试:将List类型抽象化

目前,filterApples方法还只适用于Apple。还可以将List类型抽象化,从而超越你眼前要处理的问题。

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

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;
}

List redApples = filter(inventory, (Apple apple) -> "red".equals(apple.getColor()));

List evenNumbers = filter(numbers, (Integer i) -> i % 2 == 0);

真实的例子

用Comparator来排序

// java.util.Comparator
public interface Comparator {
	public int compare(T o1, T o2);
}

inventory.sort(new Comparator() {
	@Override
	public int compare(Apple o1, Apple o2) {
		return o1.getWeight().compareTo(o2.getWeight());
	}
});

inventory.sort((Apple a1, Apple a2) 
		-> a1.getWeight().compareTo(a2.getWeight()));

用Runnable执行代码块

//行为参数化
Thread t = new Thread(new Runnable() {	
	@Override
	public void run() {
		System.out.println("Hello, World!");
	}
});


t = new Thread(()->System.out.println("Hello, World!")) ;

GUI 事件处理

Button button = new Button("Send");
button.setOnAction(new EventHandler() {
	public void handle(ActionEvent event) {
		label.setText("Sent!!");
	}
});

//行为参数化
button.setOnAction((ActionEvent event) -> label.setText("Sent!!"));

到此,相信大家对“Java8怎么实现通过行为参数传递代码”有了更深的了解,不妨来实际操作一番吧!这里是创新互联网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!


新闻标题:Java8怎么实现通过行为参数传递代码
当前地址:http://ybzwz.com/article/pdsgde.html