我有一系列开关盒,但似乎有点太复杂了。简化它的最佳方法是什么?我当时正在考虑使用策略设计模式。
我最初的想法是使sendReport成为一个方法,该方法从每个不同的类调用sendReport。但是,我不确定如何实现这一点。谁能给我一些指导,或者关于如何使这种转换案例变得更简单的一些建议。
谢谢。
public static boolean sendReport(AuthToken token, Student client, List<ContactMethod> bestOptions, String data) {
for (ContactMethod method : bestOptions) {
switch (method) {
case TEXT:
String textMessage = client.getPhoneNumber();
if (null != textMessage) {
TEXT.sendReport(token, client.getFName(), client.getLName(), data, textMessage);
return true;
}
break;
case POST:
String address = client.getAddress();
String suburb = client.getSuburb();
String state = client.getState();
String postcode = client.getPostCode();
if (null != address && null != suburb &&
null != state && null != postcode) {
Mail.sendReport(token, client.getFName(), client.getLName(), data, address, suburb, state, postcode);
return true;
}
break;
case ELECTRONICMAIL:
String email = client.getEmailAddress();
if (null != email) {
Email.sendReport(token, client.getFName(), client.getLName(), data, email);
return true;
}
break;
case VOICECALL:
String number = client.getPhoneNumber();
if (null != number) {
PhoneCall.sendReport(token, client.getFName(), client.getLName(), data, number);
return true;
}
break;
case FACE_TO_FACE:
String face2face = client.getFace2Face();
String personName = client.getPersonName();
if (null != face2face && null != personName) {
Face_To_Face.sendReport(token, client.getFName(), client.getLName(), data, face2face,personName);
return true;
}
break;
case MAGIC:
String magicID = client.getMagic();
if (null != magicID) {
magic.sendReport(token, client.getFName(), client.getLName(), data, magicID);
return true;
}
break;
default:
return false;
}
}
return false;
}
您甚至不需要设计模式,只需要基本的多态性。
将ContactMethod
从枚举更改为接口。每个case语句成为接口的实现
public class TextContactMethod implements ContactMethod { ... }
sendReport
变为
for (ContactMethod method : bestOptions) {
method.fooBar(token, client);
}
我只是简单地使开关“阻塞”到方法中并调用它们;例如
public static boolean sendReport(AuthToken token, Student client,
List<ContactMethod> bestOptions,
String data) {
for (ContactMethod method : bestOptions) {
boolean res;
switch (method) {
case TEXT:
res = processText(token, client, data);
break;
case POST:
res = processPost(token, client, data);
break;
...
default:
res = false;
}
if (res) {
return true;
}
}
return false;
}
private boolean processText(AuthToken token, Student client) {
String textMessage = client.getPhoneNumber();
if (null != textMessage) {
TEXT.sendReport(token, client.getFName(), client.getLName(),
data, textMessage);
return true;
} else {
return false;
}
}
当然,您可以使用设计模式来进行修饰,但是简单的过程抽象同样适用。
定义具有sendReport方法的公共接口ContactMethod,并为每个实现ContactMethod的开关案例创建不同的实现类。例如;
public static boolean sendReport(AuthToken token, Student client, List<ContactMethod> bestOptions, String data) {
for (ContactMethod method : bestOptions) {
if (method.sendReport(token, client, data))
return true;
}
}
public class TextContactMethod implements ContactMethod {
public boolean sendReport(AuthToken token, Student client, String data) {
String textMessage = client.getPhoneNumber();
if (null != textMessage) {
TEXT.sendReport(token, client.getFName(), client.getLName(), data, textMessage);
return true;
}
return false;
}
}
是的,实施策略/政策模式可以完成这项工作。基本上,三个已经存在的答案中有两个显示了该模式的可能实现(Michael's answer和Ali Gelenler's answer),尽管迈克尔不认为他的实现会遵循模式…
如果一组可能的联系方法是固定的,则您甚至可以将sendReport()
添加为枚举的方法,每个枚举实例的实现方式都不同。这为您节省了专用于策略的注册表(并且您无需定义几个不同的类)。
更干净的路径将(如已经提到的答案所建议的那样)定义接口ContactMethod
并为您需要的每种联系方式实现该接口。它的优点是您可以轻松添加其他联系方式(特别是如果您使用java.util.ServiceLoader
API)。
缺点是,如果联系方法是外部化实体的属性,则需要某种策略的注册表,以及从策略名称到其实现的映射-如前所述,您可以免费获得,当您扩展(滥用?)枚举时。