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)
或者这会更好用枚举?
我会简单地传递一个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)
这听起来很有意义.
我通常使用这种格式。我知道很多人不喜欢它,但到目前为止没有人提出更好的方法。
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)
注意:我渴望找到更好的方法,因此如果您有任何想法,请在评论中分享。