Java 使多态性击败那些开关/案例语句很困难
继续前面的问题(、和),我实现了一个基本的命令模式,创建了我的命令类,并将其编码到一个接口,以便在使用任何命令时调用Java 使多态性击败那些开关/案例语句很困难,java,design-patterns,polymorphism,conditional,switch-statement,Java,Design Patterns,Polymorphism,Conditional,Switch Statement,继续前面的问题(、和),我实现了一个基本的命令模式,创建了我的命令类,并将其编码到一个接口,以便在使用任何命令时调用execute()方法 但是,我仍然发现自己无法动摇这些case语句:我从主/决策字符串中读取每个字符,该字符串由随机重复的字符a、B、C或D组成,然后从映射中检索命令的相关实现并调用其execute方法 我的设计是这样的: public interface Command { void execute(); } public class CommandA impleme
execute()
方法
但是,我仍然发现自己无法动摇这些case语句:我从主/决策字符串中读取每个字符,该字符串由随机重复的字符a、B、C或D组成,然后从映射中检索命令的相关实现并调用其execute方法
我的设计是这样的:
public interface Command {
void execute();
}
public class CommandA implements Command{
//implements execute() method
}
private Map myMap= new HashMap();
myMap.put("A", new CommandA);
myMap.put("B", new CommandB);
myMap.put("C", new CommandC);
myMap.put("D", new CommandD);
但是,当我阅读每一条指令时,我不得不再次求助于案例陈述:
switch(instructionFromString){
case 'A':{myMap.get("A").execute(); break;}
case 'B':{myMap.get("B").execute(); break;}
case 'C':{myMap.get("C").execute(); break;}
case 'D':{myMap.get("D").execute(); break;}
显然,在这一过程中的某个地方,我成功地击败了多态性相对于案例陈述的优势
它可能是我选择用来存储命令的那种数据结构吗?它很可能是一个永久性的数据结构,只需从中提取这些命令
我想到的另一件事是我在地图中使用的键/值命名。我试图从概念上将每个存储的命令链接到其关联的指令的方式?i、 e.命令“A”的执行情况存储在带有键“A”的地图上,以便与相应的指令“A”匹配?但在我看来,这似乎有点不太可能
对于我下一步一劳永逸地删除这些案例陈述的任何暗示或进一步建议,我们将不胜感激。提前非常感谢我可能在这里遗漏了一些东西,但不是
开关
语句,而是有什么问题
((Command)myMap.get(instructionFromString)).execute();
如果指令fromstring是字符
,则在执行地图查找之前,请将其转换为字符串
,否则请在地图中使用字符
键
此外,如果使用Java 5通用映射,则可以删除强制转换到命令
。清理后的版本将是:
private Map<Character, Command> myMap = new HashMap<Character, Command>();
myMap.put('A', new CommandA());
myMap.put('B', new CommandB());
myMap.put('C', new CommandC());
myMap.put('D', new CommandD());
有了一个简单的映射,事情可能会变得很糟糕,因为您再次使用了相同的
CommandA
实例
封装这种行为的一个好方法是工厂:
public class CommandFactory
{
public Command CreateCommand(String instruction)
{
if (instruction.equals("A"))
return new CommandA();
else if ...
}
}
另一种方法是(又称克隆模式),它允许更灵活地处理多种不同类型(用于此目的的命令):
公共类CommandFactory
{
私有映射命令=new HashMap();
公共无效寄存器命令(字符串指令、命令命令模板)
{
commands.put(指令,commandTemplate);
}
公共命令CreateCommand(字符串指令)
{
返回命令.get(指令).clone();
}
}
正如您可能已经注意到的,您必须将克隆行为实现到
命令中,这可能很耗时。我喜欢Skaffman的答案。我只想补充一些:
为了命名命令,可以使用更简单的模式。例如,可以使用命令名作为默认情况
- 在一般情况下,那就更不用说打字了。它消除了错误
- 当名称不同时,仍然可以为此特定情况配置映射
有许多技术可用于关联名称和命令。示例:
- 类的注释,指定命令名(默认值等于类的名称)
- springconfiguration已经是一张很大的地图,它直接交付了相应的对象,并提供了更多的服务
- Java枚举也自然地将名称与对象关联起来。此外,它们允许您在IDE中进行完成和编译时检查,以及“引用搜索”和其他功能
@skaffman:对不起。我设法阅读了代码示例,但错过了上面和下面的文本。@skaffman:谢谢,非常优雅的asnwer。真不敢相信我错过了!另外,使用泛型。不要用生的collections@KLE:谢谢!这里也有非常有用的提示。
public class CommandFactory
{
public Command CreateCommand(String instruction)
{
if (instruction.equals("A"))
return new CommandA();
else if ...
}
}
public class CommandFactory
{
private Map<String, Command> commands = new HashMap<String, Command>();
public void RegisterCommand(String instruction, Command commandTemplate)
{
commands.put(instruction, commandTemplate);
}
public Command CreateCommand(String instruction)
{
return commands.get(instruction).clone();
}
}