使用 Java 8 功能接口实现策略模式
此示例的目的是展示如何使用 Java 8 功能接口实现策略模式。我们将从经典 Java 中的简单用例代码开始,然后以 Java 8 方式重新编码。
我们使用的示例问题是一系列算法(策略),描述了远距离通信的不同方式。
经典 Java 版本
我们的算法族合同由以下界面定义:
public interface CommunicateInterface {
public String communicate(String destination);
}
然后我们可以实现一些算法,如下:
public class CommunicateViaPhone implements CommunicateInterface {
@Override
public String communicate(String destination) {
return "communicating " + destination +" via Phone..";
}
}
public class CommunicateViaEmail implements CommunicateInterface {
@Override
public String communicate(String destination) {
return "communicating " + destination + " via Email..";
}
}
public class CommunicateViaVideo implements CommunicateInterface {
@Override
public String communicate(String destination) {
return "communicating " + destination + " via Video..";
}
}
这些可以实例化如下:
CommunicateViaPhone communicateViaPhone = new CommunicateViaPhone();
CommunicateViaEmail communicateViaEmail = new CommunicateViaEmail();
CommunicateViaVideo communicateViaVideo = new CommunicateViaVideo();
接下来,我们实现一个使用该策略的服务:
public class CommunicationService {
private CommunicateInterface communcationMeans;
public void setCommuncationMeans(CommunicateInterface communcationMeans) {
this.communcationMeans = communcationMeans;
}
public void communicate(String destination) {
this.communcationMeans.communicate(destination);
}
}
最后,我们可以使用不同的策略如下:
CommunicationService communicationService = new CommunicationService();
// via phone
communicationService.setCommuncationMeans(communicateViaPhone);
communicationService.communicate("1234567");
// via email
communicationService.setCommuncationMeans(communicateViaEmail);
communicationService.communicate("hi@me.com");
使用 Java 8 功能接口
不同算法实现的契约不需要专用接口。相反,我们可以使用现有的 java.util.function.Function<T, R>
接口来描述它。
组成 the family of algorithms
的不同算法可以表示为 lambda 表达式。这取代了策略类和它们的实例。
Function<String, String> communicateViaEmail =
destination -> "communicating " + destination + " via Email..";
Function<String, String> communicateViaPhone =
destination -> "communicating " + destination + " via Phone..";
Function<String, String> communicateViaVideo =
destination -> "communicating " + destination + " via Video..";
接下来,我们可以将服务编码如下:
public class CommunicationService {
private Function<String, String> communcationMeans;
public void setCommuncationMeans(Function<String, String> communcationMeans) {
this.communcationMeans = communcationMeans;
}
public void communicate(String destination) {
this.communcationMeans.communicate(destination);
}
}
最后,我们使用如下策略
CommunicationService communicationService = new CommunicationService();
// via phone
communicationService.setCommuncationMeans(communicateViaPhone);
communicationService.communicate("1234567");
// via email
communicationService.setCommuncationMeans(communicateViaEmail);
communicationService.communicate("hi@me.com");
甚至:
communicationService.setCommuncationMeans(
destination -> "communicating " + destination + " via Smoke signals.." );
CommunicationService.communicate("anyone");