如何在Java中使用泛型实现工厂模式?

问题描述 投票:11回答:7

我有一个通用接口Handler

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

我可以有该接口的n个实现。假设我目前有以下两种实现。一个处理String对象,另一个处理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);
  }
}

我想写一个工厂,它将根据类类型返回处理程序实例。像这样的东西:

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<T>

如何解决此问题?

java generics factory
7个回答
7
投票

简单解决方案>]


2
投票

您的问题是,编译器无法实现结果类型正确的事实。[]为了帮助编译器,您可以让工厂委托构造。尽管这看起来很奇怪并且毫无用处,但是它确实设法正确地保持了类型安全性,而没有牺牲例如强制转换或使用?或原始类型。


0
投票
您可以使用类似:

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

T是通用的,编译器无法在编译时将其映射。同样,使用.equals代替==更安全。

0
投票
使用泛型类型的重点是共享实现。如果您的Handler接口的n实现非常不同,以致于无法共享它们,那么我认为没有任何理由首先使用定义该通用接口。您只希望将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()); } }


-1
投票
基本上可以做到:

public Handler getHandler( Class clazz ){ if( clazz == String.class ) return new StringHandler(); if( clazz == Date.class ) return new DateHandler(); return null; } public static void main( String[] args ){ HandlerFactory handlerFactory = new HandlerFactory(); StringHandler handler = ( StringHandler )handlerFactory.getHandler( String.class ); handler.handle( "TEST" ); DateHandler handler2 = ( DateHandler )handlerFactory.getHandler( Date.class ); handler2.handle( new Date() ); }

输出:

-1
投票
我编辑了您的代码,并允许Eclipse“修复”错误,错误由此产生。

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


-1
投票
Yout HandlerFactory不知道T。如下所示使用您的工厂-

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

© www.soinside.com 2019 - 2024. All rights reserved.