如何用Java中的泛型实现工厂模式? [英] How to implement factory pattern with generics in Java?

查看:889
本文介绍了如何用Java中的泛型实现工厂模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个通用界面处理程序

public interface Handler<T> {
  void handle(T obj);
}

我可以有n个这个接口的实现。假设我现在有以下2个实现。一个处理String对象和另一个句柄的日期

I can have n implementations of this interface. Let's say I have following 2 implementations for now. One which handles String objects and another handles Date

public class StringHandler implements Handler<String> {
  @Override
  public void handle(String str) {
    System.out.println(str);
  }
}

public class DateHandler implements Handler<Date> {
  @Override
  public void handle(Date date) {
    System.out.println(date);
  }
}

我想写一个工厂,它将返回处理程序实例基于类类型。这样的事情:

I want to write a factory which will return handler instances based on the class type. Something like this :

class HandlerFactory {
  public <T> Handler<T> getHandler(Class<T> clazz) {
    if (clazz == String.class) return new StringHandler();
    if (clazz == Date.class) return new DateHandler();
  }
}

我在这家工厂遇到以下错误:

I get following error in this factory :


类型不匹配:无法从 StringHandler 转换为 Handler< ; T>

Type mismatch: cannot convert from StringHandler to Handler<T>

如何解决此问题?

推荐答案

简单解决方案

您可以保存映射类< T> - >处理器< T> 地图中。类似于:

You could save your mappings Class<T> -> Handler<T> in a Map. Something like:

Map<Class<T>, Handler<T>> registry = new HashMap<>();

public void registerHandler(Class<T> dataType, Class<? extends Handler> handlerType) {
    registry.put(dataType, handlerType);
}

public <T> Handler<T> getHandler(Class<T> clazz) {
  return registry.get(clazz).newInstance();
}

在某些地方,初始化处理程序(可能在工厂本身):

In some place, initialize handlers (could be in the factory itself):

factory.registerHandler(String.class, StringHandler.class);
factory.registerHandler(Date.class, DateHandler.class);

在其他地方,您可以创建并使用它们:

And in another place, you create and use them:

Handler<String> stringhandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);

更复杂的解决方案

您可以使用反射扫描类,而不是手动注册映射 Class< T> - >处理程序< T> ,使用反射执行。

You can "scan" classes using reflection and, instead of register manually the mappings Class<T> -> Handler<T>, do it using reflection.

for (Class<? extends Handler> handlerType : getHandlerClasses()) {
    Type[] implementedInterfaces = handlerType.getGenericInterfaces();
    ParameterizedType eventHandlerInterface = (ParameterizedType) implementedInterfaces[0];
    Type[] types = eventHandlerInterface.getActualTypeArguments();
    Class dataType = (Class) types[0]; // <--String or Date, in your case
    factory.registerHandler(dataType, handlerType);
}

然后,您可以像上面一样创建和使用它们:

Then, you create and use them like above:

Handler<String> stringhandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);

要实现 getHandlerClasses(),请查看可扫描。对于每个班级,您必须检查它是否是处理程序

To implement getHandlerClasses(), look at this to scan all classes in your jar. For each class, you have to check if it is a Handler:

if (Handler.class.isAssignableFrom(scanningClazz) //implements Handler
    && scanningClazz.getName() != Handler.class.getName()) //it is not Handler.class itself
{
        //is a handler!
}

希望有所帮助!

这篇关于如何用Java中的泛型实现工厂模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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