1

根据抽象工厂模式,我有以下 2 个接口:

public interface GenericObjectInterface<T extends Number>{
    public T getResult();
}
public interface AbstractFactoryInterface{
    public <T extends Number> GenericObjectInterface<T> createGenericObject();
}

我有一个实现 GenericObject 的抽象类,但它仍然不知道具体类型(它只对 Number 进行泛型操作):

public abstract class GenericAbstractClass<T extends Number> implements GenericObjectInterface<T>{   } 

然后我有一系列执行通用参数替换的具体类扩展:

public class IntegerObject extends GenericAbstractClass<Integer>{
     public Integer getResult(){}
}
....

现在,我从工厂的实现内部构建了具体类型,它正在实现 GenericObjectInterface 但丢失了它的泛型参数:

public class ConcreteFactory{
    public <T extends Number> GenericObjectInterface<T> greateGenericObject(Class<T> c){
         if (c.class.isInstance(Integer.class)){
             IntegerObject obj = new IntegerObject();
             //I would like to return obj
             GenericObjectInterface<T> a = new IntegerObject(); //errror
             GenericAbstractClass<T> a = new IntegerObject(); //errror

             return a;
          }else if (c.class.isInstance(Double.class)){
          }
    }
}

我想返回实现 GenericObjectInterface 的 obj 但我不知道该怎么做。我该如何解决这个问题?

我习惯于抽象工厂,但我从未将它与泛型一起使用。我在解释模式时是否犯了一些错误?

4

4 回答 4

3

如果您的方法返回一个IntegerObject为什么不直接返回GenericObjectInterface<Integer>?您已经知道参数类型。

在这种情况下,只需向 中添加一个通用参数AbstractFactoryInterface

public interface AbstractFactoryInterface<T extends Number> { ... }

public class ConcreteFactory implements AbstractFactoryInterface<Integer> { ... }

在您的实现中,类型T将从分配中推断出来,因此您可以这样做:

 GenericObjectInterface<Double> g = new ConcreteFactory().greateGenericObject();

在这种情况下,但你会在内部使用T,导致:DoubleInteger

GenericObjectInterface<Double> a = new IntegerCell(); 

由于编译器无法确保它T始终是类型Integer,因此不允许您进行该分配。

于 2011-09-23T14:45:14.200 回答
1

抽象工厂的特点是工厂方法返回接口或抽象类引用而不是具体引用。它不扩展到类型参数。

这样想:你应该能够做到这一点吗?

public class ConcreteListFactory {
    public <T> List<T> createList() {
        return new ArrayList<String>();
    }
}

如果来电者想要一个List<Integer>?

如果你希望你的工厂返回一个泛型类型,你应该让你的具体类接受类型参数。否则让你的工厂方法返回一个GenericObjectInterface<Integer>.

或者,您可以让您的方法接受类型标记 ( Integer.class)。例如:

public <T extends Number> GenericObjectInterface<T> createGenericObject(Class<T> clazz) {
    if ( clazz.equals(Integer.class) ) {
        return (GenericObjectInterface<T>) new IntegerObject();
    }
} 

这将导致未经检查的强制转换警告,但您可以向自己证明它是安全的,从而抑制警告或忽略它。

于 2011-09-23T14:48:25.760 回答
1

通常,工厂不是作为泛型实现的,因为您无法检查泛型的类型以确定要创建的对象的类型(您不能执行 T.getClass),这就是@Mark 的示例导致类被传入的原因作为论据。

我认为,通常你会有多个混凝土工厂。一个用于您打算支持的每种数字类型。

public interface AbstractFactoryInterface<T extends Number> {
    public GenericObjectInterface<T> createGenericObject();
}


class IntegerFactory implements AbstractFactoryInterface<Integer>...
class LongFactory implements AbstractFactoryInterface<Long>...

然后您可以创建一个 Map<Class, AbstractFactoryInterface>...

Map<Class, AbstractFactoryInterface> myMap = ...;
myMap.put(Integer.class, new IntegerFactory());
myMap.put(Long.class, new LongFactory ());
于 2011-09-23T15:03:58.880 回答
1

铸造在这里非常好。如果c==Integer.class, 那么T=Integer, 转换GOI<Object>GOI<T>是绝对正确的。这是一个已检查的强制转换,因为您在强制转换之前已经检查T=Integer过,因此可以合法地抑制未检查的警告。

于 2011-09-23T19:23:32.503 回答