工厂模式与java中的泛型

时间:2017-11-24 00:05:15

标签: java generics design-patterns abstract-factory

我在使用特定用例的泛型实现工厂时遇到了麻烦

我有模型类:

class BaseModel { }

class ModelA extends BaseModel { }

class ModelB extends BaseModel { }

相应的服务:

class Service<T extends BaseModel> { }

class ServiceA extends Service<ModelA> {}

class ServiceB extends Service<ModelB> {}

我的工厂类,根据它所服务的模型创建服务:

class Factory {
    private Map<Class<? extends BaseModel>, Class<? extends Service>> registry;

    Factory(){
        registry = new HashMap<>();
        registry.put(ModelA.class, ServiceA.class);
        registry.put(ModelB.class, ServiceB.class);
    }

    Service getService(Class<? extends BaseModel> clazz) throws IllegalAccessException, InstantiationException {
        return registry.get(clazz).newInstance();
    }
}

使用工厂的课程

class Handler<T extends BaseModel>{
    private Service<T> myService;

    Handler(Class<T> modelClass) {
        Factory fact = new Factory();
        try {
            myService = fact.getService(modelClass);
        } catch (IllegalAccessException | InstantiationException e) {
            e.printStackTrace();
        }
    }
}

我收到使用工厂获取服务的行的警告:

"Unchecked assignment 'Service' to 'Service<T>'"

我理解为什么会收到消息,因为getService方法返回Service,但我需要Service<T>并且对如何更改代码以获取Service<T>感到困惑

有什么建议吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

在这里,您可以将类捕获为T并返回它的实例(使用强制转换):

<T extends BaseModel> Service<T> getService(Class<T> clazz) throws IllegalAccessException, InstantiationException {
    return (Service<T>) registry.get(clazz).newInstance();
}

答案 1 :(得分:0)

Java泛型和继承有时会反直觉地交互,即Service<ModelA>Service<BaseModel>无关(就继承而言)。但是,您可以编写getService()的两个实现并显式调用服务构造函数(而不是通过反射)。您的处理程序将需要您的模型的实例,以便Java重写将为您选择正确的服务构造函数。

我在原始答案中没有想到的是:您需要捕获工厂中的所有BaseModel实现(覆盖将选择最具体的方法),并且还必须针对接口实现您的服务以拉动字符串在一起。

class BaseModel { }

class ModelA extends BaseModel { }

class ModelB extends BaseModel { }

interface Service { }

class ServiceImplementation<T extends BaseModel> implements Service { }

class ServiceFactory {
    public static Service getService(ModelA model) { return new ServiceImplementation<ModelA>(); }
    public static Service getService(ModelB model) { return new ServiceImplementation<ModelB>(); }
    public static Service getService(BaseModel model) { 
        throw new UnsupportedOperationException("Unknown Service Model");
    }
}

class Handler<T extends BaseModel> {
    private Service service;

    Handler(T model) {
        service = ServiceFactory.getService(model);
    }
}
相关问题