扩展接口或聚合接口

时间:2015-08-10 15:39:02

标签: oop design-patterns

我处于两难境地。我有一个接口Parser,实现它的类将解析具体的文件格式。例如 - CSVParser将解析CSV文件,XMLParser将解析XML文件等。

因此,接口Parser将是:

public interface Parser{

    public SomeObject parseFile(String pathToFile);

}

另一方面,一些解析器将有额外的参数,例如,一个数组将告诉他们在文件中跳过哪些行。现在这让我感到困惑,我应该扩展Parser并添加方法,例如:

public interface BetterParser extends Parser{
    public SomeObject parseFileConsideringParameter(String pathToFile, int[] whichLinesToSkip)
} 

或者我应该聚合它们以便我的班级需要实现两者:

public class concreteParser implements Parser, BetterParser{
}

我想在pipline中有解析器不可知部分,你会说:

Parser parser = ParserFactory.giveMeParser(type);
SomeObject so = parser.parseFile(path);

问题是,在某些情况下,我没有参数告诉我要跳过哪一行。

我知道我只能用两个参数创建一个方法,所以一些实现会传递另一个参数,而其他参数会传递null,但这看起来很难看。

我真的想避免受到具体实施的约束,但我该如何克服这个问题呢?也许我错过了什么?

2 个答案:

答案 0 :(得分:1)

这些接口的原因主要是服务提供商可以将接口绑定到其实现。如果所述实现具有“变体”,那么允许这种变化的一种方法是实现常规SomeObject parseFile(String pathToFile)方法,该方法使用默认parseFileConsideringParameter()参数调用whichLinesToSkip来传递。然后,如果你需要告诉哪些行要跳过,你要检查解析器是instanceof BetterParser,然后将解析器转换为BetterParser并使用该方法(但如下所述,instanceof是很少解决方案)。

话虽如此,你的问题有两个部分:

  1. 聚合或扩展
  2. 如何处理实施中的变化
  3. 对于1,这是个人偏好。两者都可以工作,但是扩展可能会显示BetterParser 是一个解析器,而不是依靠实现来传达它,只需实现两者。

    对于2,我在上面提到过它。但是,大多数人说,如果您使用instanceofthere's probably a better way。为此,您可以考虑让服务提供者使用两种方法,一种用于获取常规解析器,另一种用于获取SkippableParser(例如)。

答案 1 :(得分:1)

  

另一方面,一些解析器将有额外的参数,例如,一个数组将告诉他们在文件中跳过哪些行。现在这让我很困惑,我应该扩展Parser并添加方法,比如

interface Parser {
    public List<Token> parse(String pathToFile);
}

abstract class ParserDecorator implements Parser {
    protected Parser realParser;
    protected ParserDecorator(Parser rp) {}
    // delegates most of the methods to real parser...
}

class LineFilterParserDecorator extends ParserDecorator {
    private int[] linesToSkip;
    public LineFilterParserDecorator(Parser rp, int[] linesToSkip) {
        super(rp);
        this.linesToSkip = linesToSkip;
    }

    @override
    public List<Token> parse(Strint path) {
        List<Token> l = this.realParser.parse(path);
        // remove the skipped lines from the list
        return l;
    }
}

// Usage:

Parser myParser = new LineFilterParserDecorator(new CSVParser(...), new int{10, 20,30}); // will skip lines 10, 20 and 30

不,请,不要。

您可以使用Decorator Pattern尝试一种方法。

{{1}}