使用泛型的工厂模式

Factory pattern using generics

我想构建一个 class 来缓存 class 使用 Map 的 CachedObject 类型。

public class CachedObject {
    protected Long id;
    public CachedObject(Long id) {
        this.id = id;
    }
}

下面是工厂class.

public class CachedObjectFactory<T extends CachedObject> {

private static Logger logger = LoggerFactory.getLogger(CachedObjectFactory.class);
private Map<Long, T> cacheMap = new HashMap<>();

public T get(Class<T> type, Long id) throws CachedObjectInstantiationException {
    T cachedObject = cacheMap.get(id);
    try {
        if(cachedObject == null) {
            cachedObject = type.getDeclaredConstructor().newInstance(id);
        }
    } catch(Exception e) {
        throw new CachedObjectInstantiationException(e.getMessage());
    }
    return cachedObject;
}

}

我有一个 class 扩展 CacheableObject 如下:

@Component
class X extends CachedObject {
   
    public X(Long id) {
           super(id);
       }
       ....

}

当我尝试使用工厂中的 get 方法创建扩展 CachedObject 的 class X 实例时,如下所示:(请注意 cachedObjectFactory 是使用 Spring 自动装配的)

@Component
class Y extends CachedObject {

       CachedObjectFactory<CachedObject> cachedObjectFactory;
       Y(Long id, CachedObjectFactory cachedObjectFactory) {
          super(id);
          this.cachedObjectFactory = cachedObjectFactory;
       } 
    
       public void someMethod() {
          X x = cachedFactory.get(X.class, id);
       }

}

我收到编译时错误“CachedObjectFactory 类型中的方法 get(Class, Long) 不适用于参数 (Class, Long)"。如何用工厂方法实例化一个对象X?

将一个字段声明为 CachedObjectFactory<CachedObject> 并没有任何意义——参数已经有 CachedObject 作为上限。

您可以通过将工厂更改为如下所示来编译代码:

public class CachedObjectFactory {

        private Map<Long, Object> cacheMap = new HashMap<>();

        public <T extends CachedObject> T get(Class<T> type, Long id) {
            T cachedObject = (T)cacheMap.get(id);
            try {
                if(cachedObject == null) {
                    cachedObject = type.getDeclaredConstructor().newInstance(id);
                }
            } catch(Exception e) {
                throw new RuntimeException(e.getMessage());
            }
            return cachedObject;
        }
    }

由于您将工厂用于许多 类,因此将其通用化并没有多大意义。

当然,如果 CachedObject 的不同子 类 的两个实例具有相同的 ID,您将获得运行时 ClassCastException.