动态调度和通用接口工厂
Dynamic dispatch and generic interface factories
我应该如何在 Factory
中实现 RequestFactory
接口,以便我可以根据传递的类型创建 StringRequest
或 IntRequest
?
本质上,我想动态地创建参数化抽象 class 的具体 classes 实例,这在 Java 中可能吗?
public class Main {
public static void main(String[] args) {
Integer mInt = 10;
String mString = "string";
MyRequest mReq1 = new Factory<>(mString).getRequest();
mReq1.PerformMyRequest();
MyRequest mReq2 = new Factory<>(mInt).getRequest();
mReq2.PerformMyRequest();
}
}
class Factory<T> implements RequestFactory<T> {
private final MyRequest<T> Req;
public Factory(T body) {
Req = create(body);
}
public MyRequest<T> getRequest() {
return Req;
}
@Override
// How do I implement the interface here so
// that correct factory is invoked depending on T
// so that I can return either StringRequest or IntRequest
public MyRequest<T> create(T body) {
return null;
}
}
工厂接口:
// Interface
interface RequestFactory<T> {
MyRequest<T> create(T body);
}
// Concrete specialized factories
class StringFactory implements RequestFactory<String> {
@Override
public StringRequest create(String body) {
return new StringRequest(body);
}
}
class IntFactory implements RequestFactory<Integer> {
@Override
public IntRequest create(Integer body) {
return new IntRequest(body);
}
}
通用抽象 class 及其两个具体子项
// ======================================================
// AbstractClass
abstract class MyRequest<T> {
T mVal;
MyRequest(T body) {
mVal = body;
}
public void PerformMyRequest() {
System.out.println("-> From abstract: " + mVal);
}
}
// Concrete classes that I'd like to automatically
// create using the factory above
class StringRequest extends MyRequest<String> {
StringRequest(String body) {
super(body);
}
public void PerformMyRequest() {
super.PerformMyRequest();
System.out.println(" -> From StringRequest");
}
}
class IntRequest extends MyRequest<Integer> {
IntRequest(Integer body) {
super(body);
}
public void PerformMyRequest() {
super.PerformMyRequest();
System.out.println(" -> From IntRequest");
}
}
java无法做到这一点。您可以通过编写 "MetaFactory"(即工厂的工厂)来完成此操作,它会进行类型检查以选择要创建的工厂实现和 return.
public final class RequestMetaFactory {
public RequestFactory<T> newFactory(T req) {
if (req instanceof String) {
return new StringRequestFactory((String)req);
}
if (req instanceof Integer) {
return new IntegerRequestFactory((Integer)req);
}
throw new IllegalArgumentException(req.getClass() + " not a supported arg type");
}
}
通过执行 SPI 查找以查找实际的 RequestFactory 实例并询问每个实例支持的类型,这可以变得更加复杂。
在Java中,泛型类型仅用于编译时类型检查,一般在运行时不可用。这意味着您不能根据 create
方法中的 T
做出任何运行时决策。
你也不能仅仅从知道你想要 RequestFactory<String>
跳到知道 "the" 为此目的的具体实现是 StringFactory
。可能还有其他 类 也扩展了 RequestFactory<String>
,因此您必须在某处明确声明 StringFactory
是您想要的。如果这是 C++,您可以编写模板特化来表示 "this is the implementation for a RequestFactory<String>
",但这对于泛型是不可能的。
Brett Okken 已经指出了一种可能的替代解决方案,它与我所写的非常相似,因此我将仅指出他的回答。
我应该如何在 Factory
中实现 RequestFactory
接口,以便我可以根据传递的类型创建 StringRequest
或 IntRequest
?
本质上,我想动态地创建参数化抽象 class 的具体 classes 实例,这在 Java 中可能吗?
public class Main {
public static void main(String[] args) {
Integer mInt = 10;
String mString = "string";
MyRequest mReq1 = new Factory<>(mString).getRequest();
mReq1.PerformMyRequest();
MyRequest mReq2 = new Factory<>(mInt).getRequest();
mReq2.PerformMyRequest();
}
}
class Factory<T> implements RequestFactory<T> {
private final MyRequest<T> Req;
public Factory(T body) {
Req = create(body);
}
public MyRequest<T> getRequest() {
return Req;
}
@Override
// How do I implement the interface here so
// that correct factory is invoked depending on T
// so that I can return either StringRequest or IntRequest
public MyRequest<T> create(T body) {
return null;
}
}
工厂接口:
// Interface
interface RequestFactory<T> {
MyRequest<T> create(T body);
}
// Concrete specialized factories
class StringFactory implements RequestFactory<String> {
@Override
public StringRequest create(String body) {
return new StringRequest(body);
}
}
class IntFactory implements RequestFactory<Integer> {
@Override
public IntRequest create(Integer body) {
return new IntRequest(body);
}
}
通用抽象 class 及其两个具体子项
// ======================================================
// AbstractClass
abstract class MyRequest<T> {
T mVal;
MyRequest(T body) {
mVal = body;
}
public void PerformMyRequest() {
System.out.println("-> From abstract: " + mVal);
}
}
// Concrete classes that I'd like to automatically
// create using the factory above
class StringRequest extends MyRequest<String> {
StringRequest(String body) {
super(body);
}
public void PerformMyRequest() {
super.PerformMyRequest();
System.out.println(" -> From StringRequest");
}
}
class IntRequest extends MyRequest<Integer> {
IntRequest(Integer body) {
super(body);
}
public void PerformMyRequest() {
super.PerformMyRequest();
System.out.println(" -> From IntRequest");
}
}
java无法做到这一点。您可以通过编写 "MetaFactory"(即工厂的工厂)来完成此操作,它会进行类型检查以选择要创建的工厂实现和 return.
public final class RequestMetaFactory {
public RequestFactory<T> newFactory(T req) {
if (req instanceof String) {
return new StringRequestFactory((String)req);
}
if (req instanceof Integer) {
return new IntegerRequestFactory((Integer)req);
}
throw new IllegalArgumentException(req.getClass() + " not a supported arg type");
}
}
通过执行 SPI 查找以查找实际的 RequestFactory 实例并询问每个实例支持的类型,这可以变得更加复杂。
在Java中,泛型类型仅用于编译时类型检查,一般在运行时不可用。这意味着您不能根据 create
方法中的 T
做出任何运行时决策。
你也不能仅仅从知道你想要 RequestFactory<String>
跳到知道 "the" 为此目的的具体实现是 StringFactory
。可能还有其他 类 也扩展了 RequestFactory<String>
,因此您必须在某处明确声明 StringFactory
是您想要的。如果这是 C++,您可以编写模板特化来表示 "this is the implementation for a RequestFactory<String>
",但这对于泛型是不可能的。
Brett Okken 已经指出了一种可能的替代解决方案,它与我所写的非常相似,因此我将仅指出他的回答。