我有一个通用接口处理程序
public interface Handler<T> {
void handle(T obj);
}
我可以有n个这个接口的实现。假设我现在有以下两个实现。一个处理字符串对象,另一个处理日期
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);
}
}
我想写一个工厂,它将根据类类型返回处理程序实例。比如:
class HandlerFactory {
public <T> Handler<T> getHandler(Class<T> clazz) {
if (clazz == String.class) return new StringHandler();
if (clazz == Date.class) return new DateHandler();
}
}
我在这个工厂里遇到了以下错误:
类型不匹配:无法从StringHandler
转换为Handler
如何解决这个问题?
使用泛型类型的全部目的是共享实现。如果处理程序接口的n实现差异太大,无法共享,那么我认为没有任何理由使用define这个通用接口。您更希望将StringHandler和DateHandler作为顶级类。
另一方面,如果实现可以共享(如您的示例所示),那么工厂自然会工作:
public class Main {
static public interface Handler<T> {
void handle(T obj);
}
static public class PrintHandler<T> implements Handler<T> {
@Override
public void handle(T obj) {
System.out.println(obj);
}
}
static class HandlerFactory {
public static <T> Handler<T> getHandler() {
return new PrintHandler<T>();
}
}
public static void main(String[] args) {
Handler<String> stringHandler = HandlerFactory.getHandler();
Handler<Date> dateHandler = HandlerFactory.getHandler();
stringHandler.handle("TEST");
dateHandler.handle(new Date());
}
}
你的问题是编译器无法跳到结果类型正确的事实上。
为了帮助编译器,您可以让工厂委托构造。尽管这看起来很奇怪,也很笨拙,但它确实能够在不牺牲(比如施法或使用)的情况下正确地维护类型安全性
或原始类型。
public interface Handler<T> {
void handle(T obj);
}
public static class StringHandler implements Handler<String> {
@Override
public void handle(String str) {
System.out.println(str);
}
}
public static class DateHandler implements Handler<Date> {
@Override
public void handle(Date date) {
System.out.println(date);
}
}
static class HandlerFactory {
enum ValidHandler {
String {
@Override
Handler<String> make() {
return new StringHandler();
}
},
Date {
@Override
Handler<Date> make() {
return new DateHandler();
}
};
abstract <T> Handler<T> make();
}
public <T> Handler<T> getHandler(Class<T> clazz) {
if (clazz == String.class) {
return ValidHandler.String.make();
}
if (clazz == Date.class) {
return ValidHandler.Date.make();
}
return null;
}
}
public void test() {
HandlerFactory factory = new HandlerFactory();
Handler<String> stringHandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);
}
简单解决方案
您可以保存映射类
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();
}
在某些地方,初始化处理程序(可能在工厂本身):
factory.registerHandler(String.class, StringHandler.class);
factory.registerHandler(Date.class, DateHandler.class);
在另一个地方,你创造并使用它们:
Handler<String> stringhandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);
更复杂的解决方案
您可以使用反射“扫描”类,而不是手动注册映射
类
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);
}
然后,像上面一样创建和使用它们:
Handler<String> stringhandler = factory.getHandler(String.class);
Handler<Date> dateHandler = factory.getHandler(Date.class);
要实现
getHandlerClasses()
,请查看以下内容以扫描jar
中的所有类。对于每个类,您必须检查它是否是处理程序
:
if (Handler.class.isAssignableFrom(scanningClazz) //implements Handler
&& scanningClazz.getName() != Handler.class.getName()) //it is not Handler.class itself
{
//is a handler!
}
希望有帮助!
问题内容: 我希望返回具有适当泛型的用户界面实例。我陷入下面的错误示例中: 绑定不匹配:BallUserInterfaceFactory类型的通用方法getBaseballUserInterface(BASEBALL)不适用于参数(BALL)。推断的类型BALL不能有效替代有界参数 我了解它不能保证BALL是棒球,因此getBaseballUserInterface方法调用上存在参数类型不匹配的情
我需要初始化类的泛型类型,但无法初始化。就我所做的研究而言,工厂设计模式更适合进行这种泛型类型初始化,但我不知道如何进行。 这是我的通用服务; 当您注意到我的给出了一个错误,为了实现这一点,我需要找到一种初始化Entity的方法。我该如何实现这一点?
我使用方法遇到了麻烦,无论我用什么方法尝试,我都得到了: null 我的代码:
问题内容: 我有一个像这样的通用接口: 此接口具有有限的实例,因此最好将它们实现为枚举值。问题是那些实例具有不同类型的值,因此我尝试了以下方法,但无法编译: 有什么想法吗? 问题答案: 你不能 Java不允许在枚举常量上使用泛型类型。但是,它们允许用于枚举类型: 在这种情况下,你可以做的是为每个泛型类型都拥有一个枚举类型,或者通过将其设为一个类来“伪造”一个枚举: 不幸的是,它们都有缺点。
我正在制作一个餐厅应用程序,我需要使用泛型类型参数。工作流程如下:客户机(观察者)订购食物(界面),FoodFactory返回具体类型(如热狗、薯片等),然后客户机(观察者)收到通知。我需要在这个练习中使用一些课程。在本练习中,类型参数
问题内容: 我正在尝试编写工厂模式以在程序中创建MainMode或TestMode。我以前用来创建这些对象的代码是: 我的游戏(游戏)将根据布尔值(isMode)创建MainMode对象或TestMode对象。如您所见,我正在向我的TestMode对象(randNo())添加一个额外的值。在TestMode中使用此值,以允许用户输入自己的“随机数”,而在MainMode构造函数中,则是随机生成的。