使用Lambda表达式实现策略模式
看下面这个例子
public class Asset {
public enum AssetType { BOND, STOCK };
private final AssetType type;
private final int value;
public Asset(final AssetType assetType, final int assetValue) {
type = assetType;
value = assetValue;
}
public AssetType getType() { return type; }
public int getValue() { return value; }
}
上面这个类是资产类,资产类有一个枚举代表两种资产类型,一种是STOCK一种是BOND类型,资产类有两个属性一个是type用于代表资产类型,一个是value代表资产的价值
现在有这样一个需求要计算所有资产的总价值,我们通常会这样写
public static int totalAssetValues(final List<Asset> assets) {
return assets.stream().mapToInt(Asset::getValue).sum();
}
但是现在有一个新的需求,要计算Bond类型的资产总值,我们通常会复制上面的代码然后修改成下面这样的代码
public static int totalBondValues(final List<Asset> assets) {
return assets.stream().filter(asset -> asset.getType() == Asset.AssetType.BOND).mapToInt(Asset::getValue).sum();
}
这样写的话我们又犯了一个面向实现的错误,而设计模式提倡面向组合,如果需求再次发生更改要计算Stock类型的资产我们又要增加新的方法。我们的代码不利于扩展,经过分析我们发现上面的两个需求都涉及到以下三点:1.如何遍历,2.计算什么,3.如何计算.而如何遍历集合不会变化,如何计算也不会变化,而对什么类型的资产计算往往是变化地方.为此我们可以将代码修改成如下
public static int totalAssetValues(final List<Asset> assets, final Predicate<Asset> assetPredicate) {
return assets.stream().filter(assetPredicate).mapToInt(Asset::getValue).sum();
}
在调用的时候我们这样调用
System.out.println(totalAssetValues(assets, asset -> true));