0

我正在尝试为扑克手历史编写一个解析器系统。有些会使用正则表达式,有些会使用 XML,等等……

目前我有这个:

abstract class Parser {

    abstract protected GameContext findGameContext();

    public void parse() {
      GameContext gameContext = findGameContext();
    }    
}

和:

class RegexParser {
    protected GameContext findGameContext() {
        // find game context by using some regex...
    }
}

我对此很满意。如果我想要另一种解析器,我将 Parser 子类化并实现抽象方法。
但是,我知道我可以使用依赖注入来做同样的事情。
像这样的东西:

class Parser {

    private IDataType<GameContext> gameContextFinder;

    public setGameContextFinder(IDataTypeFinder<GameContext> finder) { this... = ... }

    public parse() {
        GameContext gameContext = this.GameContextFinder.find();
        ...
    }

在哪里:

interface IDataTypeFinder<T> {
    public T find();
}

class GameContextFinder implements IDataTypeFinder {
    public GameContext find() {
        // some regex...
    }
}

和:

class RegexParser extends Parser {

    public RegexParser() {
        this.setGameContextFinder( new GameContextFinder() );
    }                                        
}

你怎么看这两种方式?到目前为止,我发现 DI 对单元测试很有用。但是抽象继承感觉更“自然”……

4

1 回答 1

0

我不确定我是否理解“游戏上下文”包含的内容,也不明白为什么解析器需要一个。但是,我会让解析器之外的东西找到游戏上下文并将其注入到基本解析器类中。每个子类解析器都可以根据需要使用该上下文。

我更喜欢保留几个作为解析器的类,但它们都是主类的子Parser类或都实现了Parser接口。(在接口的情况下,我们通常使用一个BaseParserParserImpl类,因为我们需要一个根类。)

然后,在使用解析器的地方保留一个保存它的变量:

public UsingParserClass {
    private Parser theParser;

    public setParser(Parser val) { theParser = val;}
}

并且它将有更多的方法来完成实际的工作。

UsingParserClass然后使用 setter将所需的子类注入到实例中。不同的依赖注入框架以不同的方式做到这一点。或者您可以只使用您的代码来执行此操作。

您还可以找到游戏上下文并将其从同一位置注入解析器。

... some setup code somewhere ...

myUsingParserClass.setParser(new RegexParser());
myUsingParserClass.getParser().setGameContext(gameContextFinder.find());
于 2013-07-30T17:05:45.950 回答