策略设计模式,泛型和类型安全 [英] Strategy Design Pattern, Generics and TypeSafety
问题描述
我想创建与Factory结合的以下策略模式,但我希望它是类型安全的。我已经完成了以下工作:
public interface Parser< T> {
public Collection< T>解析(ResultSet结果集);
}
公共类AParser实现了解析器< String> {
@Override
public Collection< String>解析(ResultSet结果集){
//执行解析,获取集合
集合< String> cl = performParsing(resultSet); //本地私有方法
return cl;
public class ParserFactory {
public enum ParserType {
APARSER
}
public static< T>解析器< T> createParser(ParserType parserType){
Parser<?> parser = null;
switch(parserType){
case APARSER:
parser = new AParser();
休息;
}
//未经检查的转换发生在这里
return(Parser< T>)解析器;
$ b public class Context {
public< T>收集和LT; T> getResults(String query,ParserType parserType){
ResultSet resultSet()= getResultSet(query); //本地私有方法
解析器p = ParserFactory.createParser(parserType);
收藏品< T> results = p.parse(resultSet)
}
}
一般来说,无论我尝试什么,我都会有一个不受控制的演员。
任何人都知道如何将代码重构为类型安全吗?
检查有效的Java我也偶然发现了这种模式:
public final class ParserFactory {
private ParserFactory(){
private static class AParser实现了解析器< String> {
@Override
public Collection< String>解析(ResultSet结果集){
// ...
返回新的ArrayList<>();
}
}
public static final Parser< String> APARSER = new AParser();
所以现在我可以使用Ingo建议
public< T>收集和LT; T> getResults(String query,Parser< T> p)
as
getResults(query,ParserFactory.APARSER);
或者这对于枚举更好?
Parser< T>
的解决方案。 $ c>方法,忘记那个工厂的东西。看,如果你说: public< T>解析器< T> createParser(ParserType typ){...}
你很有希望该方法将创建一个解析器来电者想要的任何类型。这只能通过解析器以类型安全的方式进行,所有解析器都返回一个空集合。此外,您不能从该函数返回 Parser< String>
,因为 String
与任何键入想要的调用者。
然而,如果你写:
public< T>收集和LT; T> getResults(String query,Parser< T> parser){
ResultSet resultSet = getResultSet(query); //本地私有方法
Collection< T> results = parser.parse(resultSet);
返回结果;
}
您正是想要的: getResult
方法与解析器的工作方式无关,但它返回正确类型的集合。
后来,而不是
集合< String> it =(Collection< String>)getResults(query,APARSER);
你说:
收集和LT;字符串>它= getResults(查询,新的AParser());
这听起来很有意义。
I want to create the following Strategy Pattern combined with Factory, but I want it to be typesafe. I have done the following till now:
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)
}
}
In general whatever I attempt, somewhere I will have an unchecked cast. Anyone have an idea how I can refactor the code to be typesafe?
Checking Effective Java I also stumbled upon this pattern:
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();
}
So now I can use as Ingo suggested
public <T> Collection<T> getResults(String query, Parser<T> p)
as
getResults("query", ParserFactory.APARSER);
Or would this be better with enums?
I'd simply pass a Parser<T>
to the getResults()
method and forget about that factory stuff. Look, if you say:
public <T> Parser<T> createParser(ParserType typ) { ... }
you are promising that the method will create a parser of any type the caller wants. This is only possible in a type safe way with parsers that all return an empty collection. Moreover, you can't return a Parser<String>
from that function, because String
is not the same as any type the caller wanted.
If, however, you write:
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;
}
you have exactly what you wanted: the getResult
method is independent of how the parser works, and yet it returns a collection of the correct type.
And later, instead of
Collection<String> it = (Collection<String>) getResults("query", APARSER);
you say:
Collection<String> it = getResults("query", new AParser());
This is sound and makes sense.
这篇关于策略设计模式,泛型和类型安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!