扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
文章目录阅读完《Java进阶高手》第一章以及第二章;对书中知识进行复盘整理;主要记录:通过行为参数化传递代码
成都创新互联是一家专业的成都网站建设公司,我们专注成都网站设计、成都做网站、网络营销、企业网站建设,卖友情链接,1元广告为企业客户提供一站式建站解决方案,能带给客户新的互联网理念。从网站结构的规划UI设计到用户体验提高,创新互联力求做到尽善尽美。
正文内容:
具体的代码如下所示:
public class Apple {private Integer weight;
private Color color;
public Integer getWeight() { return weight;
}
public void setWeight(Integer weight) { this.weight = weight;
}
public Color getColor() { return color;
}
public void setColor(Color color) { this.color = color;
}
}
enum Color {RED, GREEN
}
public class Filter {public static ListfilterGreenApple(Listinventory) {Listresult = new ArrayList<>();
for (Apple apple : inventory) {if (GREEN.equals(apple.getColor())) {result.add(apple);
}
}
return result;
}
}
我们现在使用枚举类把苹果的颜色进行描述,然后将苹果抽象化为Apple类,包含颜色与重量的属性,最后构造过滤类,在过滤类里面给出具体的过滤绿色苹果的方法filterGreenApple;如果现在需求变了,农民需要过滤红色苹果,那么我们就需要将filterGreenApple方法复制一份,将方法名改为filterRedApple并且将里面的GREEN颜色改为RED;这个样子确实解决了问题,但是很明显,重复代码很多,并不是一个好的解决方法;一个好的解决方法是我们编写类似代码后,尽量对其进行抽象化
2.再展身手:把颜色作为参数在上一版代码中,我们复制filterGreenApple方法完成对红色苹果的过滤,重复了filterGreenApple中大量代码,怎样避免这种问题的发生呢?好的解决方式是将颜色进行参数化,把颜色作为参数传递给过滤的方法,这样子就灵活适应变化了
public static ListfilterApple(Listinventory,Color color) {Listresult = new ArrayList<>();
for (Apple apple : inventory) {if (color.equals(apple.getColor())) {result.add(apple);
}
}
return result;
}
现在解决了颜色筛选的问题,但是农民又跑过来告诉你:要是可以区分苹果的重量就太好了,重的苹果一般是重量大于150克
对于我们来说,这不是问题,我们只需要重新写一个过滤苹果的方法就可以了,我们现在复制filterApple方法,然后把形参color改为weight,然后把筛选条件改为weight大于150就完成了
具体代码如下所示:
public static ListfilterApple(Listinventory, Integer weight) {Listresult = new ArrayList<>();
for (Apple apple : inventory) {if (apple.getWeight() >weight) {result.add(apple);
}
}
return result;
}
-我们可以将重量和颜色都作为参数传递给方法,然后给一个标记,根据标记去判断是通过颜色还是重量过滤苹果
3.第三次尝试:对你能想到的每个属性做筛选我们将所有的苹果属性结合起来,如下所示:
public static ListfilterApple(Listinventory,
Color color, Integer weight, boolean flag) {Listresult = new ArrayList<>();
for (Apple apple : inventory) {if ((flag && color.equals(apple.getColor())) ||
(!flag && apple.getWeight() >weight)) {result.add(apple);
}
}
return result;
}
现在的问题确实已经解决了,但是这个解决方案再差不过。首先客户端看上去糟糕透了,true和false是什么意思?此外,这个解决方案无法应对变化的需求,如果这位农民要求你对苹果的不同属性进行筛选,比如,大小,产地,形状等,该怎样处理?或者农民要求组合属性,做更复杂的查询,比如绿色的重苹果,又该怎么办?如今的情况,我们需要一种更好的解决方式来告诉过滤方法
一种可能的解决方式是对我们的选择标准进行建模:考虑的是苹果,需要根据Apple的某些属性(比如它是绿色的吗?重量超过150克吗?)来返回一个boolean值。我们把它称为谓词(即一个返回boolean值的函数)。让我们定义一个接口来对选择标准建模:
public interface ApplePredicate {boolean test(Apple apple);
}
选择苹果的不同策略,可以将这些标准看作filter方法的不同行为。刚才做的这些和策略设计模式相关,它让我们定义一族算法,把它们封装起来(称为策略),然后再运行的时候选择一个算法。在则这里,算法族就是ApplePredicate,不同的策略就是AppleGreenColorPredicate和AppleHeavyWeightPredicate
public class AppleGreenColorPredicate implements ApplePredicate{@Override
public boolean test(Apple apple) {return GREEN.equals(apple.getColor());
}
}
public class AppleHeavyWeightPredicate implements ApplePredicate {@Override
public boolean test(Apple apple) {return apple.getWeight() >150;
}
}
但是,该怎么利用ApplePredicate的不同实现呢?我们需要filterApple方法接受ApplePredicate对象,对Apple做条件测试。这就是行为参数化:让方法接受多种行为(策略)作为参数,并在内部使用,来完成不同行为
具体代码如下:
public class Filter {public static ListfilterApple(Listinventory,ApplePredicate predicate){ArrayListresult = new ArrayList<>();
for (Apple apple:inventory){if(predicate.test(apple)){result.add(apple);
}
}
return result;
}
}
在这个例子中,唯一重要的代码是test方法的实现,正是它定义了filterApple方法的新行为。但是现在有一个遗憾,由于filterApple方法只接受对象,所以我们必须把代码包裹在ApplePredicate对象里。这种做法类似于内联“传递代码”,因为我们通过实现一个test方法来传递布尔表达式值。再JDK8之后我们可以使用Lambda进一步简化代码,这样子我们就无须定义多个ApplePredicate实现类了,从而去掉不必要的代码
具体代码如下:
public class Main {public static void main(String[] args) {Listresult1 = Filter.filterApple(new ArrayList(), (apple) ->GREEN.equals(apple.getColor()));
Listresult2 = Filter.filterApple(new ArrayList(), (apple) ->apple.getWeight() >150);
}
}
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流