看不懂?没关系。我们先来看一个体现传值局限性的场景吧,上代码:
- List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
- public int sumAll(List<Integer> numbers) {
- int total = 0;
- for (int number : numbers) {
- total += number;
- }
- return total;
- }
sumAll算法很简单,完成的是将List中所有元素相加。某一天如果我们需要增加一个对List中所有偶数求和的方法sumAllEven,如下:
- public int sumAllEven(List<Integer> numbers) {
- int total = 0;
- for (int number : numbers) {
- if (number % 2 == 0) {
- total += number;
- }
- }
- return total;
- }
又有一天,我们需要增加第三个方法:对List中所有大于3的元素求和,那是不是继续加下面的方法呢?
- public int sumAllEven(List<Integer> numbers) {
- int total = 0;
- for (int number : numbers) {
- if (number > 3) {
- total += number;
- }
- }
- return total;
- }
比较这三个方法,我们发现了一个很明显的“代码臭味”—— 代码重复(详情参考《重构》),三个方法的唯一区别在于if判断这一行代码。如果脱离这里的上下文,我们会怎么做呢?我首先会先想到利用策略模式重构代码如下:
- public interface Strategy {
- public boolean test(int num);
- }
- public class SumAllStrategy implements Strategy {
- public boolean test(int num) {
- return true;
- }
- }
- public class SumAllEvenStrategy implements Strategy {
- public boolean test(int num) {
- return num % 2 == 0;
- }
- }
- public class ContextClass {
- private Strategy stragegy = null;
- private final static Strategy DEFAULT_STRATEGY = new SumAllStrategy();
- public ContextClass() {
- this(null);
- }
- public ContextClass(Stragegy stragegy) {
- if(strategy != null) {
- this.strategy = strategy;
- }
- else {
- this.strategy = DEFAULT_STRATEGY;
- }
- }
- public int sumAll(List<Integer> numbers) {
- int total = 0;
- for (int number : numbers) {
- if (strategy.test(number)) {
- total += number;
- }
- }
- return total;
- }
- }
- // 调用
- ContextClass context = new ContextClass();
- context.sumAll(numbers);
设计模式在这里发挥了作用,OO特性还是蛮强大的!但这是唯一的解决方案吗(当然不考虑用其他设计模式来解决,因为都是OO范畴!)?当然有,该轮到Java 8 Lambda表达式中的谓词(Predicate)发挥作用了!
- public int sumAll(List<Integer> numbers, Predicate<Integer> p) {
- int total = 0;
- for (int number : numbers) {
- if (p.test(number)) {
- total += number;
- }
- }
- return total;
- }
- sumAll(numbers, n -> true);
- sumAll(numbers, n -> n % 2 == 0);
- sumAll(numbers, n -> n > 3);
代码是不是比上面简洁很多了?语义应该也很明确,就不多解释了,如果实在看不懂,请参考我的另外一篇文章:http://www.cnblogs.com/feichexia/archive/2012/11/15/Java8_LambdaExpression.html 从这里也可以看出未引入Lambda表达式之前的Java代码的冗长(Java这点被很多人诟病)。