依赖注入作为一项规则?

时间:2013-07-30 16:57:40

标签: inheritance dependency-injection abstract-class

我正在尝试为扑克手历史编写一个解析器系统。有些人会使用正则表达式,有些人会使用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对单元测试很有用。 但抽象的继承感觉更“自然”......

1 个答案:

答案 0 :(得分:0)

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

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

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

public UsingParserClass {
    private Parser theParser;

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

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

然后使用setter将所需的子类注入UsingParserClass的实例。不同的依赖注入框架以各种方式做到这一点。或者你可以使用你的代码来完成它。

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

... some setup code somewhere ...

myUsingParserClass.setParser(new RegexParser());
myUsingParserClass.getParser().setGameContext(gameContextFinder.find());