行为参数化就是能够帮助你处理频繁变动的需求的一种软件开发模式。一言以弊之,它意味着拿出一个代码块,把它准备好却不去执行它。这个代码块之后能够被你的程序的其余部分调用,这意味着你能够推迟这块代码的执行。算法
1、应对不断变化的需求app
一、初试牛刀:筛选绿苹果code
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); } }
二、再展身手:把颜色做为参数对象
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; }
三、第三次尝试:对你能想到的每一个属性作筛选接口
public static List<Apple> filterApplesByColor(List<Apple> inventory, String color,int weight,boolean flag){ List<Apple> result = new ArrayList<>(); for(Apple apple: inventory){ if((flag &&apple.getColor().equals(color))|| (!flag &&apple.getWeight()>weight)){ result.add(apple); } } return result; }
2、行为参数化开发
一、定义一个接口来对选择标准建模(即定义一族算法),把它们封装起来(称为“策略”),而后再运行时选择一个算法。get
二、参数化:让方法接收多种行为(或战略)做为参数,并在内部使用,来完成不一样的行为。test
三、第四次尝试:根据抽象条件筛选软件
(1)传递代码行为List
public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p){ List<Apple> result = new ArrayList<>(); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); } } return result; }
注: 正是test方法定义了filterApples方法的新行为,但使人遗憾的是,因为filterApples方法只能接收对象,因此你必须把代码包裹在ApplePredicate对象里。你的作法就相似于在内联“传递代码”,由于你是经过实现了test方法的对象来传递布尔表达式的。
(2)多种行为,一个参数 正如咱们先前解释的那样,行为参数化的好处在于你能够把迭代要筛选的集合逻辑与对集合中每一个元素应用的行为区分开来。
3、对付啰嗦
一、匿名类
二、第五次尝试:使用匿名类
List<Apple> redApples2 = filter(inventory, new ApplePredicate() { public boolean test(Apple a){ return a.getColor().equals("red"); } }); System.out.println(redApples2); }
三、第六次尝试:使用Lambda表达式
List<Apple> result = filterApples(inventory,(Apple apple)) -> "red".equles(apple.getColor())
四、第七次尝试:将List类型抽象化
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; }