Java 通用工厂模式-如何处理返回类型

Java 通用工厂模式-如何处理返回类型,java,generics,caching,Java,Generics,Caching,我试图用一个返回嵌套类型缓存的方法实现一个通用缓存工厂。 根据用于获取缓存实例的泛型类型参数,我面临在工厂中配置缓存的问题 我认为我的模型不适合在工厂中处理特定配置,但我希望在一个地方管理我的不同缓存。你建议怎么做 我的实施: public class GuavaCacheFactory { public static final String STRING_CACHE = "STRING_CACHE"; public static final String SERVICES_

我试图用一个返回嵌套类型缓存的方法实现一个通用缓存工厂。 根据用于获取缓存实例的泛型类型参数,我面临在工厂中配置缓存的问题

我认为我的模型不适合在工厂中处理特定配置,但我希望在一个地方管理我的不同缓存。你建议怎么做

我的实施:

public class GuavaCacheFactory {

    public static final String STRING_CACHE = "STRING_CACHE";
    public static final String SERVICES_LIST_CACHE = "SERVICES_LIST_CACHE";

    private volatile Map<String, Cache<String, ? extends Object>> cacheMap = Maps.newHashMap();

    public final <I extends Object> Cache<String, I> getCache(String name) {

        Cache<String, I> cache = (Cache<String, I>) cacheMap.get(name); // Unchecked cast :(

        if (cache == null) {
            if(STRING_CACHE.equals(name)) {
                cache = CacheBuilder.newBuilder()
                        .maximumSize(300)
                        .expireAfterWrite(12, TimeUnit.HOURS)                       
                        .removalListener(new RemovalListener<String, I>() {
                            @Override
                            public void onRemoval(RemovalNotification<String, I> notification) { // I -> String here
                                System.out.println("Remove parameter '" + notification + "' from cache with cause " + notification.getCause()));
                            }
                        })
                        .build();
            } else if(SERVICES_LIST_CACHE.equals(name)) {
                // I need to do an unchecked cast if I want to manipulate "List<Service>" instead of I
                cache = (Cache<String, I>) CacheBuilder.newBuilder()
                        .maximumWeight(1000L)
                        .weigher(new Weigher<String, List<Service>>() {
                            @Override
                            public int weigh(String key, List<Service> services) { // I -> List<Service>
                                return services != null ? services.size() : 0;
                            }
                        })
                        .expireAfterWrite(1, TimeUnit.HOURS)
                        .build();
                /*cache = CacheBuilder.newBuilder()
                        .maximumWeight(1000L)
                        .weigher(new Weigher<String, I>() {
                            @Override
                            public int weigh(String key, I services) { // I -> List<Service> here
                                return services != null ? services.size() : 0; // Error -> Here I want manipulate "List"
                            }
                        })
                        .expireAfterWrite(1, TimeUnit.HOURS)
                        .build();*/
            } else {
                throw new IllegalStateException("Cache with name '"+ name + "' cannot be created by GuavaCacheFactory");
            }
            cacheMap.put(name, cache);
        }

        return cache;
    }   
    // singleton
}
公共类瓜瓦切奇工厂{
公共静态最终字符串String\u CACHE=“String\u CACHE”;
公共静态最终字符串SERVICES\u LIST\u CACHE=“SERVICES\u LIST\u CACHE”;
private volatile Map cacheMap=Maps.newHashMap();
公共最终缓存getCache(字符串名称){
Cache Cache=(Cache)cacheMap.get(name);//未选中的强制转换:(
if(缓存==null){
if(字符串_CACHE.equals(名称)){
cache=CacheBuilder.newBuilder()
.最大尺寸(300)
.expireAfterWrite(12,时间单位:小时)
.removalListener(新的removalListener(){
@凌驾
公共void onremovation(RemovalNotification通知){//I->此处为字符串
System.out.println(“从缓存中删除参数“”+notification+”,原因为“+notification.getCause());
}
})
.build();
}else if(服务列表缓存等于(名称)){
//如果我想操纵“列表”而不是I,我需要执行未经检查的强制转换
cache=(cache)CacheBuilder.newBuilder()
.最大重量(1000L)
.秤(新秤(){
@凌驾
公共整数权重(字符串键,列表服务){//I->List
返回服务!=null?服务。大小():0;
}
})
.expireAfterWrite(1,时间单位为小时)
.build();
/*cache=CacheBuilder.newBuilder()
.最大重量(1000L)
.秤(新秤(){
@凌驾
公共整数权重(字符串键,I服务){//I->此处列出
return services!=null?services.size():0;//错误->这里我想要操纵“列表”
}
})
.expireAfterWrite(1,时间单位为小时)
.build()*/
}否则{
抛出新的IllegalStateException(“GuavacheFactory无法创建名为“+”名为“+”的缓存”);
}
cacheMap.put(名称、缓存);
}
返回缓存;
}   
//独生子女
}
我需要如何使用它:

Cache<String, String> stringCache = GuavaCacheFactory.getInstance().getCache(GuavaCacheFactory.STRING_CACHE);
String value = stringCache.get("str1", ...);
// or
Cache<String, List<Service>> listCache = GuavaCacheFactory.getInstance().getCache(GuavaCacheFactory.SERVICES_LIST_CACHE);
List<Service> services = listCache.get("serv1", ...);
Cache-stringCache=GuavaCacheFactory.getInstance().getCache(GuavaCacheFactory.STRING\u Cache);
String value=stringCache.get(“str1”,…);
//或
Cache listCache=GuavaCacheFactory.getInstance().getCache(GuavaCacheFactory.SERVICES\u LIST\u Cache);
List services=listCache.get(“serv1”,…);

我知道我想用什么类型取决于我的名字。没有更好的解决方案来解决我的问题?

您可以将标识缓存类型的字符串常量替换为预期缓存的实际类型。这适用于非类型类,如
String
。对于服务列表,您必须定义自己的类才能使其工作:

public class ServiceList extends List<Service> { }

public class GuavaCacheFactory {

    public final <I> Cache<String, I> getCache(Class<I> cacheType) {
        if cacheType.equals(String.class) {
            // ...
        } else if cacheType.equals(ServiceList.class) {
            // ...
        }
}
公共类ServiceList扩展列表{}
公共级瓜瓦切奇工厂{
公共最终缓存getCache(类cacheType){
如果cacheType.equals(String.class){
// ...
}如果cacheType.equals(ServiceList.class)为else,则为{
// ...
}
}
然后像这样使用它:

GuavaCacheFactory f = GuavaCacheFactory.getInstance()

// String-Cache
Cache<String, String> stringCache = f.getCache(String.class);
String value = stringCache.get("str1", ...);

// ServiceList-Cache
Cache<String, ServiceList> listCache = f.getCache(ServiceList.class);
ServiceList services = listCache.get("serv1", ...);
GuavaCacheFactory f=GuavaCacheFactory.getInstance()
//字符串缓存
Cache-stringCache=f.getCache(String.class);
String value=stringCache.get(“str1”,…);
//服务列表缓存
Cache listCache=f.getCache(ServiceList.class);
servicelistservices=listCache.get(“serv1”,…);
注意下面的代码:

private volatile Map<String, Cache<String, ? extends Object>> cacheMap = Maps.newHashMap();
private volatile Map cacheMap=Maps.newHashMap();
volatile在此没有帮助,它只影响对字段cacheMap的修改,而不影响映射本身。请查看Collections.synchronizedMap(…)或使getCache方法同步化

集中式配置或god对象反模式:您的应用程序最终需要多少不同的缓存?您可能有双向依赖关系:缓存用户依赖工厂来构造缓存,缓存工厂依赖用户定义所需的值类型,可能需要额外的侦听器,等等兴是相互依赖的,这不是一个分层的体系结构

强力缓存接口曝光:谁在使用缓存工厂?每个人都可以请求服务缓存并删除服务吗?也许服务缓存只是服务工厂需要的。那么为什么要将服务缓存公开和通用呢

易出错的重新配置:可能您希望将配置放在中心位置。但是,工厂中的某些配置选项不需要更改,或者缓存用户也需要更改。这是内聚性,但代码是分开的

因此,更好的解决方案是在需要缓存的地方实例化缓存

您还编写了一些已经存在于更高级缓存中的东西。请看一看或哪些缓存管理器或任何符合JCache的缓存实现


很抱歉回答得有点离题。

这是个不错的选择。但是如何在不强制转换对象的情况下使用生成器实例化我的
缓存
(返回