Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 扩展接口或聚合接口_Oop_Design Patterns - Fatal编程技术网

Oop 扩展接口或聚合接口

Oop 扩展接口或聚合接口,oop,design-patterns,Oop,Design Patterns,我进退两难。我有一个接口解析器,实现它的类将解析具体的文件格式。例如,CSVParser将解析CSV文件,XMLParser将解析XML文件等等 因此,接口解析器应该是: public interface Parser{ public SomeObject parseFile(String pathToFile); } 另一方面,一些解析器将有额外的参数,例如,一个数组,它将告诉他们在文件中跳过哪些行。现在这让我很困惑,我是否应该扩展解析器并添加方法,比如: public inte

我进退两难。我有一个接口解析器,实现它的类将解析具体的文件格式。例如,CSVParser将解析CSV文件,XMLParser将解析XML文件等等

因此,接口解析器应该是:

public interface Parser{

    public SomeObject parseFile(String pathToFile);

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

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,但这看起来很难看


我真的希望避免局限于具体的实现,但是我如何克服这个问题呢?也许我遗漏了什么?

这些接口的原因本质上是为了让服务提供者可以将接口绑定到其实现。如果所述实现具有“变体”,那么允许此类变体的一种方法是实现常规的
SomeObject parseFile(String pathToFile)
方法,该方法调用
parseFileConsideringParameter()
,并使用默认的
跳过
参数进行传递。然后,如果您需要知道要跳过哪些行,您应该检查解析器是否是
instanceof
BetterParser,然后将解析器转换为BetterParser并使用该方法(但如下所述,
instanceof
很少是解决方案)

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

  • 聚合或扩展
  • 如何处理实现中的变化
  • 对于我来说,这真的是个人喜好。但是,扩展可能表明BetterParser是一个解析器,而不是依赖于实现来传达这一点,只是通过实现两者

    对于2,我在上面提到过。然而,大多数人说,如果您使用
    instanceof
    。为此,您可以考虑让服务提供者使用两种方法,一种是获取正则解析器,另一种是获取SkippableParser(例如)。 另一方面,一些解析器将有额外的参数,例如,一个数组,它将告诉他们在文件中跳过哪些行。现在这让我很困惑,我应该扩展解析器并添加方法吗

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

    您可以尝试使用

    接口解析器{
    公共列表解析(字符串路径文件);
    }
    抽象类ParserDecorator实现语法分析器{
    受保护的解析器;
    受保护的ParserDecorator(解析器rp){}
    //将大多数方法委托给真正的解析器。。。
    }
    类LineFilterParserDecorator扩展ParserDecorator{
    私有int[]linesToSkip;
    公共LineFilterParserDecorator(解析器rp,int[]linesToSkip){
    超级(rp);
    this.linesToSkip=linesToSkip;
    }
    @凌驾
    公共列表解析(Strint路径){
    List l=this.realParser.parse(路径);
    //从列表中删除跳过的行
    返回l;
    }
    }
    //用法:
    Parser myParser=newlinefilterparserdecorator(newcsvparser(…),newint{10,20,30});//将跳过第10、20和30行
    
    跳行是否取决于格式?是特定于特定语法分析器的东西,还是不管格式如何都需要执行的东西?谢谢您的关注。是的,它取决于格式。对于某些文件,它是不需要的,但对于其他文件,它应该是具体解析器的一部分,即不是接口的一部分。在实例化解析器或让解析器以某种方式“检测”该内容时,将其作为参数。在最坏的情况下,您可能会在解析器中注入一个“服务”,该服务可以像svc.GetCSVLinesToSkip()一样调用
    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