design-patterns - 我如何编写一个名称中不涉及方法逻辑但适应各种算法(在 Java 中)的方法?
问题描述
我正在编写一个 Java 应用程序,该应用程序必须与接受其自己的语言的设备进行通信,该语言通过安全外壳通道由命令序列(一系列字节)组成。
为简单起见,此设备上有命名的读/写字段
fieldAlpha
fieldBeta
...fieldn
我可以在此设备上获取和设置。
命令序列由 StringBuilder 对象创建,该对象由
- 字首
- 可选的设置器有效负载(用于设置器)
- 后缀
命令序列看起来像<ESC>ABC*somerandomvalueDEF<LF>
.
在写了大约 20 篇之后,我认为必须有一种更易于维护的方式来处理这个问题。
public String getFieldAlpha() {
StringBuilder sb = new StringBuilder();
sb.append((char) 0x1B).append("ABC").append("DEF").append((char) 0x0D);
byte[] command = sb.toString().getBytes();
String response = (sendMessage(command));
return response;
}
public String setFieldAlpha(String alpha) {
StringBuilder sb = new StringBuilder();
sb.append((char) 0x1B).append("ABC*").append(alpha).append("DEF").append((char) 0x0D);
byte[] command = sb.toString().getBytes();
String response = (sendMessage(command));
return response;
}
public String getFieldBeta() {
StringBuilder sb = new StringBuilder();
sb.append((char) 0x1B).append("OPQ").append("RST").append((char) 0x0D);
byte[] command = sb.toString().getBytes();
String response = (sendMessage(command));
return response;
}
public String setFieldBeta(String beta) {
StringBuilder sb = new StringBuilder();
sb.append((char) 0x1B).append("OPQ*").append(beta).append("RST").append((char) 0x0D);
byte[] command = sb.toString().getBytes();
String response = (sendMessage(command));
return response;
}
// ... and so forth
我怀疑更好的 API 设计是两种基于参数选择函数的方法。我挂断了命令序列根据字段而变化的事实。
getField()
setField(Method FieldName, String value)
或者有没有更好的方法我没有考虑?我看起来可能使用 Enum Objects 来设置字段命令序列的前缀和后缀。
解决方案
实现这一点的一种方法是使用将字段映射到消息格式的HashMap 。如果您有不同的格式来获取字段和设置字段,您将需要两个HashMaps。
您的应用程序必须为每个字段调用方法,因此您可以添加两个方法:setField(string fieldName, string fieldValue)和getField(string fieldName)。
您可以添加一个包含字段的静态类。
public class Fields {
public final string Alpha = "Alpha";
public final string Alpha = "Beta";
// ......
}
添加工厂将消息创建的职责分离到一个特殊的对象:
public class MessageFactory {
private HashMap<string, string> mFieldNameMessageFormatMap;
public MessageFactory() {
mFieldNameMessageFormatMap = HashMap<string, string>();
// Initialize your formats here. These are just for example and are not
correct
mFieldNameMessageFormatMap.put(Fields.Alpha, "<ESC>ABC*%sDEF<LF>");
mFieldNameMessageFormatMap.put(Fields.Beta, "<ESC>OPQ*%sRST<LF>");
}
public string createGetFielMessage(string fieldName) {
return String.format(mFieldNameMessageFormatMap.get(fieldName), "");
}
public void createSetFieldMessage(string fieldName, string value) {
return String.format(mFieldNameMessageFormatMap.get(fieldName), value);
}
}
然后你的代码变成:
public void getValue(string fieldName) {
return sendMessage(mMessageFactory.createGetFieldValue(fieldName));
}
public void setValue(string fieldName, string value) {
return sendMessage(mMessageFactory.createSetFieldValue(fieldName), value);
}
// usage:
string fieldValue = getValue(Fields.Alpha);
setValue(Fields.Alpha);
添加新字段很容易。您只需将字段添加到Fields类并将格式添加到工厂
这样您就不必为每个字段编写方法,并且您的代码中不会有“魔术字符串”。
推荐阅读
- java - 尝试导入 spigot api 时,Eclipse 中出现“JavaPlugin 不可访问”错误?
- javascript - 为什么我们不能只使用 react 库中的“useState()”而不是 redux,使用 redux 有什么好处?
- python - 用成功/失败而不是或多或少找到未知数的二分法
- python - 设置网箱,AttributeError:模块“秘密”没有属性“选择”
- go - 为什么 p 不满足 c 的接口(第 106 行)?
- html - 在 2 个不同的 HTML 页面中预加载相同的资源
- python - Numpy - 在 ND 数组中的子数组上应用函数
- php - 如何使 Phonegap 连接到本地主机
- c# - 如何在 selenium c# 中验证下拉列表中的所有值
- atom-editor - Platformio-IDE-Terminal 无法运行 conda,但普通终端可以