策略设计模式,泛型和类型安全 [英] Strategy Design Pattern, Generics and TypeSafety

查看:331
本文介绍了策略设计模式,泛型和类型安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建与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); 

或者这对于枚举更好?

getResults()传递一个 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆