获得专门的儿童班的正确方法是什么?

时间:2013-09-30 16:27:04

标签: java design-patterns

我有一个特殊的问题,我有一个class Command我用来按顺序表示缓冲区中的命令。我还有几个子类,如ComputeCommandDefineCommandDisplayCommand等。  每个子类的构造函数都使用String参数,该命令根据命令语法进行解析,该命令语法因命令类型而异,不同于命令类型。

我希望能够做到这样的事情:

String [] lines = { ... };
ArrayList<Command> commands = new ArrayList<Command>();
for(String line: lines){
    commands.add(new Command(line))
}

但是,我需要更专业的类来处理每个命令。

如果我可以将构造函数定义为:

Command(String line){
    if(ComputeCommand.isValidComputeCommand(line))
        return new ComputeCommand(line);
    else if(DisplayCommand.isValidDisplayCommand(line))
        return new DisplayCommand(line);
    [ ... ]
}

这将完成我的需要,但是正如我们所知,构造函数不会那样工作。

我想到的一种方法是包括像

这样的方法
static Command getInstance(String line){ [...] }

执行该功能,但我不确定在这种情况下这是否正确。

另一种可能的方法是为每一个创建工厂类:

class CommandFactory(){
    CommandFactory [] subFactories = {new ComputeCommandFactory(), [...]};
    Command makeCommand(String line){
        for(CommandFactory subFactory: subFactories)
            if(subFactory.canMake(String line))
                return subFactory.makeCommand(line);
    }
    boolean canMake(String line){
        for(CommandFactory subFactory: subFactories)
            if(subFactory.canMake(String line))
                return true;
    }
}

我认为这可能是最正确的方法,但如果有更好的方法,我不想增加额外的复杂性。

在这种情况下使用的正确设计模式是什么?

编辑: 我还计划进一步子类化一些命令,例如ComputeCommand可以有AddCommandMultiplyCommand子类。

4 个答案:

答案 0 :(得分:2)

正如您所想,您的CommandFactory方法最接近正确。工厂/工厂方法通常用于此类问题。

你明显看到的唯一问题是这个CommandFactory必须知道所有子事件,必须知道所有类型。这意味着,如果您添加新类型,则必须将其添加到CommandFactory

但是!你可以用例如来自ClassFinder库的org.clapper.util,以查找在类路径中实现Command或扩展CommandFactory的所有类。这样,您可以在以后添加任何新的CommandsCommandFactory仍会找到它们并将其添加到subFactories

你也可以扭转问题 - 让子工厂(或个人Commands自己)了解工厂!首先使用ClassFinder找到它们,然后在它们上面调用一个方法,将它们添加到工厂列表中。这与听众的工作方式类似。

答案 1 :(得分:1)

我正在阅读的是你想根据上下文构建正确的对象?你有一些字符串,并且你想从该字符串的内容构建正确的对象?

你可以拥有一个CommandBuilder / Factory,在那里你可以放置你的if-else逻辑来返回正确的命令。

public Command buildCommand(String line){
    if(ComputeCommand.isValidComputeCommand(line))
        return computeCommandFactory.buildCommand(line);
    else if(DisplayCommand.isValidDisplayCommand(line))
        return displayCommandFactory.buildCommand(line);
    [ ... ]

}

听起来您想要使用构建器或abstract factory来构建所需的Command对象。如果你有一个大的if-else if链,你通常想要使用策略模式。

答案 2 :(得分:1)

我认为您需要FactoryChain of Responsibility模式的组合才能达到您想要的效果。

interface CommandFactory{
    Command create(String line);

    void addToChain(CommandFactory next);
}

如果您的工厂无法处理给定的生产线,那么它会将生产线传递给链中的下一个工厂:

class ComputeCommandFactory{


    CommandFactory next;

    Command create(String line){
        if(<can process>){
           return new ComputeCommand(line);
        }
        if(next ==null){
          throw Exception("can't process");
        }
        return next.create(line);
     }

 }

这样您可以稍后添加新工厂(即使在运行时)。这类似于添加类加载器和数据库驱动程序在Java中的工作方式。

答案 3 :(得分:1)

你走在正确的轨道上。您希望在此处使用的模式是工厂模式。 你的想法是正确的,模式只不过是在纸上“写下”的那种思想:)。

因此,对于您的情况,您可以执行以下操作:

public class CommandFactory
{
   public static Command getCommand (String line)
   {
      Command command = null;
      if (ComputeCommand.isValidComputeCommand (line))
      {
        command = new ComputeCommand (line);
      }
      else if (DisplayCommand.isValidDisplayCommand (line))
      {
        command = new DisplayCommand (line);
      }

     return command;
   }
}

并像这样使用它:

Command command = CommandFactory.getCommand (line);

希望有所帮助。