需要有关解析器设计策略的建议

Need suggestion on Parser Design Strategy

我需要有关解析器设计策略的建议

考虑 type1, type2, type3 是三个不同的 csv 文件,它们具有不同的格式,将分别由 Parser1, Parser2, Parser3 解析。
将来这将演变为解析来自其他来源(如 dbs)的信息。
还将有新的解析器出现。设计解析器的最佳方法是什么? factory/abstract 工厂是合适的候选人吗?
一些好处和例子会有所帮助吗?

Type1 - Parser1    
Type2 - Parser2    
Type3 - Parser3

我已经放下我的代码,寻找宝贵的建议。

interface Parser<T>{
    public List<T> parse (string s);
}

//where T - data model 

class Parser1CSV implements Parser<Model1>{
    //implement 
    //s-csv file
    public List<Model1> parse (string s){
    }
}

class Parser1DB implements Parser<Model1>{
    //implement 
    //s- connection string
    public List<Model1> parse (string s){
    }
}

class Parser2CSV implements Parser<Model2>{
    //implement 
    //s-csv file
    public List<Model2> parse (string s){
    }
}

//same way other parsers are implemented

interface AbstarctFactory<T>{
    public Parser<T> createParser();
}

class Parser1Factory implements AbstarctFactory<Model1>{
    private String type;
    Parser1Factory(String type){
        this.type = type;
    }

    public Parser<Model1> createParser(){
        if(type.equals("CSV"){
            return new Parser1CSV();
        }else if(type.equals("DB"){
            return Parser1DB();
        }else{
            throw UnSupportedOperationException("Not Supported.");
        }
    }
}

//same way other parser factories are implemented

class ParserFactory{
    public static <T> Parser<T> getParser(AbstarctFactory<T> factory){
        factory.createParser();
    }
}

//Usage:
Parser<Model1> parser = ParserFactory.getParser(new Parser1Factory("CSV"));
List<Model1> list = parser.parse(file);

目前,我没有使用 DI 框架。当我需要使用时会有什么好处和影响?

1) 设计问题有个人空间interpretation/taste,但总而言之,我非常喜欢你的方法,由于其灵活性和模块化,它在行业中很常见。 有时我可以不用工厂的层次结构,但显然这会因情况而异。

2) 你的"class ParserFactory"有什么用?我没有看到它添加了 flexibility/decoupling,而不是旧的 "new Parser1Factory("CSV").createParser()"... 但也许您有一些我错过的可行设计意图。

3) 关于 DI,我主要可以证明 Spring - 你的代码会很好地配合它。 DI的点是"ok, you know how to create parsers, now how do you pass them on to the business code"?例如。如果你有一些 'BankService':

// Without DI:
public class BankService {
   private AbstarctFactory factory= new Parser1Factory();
   public void depositFundsFromFile(File file){
      //  use factory
   }
}
// With DI:
public class BankService {
   @Autowired
   private AbstarctFactory factory; // will be injected by the framework
   public void depositFundsFromFile(File file){
      //  use factory
   }
}

=> DI 使 BankService 真正独立于具体工厂类型:BankService 不包含具体承诺 "new Parser1Factory",因此它可以与任何工厂一起工作,它甚至允许多个 BankService 实例 co-exist ,每个都有不同的工厂类型......然后你会给框架单独的说明关于如何创建你的具体工厂(es ) ,例如"new Parser1Factory("CSV")。对于 spring,此类单独的指令来自 XML 文件或@Configuration 代码。

4) 根据要求,DI 还可以注入解析器而不是工厂(同样,框架将需要单独的指令来创建解析器):

public class BankService ... {
   @Autowired
   private Parser parser; // will be injected from the framework
   public void depositFundsFromFile(File file){
      //  use parser
   }
}

5) 您可以考虑实现 Springs 的 FactoryBean 接口,尽管您确实不必这样做:避免依赖于框架的代码是一个合理的决定.