战略设计模式,泛型和类型安全

Chr*_*Geo 8 java generics strategy-pattern factory-pattern

我想创建以下策略模式与Factory结合,但我希望它是类型安全的.到目前为止我做了以下事情:

public interface Parser<T> {

    public Collection<T> parse(ResultSet resultSet);

}


public class AParser implements Parser<String> {

    @Override
    public Collection<String> parse(ResultSet resultSet) {
             //perform parsing, get collection
        Collection<String> cl = performParsing(resultSet); //local private method
        return cl;
    }
}

public class ParserFactory {

    public enum ParserType {
        APARSER
    }


    public static <T> Parser<T> createParser(ParserType parserType) {


        Parser<?> parser = null;
        switch (parserType) {
        case APARSER:
            parser = new AParser();
            break;
        }
            //unchecked cast happens here
        return (Parser<T>) parser;
    }
}


public class Context {

      public <T> Collection<T> getResults(String query, ParserType parserType) {
          ResultSet resultSet() = getResultSet(query); //local private method
          Parser p = ParserFactory.createParser(parserType);
          Collection<T> results = p.parse(resultSet)
      }

}
Run Code Online (Sandbox Code Playgroud)

一般来说无论我尝试什么,某个地方我都会有一个未经检查的演员.任何人都知道我如何重构代码是类型安全的?

检查有效的Java我也偶然发现了这种模式:

public final class ParserFactory {

    private ParserFactory() {

    }

    private static class AParser implements Parser<String> {
        @Override
        public Collection<String> parse(ResultSet resultSet) {
            //...
            return new ArrayList<>();
        }
    }

    public static final Parser<String> APARSER = new AParser();

}
Run Code Online (Sandbox Code Playgroud)

所以现在我可以使用Ingo建议

public <T> Collection<T> getResults(String query, Parser<T> p)
Run Code Online (Sandbox Code Playgroud)

getResults("query", ParserFactory.APARSER);
Run Code Online (Sandbox Code Playgroud)

或者这会更好用枚举?

Ing*_*ngo 5

我会简单地传递一个Parser<T>getResults()方法,而忘记了那个工厂的东西.看,如果你说:

public <T> Parser<T> createParser(ParserType typ) { ... }
Run Code Online (Sandbox Code Playgroud)

你承诺该方法将创建一个调用者想要的任何类型的解析器.这只能以类型安全的方式使用,所有解析器都返回一个空集合.此外,您无法Parser<String>从该函数返回a ,因为String它与调用者想要的任何类型都不一样.

但是,如果你写:

  public <T> Collection<T> getResults(String query, Parser<T> parser) {
      ResultSet resultSet = getResultSet(query); //local private method
      Collection<T> results = parser.parse(resultSet);
      return results;
  }
Run Code Online (Sandbox Code Playgroud)

你有你想要的东西:该getResult方法独立于解析器的工作方式,但它返回正确类型的集合.

而后来,而不是

Collection<String> it = (Collection<String>) getResults("query", APARSER);
Run Code Online (Sandbox Code Playgroud)

你说:

Collection<String> it = getResults("query", new AParser());
Run Code Online (Sandbox Code Playgroud)

这听起来很有意义.


Ada*_*old 3

我通常使用这种格式。我知道很多人不喜欢它,但到目前为止没有人提出更好的方法。

public enum ParserType {
    APARSER(new AParser());

    private Parser parser; // this should be an interface which is implemented by AParser

    private ParseType(Parser parser){
        this.parser = parser;
    }

    public Parser getParserInstance() {
        return parser;
    }

}
Run Code Online (Sandbox Code Playgroud)

Class如果您每次都想要一个新实例,则可以传递对象:

public enum ParserType {
    APARSER(AParser.class);

    private Class<Parser> parserClass;

    private ParseType(Class<Parser> parserClass){
        this.parserClass = parserClass;
    }

    public Parser createParser() {
        return parserClass.newInstance(); // TODO: handle exceptions here
    }

}
Run Code Online (Sandbox Code Playgroud)

注意:我渴望找到更好的方法,因此如果您有任何想法,请在评论中分享。