# 策略模式&lambda重构策略模式

#### 二、策略模式

CalculateStrategy是策略接口，有一个待实现的calculate方法，计算邮费，根据传入的包裹重量，返回计算好的邮费。JdCalculateStrategy、StoCalculateStrategy、YtoCalculateStrategy分别为京东、申通、圆通不同的计算邮费方式，实现了CalculateStrategy接口的calculate方法。

CalculateStrategy策略接口代码如下：

```public interface CalculateStrategy {
Double calculate(Integer weight);
}```

JdCalculateStrategy类：

```public class JdCalculateStrategy implements CalculateStrategy {
@Override
public Double calculate(Integer weight) {
return 10 + weight * 1.2;
}
}```

StoCalculateStrategy类：

```public class StoCalculateStrategy implements CalculateStrategy {
@Override
public Double calculate(Integer weight) {
return 12 + weight * 0.8;
}
}```

YtoCalculateStrategy类：

```public class YtoCalculateStrategy implements CalculateStrategy {
@Override
public Double calculate(Integer weight) {
return 8 + weight * 1.5;
}
}```

```public class CalculateContext {
//持有策略接口
private CalculateStrategy calculateStrategy;
public void setCalculateStrategy(CalculateStrategy calculateStrategy) {
this.calculateStrategy = calculateStrategy;
}
public Double calculate(Integer weigth) {
return calculateStrategy.calculate(weigth);
}
}```

```public class Client {
public static void main(String[] args) {
Integer weight = 15;
CalculateContext context = new CalculateContext();
CalculateStrategy calculateStrategy = new JdCalculateStrategy();
context.setCalculateStrategy(calculateStrategy);
System.out.println("运行时指定策略，计算邮费如下：" + context.calculate(weight));
}
}```

#### 三、lambda重构策略模式

```@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}```

```public enum ParcelCompanyEnum {
ZTO("中通快递"),YTO("圆通快递"),STO("申通快递"),JD("京东快递");
String name;
ParcelCompanyEnum(String name) {
this.name = name;
}
}```

CalculatePostage类有一个Map成员变量，在类对象初始化的时候初始化该map，map设置lambda表达式，实现函数式接口，

```public class CalculatePostage {
Map<ParcelCompanyEnum, Function<Integer, Double>> map = new HashMap<>(5);

{
map.put(ParcelCompanyEnum.JD, this::calculateJd);
map.put(ParcelCompanyEnum.STO, this::calculatSto);
map.put(ParcelCompanyEnum.YTO, this::calculateYto);
map.put(ParcelCompanyEnum.ZTO, this::calculateZto);
}
public Double calculateJd(Integer weight) {
return 10 + weight * 1.2;
}
public Double calculatSto(Integer weight) {
return 12 + weight * 0.8;
}
public Double calculateYto(Integer weight) {
return 8 + weight * 1.5;
}
public Double calculateZto(Integer weight) {
return 9 + weight * 1.1;
}
}```

```public class Client {
public static void main(String[] args) {
ParcelCompanyEnum company = ParcelCompanyEnum.JD;
Integer weight = 15;
CalculatePostage calculatePostage = new CalculatePostage();
System.out.println("Java8 lambda + 策略模式 计算邮费：" + calculatePostage.map.get(company).apply(weight));
}
}```