使用lambda表达式重构策略模式

1.策略模式

策略模式代表了解决一类算法的通用解决方案,你可以在运行时选择使用哪种方案。你可以将这一模式应用到更广泛的领域,比如使用不同的标准来验证输入的有效性,使用不同的方式来分析或者格式化输入。

策略模式包含三部分内容,如图所示。 

  • 一个代表某个算法的接口(它是策略模式的接口) 。 
  •  一个或多个该接口的具体实现,它们代表了算法的多种实现(比如,实体类 ConcreteStrategyA 或者 ConcreteStrategyB) 
  • 一个或多个使用策略对象的客户。

假设你希望验证输入的内容是否根据标准进行了恰当的格式化 (比如只包含小写字母或数字) 。你可以从定义一个验证文本(以 String 的形式表示)的接口入手:

interface ValidationStrategy {
	public boolean execute(String s);
}

其次,你定义了该接口的一个或多个具体实现: 

static private class IsAllLowerCase implements ValidationStrategy {

	@Override
	public boolean execute(String s) {
		return s.matches("[a-z]+");
	}

}

	static private class IsNumeric implements ValidationStrategy {

	@Override
	public boolean execute(String s) {
		return s.matches("\\d+");
	}
}

之后,你就可以在你的程序中使用这些略有差异的验证策略了:

static private class Validator {
	private final ValidationStrategy strategy;

	public Validator(ValidationStrategy v) {
		this.strategy = v;
	}

	public boolean validate(String s) {
		return strategy.execute(s);
	}
}

Validator v1 = new Validator(new IsNumeric());
System.out.println(v1.validate("bbbb"));
Validator v2 = new Validator(new IsAllLowerCase());
System.out.println(v2.validate("cccc"));

接下来使用Lambda表达式重构上述代码:

到现在为止,你应该已经意识到 ValidationStrategy 是一个函数接口了(除此之外,它还与 Predicate<String> 具有同样的函数描述) 。这意味着我们不需要声明新的类来实现不同的策略,通过直接传递Lambda表达式就能达到同样的目的,并且还更简洁: 

// 使用lambda
Validator v3 = new Validator((String s) -> s.matches("\\d+"));
System.out.println(v3.validate("bbbb"));
Validator v4 = new Validator((String s) -> s.matches("[a-z]+"));
System.out.println(v4.validate("cccc"));
正如你看到的,Lambda表达式避免了采用策略设计模式时僵化的模板代码。如果你仔细分析一下个中缘由,可能会发现,Lambda表达式实际已经对部分代码(或策略)进行了封装,而这就是创建策略设计模式的初衷。因此,强烈建议对类似的问题,你应该尽量使用Lambda表达式来解决。 

猜你喜欢

转载自blog.csdn.net/u013230189/article/details/80865072