先决条件:
String command = "x";
Data data = request.get();
interface Action {
Response process(Data data);
}
class ActionX implements Action {
public Response process(Data data) {}
}
class Service {
public execute(Action action) {
action.process();
}
}
我不明白如何注册我的行为。以下选项是不可接受的:
// bad because too verbose
case "x":
action = new ActionX();
and
// bad because package name is a constant string
action = Class.forName("some.package.name.Action" + command.toUpperCase());
我想我可能会尝试使用Java注释来解决我的问题。像这样:
@Action(command = "x")
class ActionX implements Action {}
// scan whole classpath etc ...
但也许我只需要使用另一种模式......
答案 0 :(得分:1)
根据我,在这种情况下,Factory design pattern(或抽象工厂设计模式)合适。 我可能错了。
您可以尝试使用工厂模式的方式
enum Command {
X("x");
private String commandString;
Command(String commandString) {
this.commandString = commandString;
}
public String getCommandString() {
return commandString;
}
}
interface Action {
void process();
}
class ActionX implements Action {
@Override
public void process() {
System.out.println("Processing..");
}
}
class ActionFactory {
public Action getAction(Command command) {
// Check command and return action
// Switch is the best suitable here
return action;
}
}
考虑一下你有很多命令和许多动作的情况....!在这种情况下,你必须首先查看你的设计,然后再考虑一些分析可以完成而不是首先决定设计模式。
答案 1 :(得分:0)
不要使用Class.forName(“”)。我会选择切换案例,但可能会将命令表示更改为枚举而不是字符串。
答案 2 :(得分:0)
您可以使用地图:
Map<String, Action> map = ...;
map.put("x", new ActionX());
Response response = map.get("x").process(data);
答案 3 :(得分:0)
看起来命令名称是命令的固有部分(而不是在外部配置)。如果是这种情况,就这样建模:
interface Action {
String name();
Response process(Data data);
}
然后,您只需创建一个Map<String,Action>
,将每个操作的名称用作关键字。
如果您想让命令类可被发现而不是硬编码,并且您没有使用像Spring这样的现有扫描程序,那么您应该使用Service Provider Interface。