我应该使用哪种模式根据命令名运行某些操作?

时间:2016-08-11 07:48:04

标签: java design-patterns

先决条件:

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 ...

但也许我只需要使用另一种模式......

4 个答案:

答案 0 :(得分:1)

根据我,在这种情况下,Factory design pattern(或抽象工厂设计模式合适我可能错了。

  • 基于注释的方式对于这种情况 overkill
  • Switch case并不详细。

您可以尝试使用工厂模式的方式

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