行为参数化
什么是行为参数化?
行为参数化是指可以帮我们处理频繁变更的需求的一种通用的解决方案。
案例:根据重量和颜色筛选苹果
public class Apple {
private String color = "";
private int weight = 0;
public Apple(String color, int weight) {
super();
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Apple [color=" + color + ", weight=" + weight + "]";
}
}
需求:根据重量和颜色去筛选苹果。
设计原则(抽取):
1.针对属性抽取(属性:名词)
2.针对行为抽取(我们发现了一个很有趣的事情,我们都要针对一个【规则】筛选)我们站在更高的维度思考这个问题:针对规则(方法,行为)进行抽取
开发者不提供具体的实现,只对外提供一个抽象方法。
设计:
1.定义filterApple()方法,返回Apple类型的List数组,参数为仓库里的苹果List数组和自定 义的筛选方式。遍历仓库里的苹果,判断是否满足,满足则加入要返回的列表中。
2.定义一个接口,接口中定义用于筛选苹果的抽象方法。
3.自定义类实现该接口,重写方法。
4.调用filterApple方法进行测试。
public class Utils {
static ArrayList<Apple> inventory = new ArrayList<>();
static {
inventory.add(new Apple("绿色", 10));
inventory.add(new Apple("绿色", 11));
inventory.add(new Apple("青色", 10));
inventory.add(new Apple("青色", 11));
inventory.add(new Apple("青色", 12));
}
public interface ApplePredicate{
public boolean test(Apple apple);
}
//自定义实现类实现接口,定义筛选规则
public class AppleColorAndWeightPredicate implements ApplePredicate{
public boolean test(Apple apple) {
return apple.getColor().equals("青色") && apple.getWeight()>10;
}
}
public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate applePredicate){
ArrayList<Apple> arrayList = new ArrayList<Apple>();
for (Apple apple : inventory) {
if (applePredicate.test(apple)) {
arrayList.add(apple);
}
}
return arrayList;
}
@Test
public void testfilterApples() {
List<Apple> filterApples = filterApples(inventory, new AppleColorAndWeightPredicate());
System.out.println(filterApples);
}
}
继续改进:使用匿名内部类的方式解决定义多个类导致的模板代码多的问题:
@Test
public void testfilterApples() {
List<Apple> filterApples = filterApples(inventory, new AppleColorAndWeightPredicate(){
@Override
public boolean test(Apple apple) {
return apple.getColor().equals("青色")&&apple.getWeight()>10;
}
});
System.out.println(filterApples);
}
继续改进:使用lambda表达式解决代码冗余问题;
@Test
public void testfilterApples() {
List<Apple> filterApples = filterApples(inventory, (Apple apple)->{
return apple.getColor().equals("青色")&&apple.getWeight()>10;
});
System.out.println(filterApples);
}
需求:我不再只想筛选苹果了,或者说水果,我想筛选任何的东西everything
最终改进:使用泛型设计弹性系统。
//下面这个自定义接口也可以不自己定义,直接导包import java.util.function.Predicate;源码已经定义过
public interface Predicate<T>{
public boolean test(T t);
}
public static <T> List<T> filter(List<T> list, Predicate<T> predicate){
ArrayList<T> arrayList = new ArrayList<>();
for (T t : list) {
if(predicate.test(t)) {
arrayList.add(t);
}
}
return arrayList;
}
@Test
public void testFilter() {
List<Integer> list = filter(Arrays.asList(1,2,3,4,5,6,7,8), (Integer i)->{
return i%2==0;
});
System.out.println(list);
}
通过这个案例,我们能知道JDK人员是如何思考问题的,泛型是给做底层设计人员来用的
关于Lambda表达式与函数式接口的相关内容,可以参考我之前的文章: