我正在尝试为扑克手历史编写一个解析器系统。有些人会使用正则表达式,有些人会使用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对单元测试很有用。 但抽象的继承感觉更“自然”......
答案 0 :(得分:0)
我不确定我理解“游戏上下文”包含什么,我不明白为什么解析器需要一个。但是,我会在解析器之外找到游戏上下文并将其注入基本解析器类。每个子类解析器都可以根据需要使用该上下文。
我更喜欢保留几个解析器类,但它们都是主Parser
类的子类,或者都是实现Parser
接口。 (在接口的情况下,我们通常使用BaseParser
或ParserImpl
类,我们需要一个根类。)
然后,在使用解析器的地方,你会保留一个包含它的变量:
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());