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

发布时间:2021-11-17 13:44:38 作者:iii
来源:亿速云 阅读:135

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

应对不断变化的需求

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

初试牛刀:筛选绿苹果

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

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

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

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

运用

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

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

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

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

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

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

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

List<Apple> greenApples = filterApples(inventory, "green", 0, true);
List<Apple> 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<Apple> filter(List<Apple> inventory, ApplePredicate p){
	List<Apple> 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<Apple> redAndHeavyApples = filter(inventory, new AppleRedAndHeavyPredicate());

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

多种行为,一个参数

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

编写灵活的prettyPrintApple方法

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

public static void prettyPrintApple(List<Apple> 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<Apple> 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<Apple> redApples = filterApples(inventory, new ApplePredicate() {
	public boolean test(Apple apple){
		return "red".equals(apple.getColor());
	}
});

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

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

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

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

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

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

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

public static <T> List<T> filter(List<T> list, Predicate<T> p){
	List<T> result = new ArrayList<>();
	for(T e: list){
		if(p.test(e)){
			result.add(e);
		}
	}
	return result;
}

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

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

真实的例子

用Comparator来排序

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

inventory.sort(new Comparator<Apple>() {
	@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<ActionEvent>() {
	public void handle(ActionEvent event) {
		label.setText("Sent!!");
	}
});

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

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

推荐阅读:
  1. 如何实现Python参数传递
  2. vue如何通过滚动行为实现从列表到详情

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Alibaba中Sentinel骨架的示例分析

下一篇:jquery如何获取tr里面有几个td

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》