如何应对不断变化的需求?
理想状态下:应该把工作量降到最低,此外类似的新功能实现起来还应该很简单,而且易于长期维护。
行为参数化:
就是可以帮助你处理频繁变更的需求的一种软件开发模式。这意味着,你单独控制一段代码,这段代码将作为一个函数或者方法的参数,在你需要的时候调用这段代码去执行需要完成的任务。这样这个方法或者函数的行为就基于这段代码被参数化了。
2.1 应对不断变化的需求
注意DRY(Don't Repeat Yourself)的软件工程原则:当你重复的使用某段代码时,如果你需要修改某个部分,你讲需要修改所有代码的这个部分,过于麻烦。
2.2 行为参数化
1.传递代码
2.多种行为,一个参数
行为参数化的好处在于你可以把迭代要筛选的集合的逻辑与对集合中每个元素应用的行为区分开来。这样你可以重复使用 一种方法,从而实现不同的行为。
示例代码:
//定义筛选因子
interface ApplePredicate{
public boolean test(Apple a);
}
static class AppleWeightPredicate implements ApplePredicate{
public boolean test(Apple apple){
return apple.getWeight() > 150;
}
}
static class AppleColorPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "green".equals(apple.getColor());
}
}
static class AppleRedAndHeavyPredicate implements ApplePredicate{
public boolean test(Apple apple){
return "red".equals(apple.getColor())
&& apple.getWeight() > 150;
}
}
//定义筛选类
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;
}
//使用:
/*代码参数化*/
// [Apple{color='green', weight=80}, Apple{color='green', weight=155}]
List<Apple> greenApples2 = filter(inventory, new AppleColorPredicate());
System.out.println(greenApples2);
// [Apple{color='green', weight=155}]
List<Apple> heavyApples = filter(inventory, new AppleWeightPredicate());
System.out.println(heavyApples);
// []
List<Apple> redAndHeavyApples = filter(inventory, new
AppleRedAndHeavyPredicate());
System.out.println(redAndHeavyApples);
行为抽象出来,让代码适应需求的变化而变化,但是这个过程太啰嗦,需要定义太多只要实例化一次的类,所以有了以下的改进:
2.3 对付啰嗦
2.3.1 匿名类
匿名类类似于使用的局部类,但是匿名类没有名字,可以声明的同时实例化,随时建立,随时使用。
2.3.2 匿名类的使用
匿名类有缺点:
① 很笨重,占用很多空间
② 用起来让人费解
package chap2;
public class MeaningOfThis
{
public final int value = 4;
public void doIt()
{
int value = 6;
Runnable r = new Runnable(){
public final int value = 5;
public void run(){
int value = 10;
System.out.println(this.value);
}
};
r.run();
}
public static void main(String...args)
{
MeaningOfThis m = new MeaningOfThis();
m.doIt();
}
}
答案为:5
因为this.value this指的是匿名类
2.3.3 第六次尝试:使用 Lambda 表达式
示例代码:
List<Apple> redApples3 = filter(inventory,(Apple apple)->"red".equals(apple.color()));
System.out.println(redApples3);
2.3.4 第七次尝试:将 List 类型抽象化
采用泛型:
public interface Predicate<T>{
boolean test(T t);
}
public static<T> List<T> filter(List<T> inventory,Predicate<T> p){
List<T> result = new ArrayList<T>();
for(T t:inventory){
if(p.test(t)){
result.add(t);
}
}
return result;
}
}
public static void main(String...args){
List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
new Apple(155, "green"),
new Apple(120, "red"));
List<Apple> redApples = filter(inventory,
(Apple apple)->"red".equals(apple.getColor));
}
2.5 小结
行为参数化就是一个方法接受不同的行为作为参数,并在内部使用他们,以执行不同的任务。