Jas*_*n S 5 java oop polymorphism api-design
我正在开发一个API设计,并且有一些关于Java和多态的东西,直到现在我都没想过.如果我创建这样的API:
interface FooFactory
{
public Foo getFoo();
}
interface Foo
{
public void sayFoo();
}
Run Code Online (Sandbox Code Playgroud)
那么我的FooFactory
实现可以依赖的唯一的东西就是Foo
实现.如果我决定提供一些增强的方法,像这样:
interface EnhancedFoo extends Foo
{
public void patHeadAndRubBelly();
}
class EnhancedFooImpl implements EnhancedFoo
{
... implementation here ...
}
class EnhancedFooFactoryImpl implements FooFactory
{
@Override public EnhancedFoo getFoo() { return new EnhancedFooImpl(); }
}
Run Code Online (Sandbox Code Playgroud)
我的API客户端可以使用该EnhancedFoo
接口的唯一方法是,如果他们获得一个Foo
接口并尝试将其转换为EnhancedFoo
.
我记得Microsoft在IUnknown
界面中处理COM的方式:
HRESULT QueryInterface(
[in] REFIID riid,
[out] void **ppvObject
);
Run Code Online (Sandbox Code Playgroud)
我们的想法是为你想要的接口传入一个GUID,如果成功,你会得到一个指针,保证你可以安全地将它转换为你想要的接口.
我可以用Java以类型安全的方式做类似的事情:
interface FooFactory
{
public <T extends Foo> T getFoo(Class<T> fooClass);
}
Run Code Online (Sandbox Code Playgroud)
我在请求时提供一个实现,它返回所需子接口的实例,如果没有可用则返回null.
我的问题是:
Foo
我的例子中的方法而不是任何EnhancedFoo
方法)澄清:客户端代码不会知道工厂实现.(假设它使用依赖注入或某些服务提供者体系结构,如java ServiceLoader
或NetBeans Lookup
.)因此,作为客户端,我不知道可用的是什么.工厂可能可以访问多个Foo
衍生产品,我希望客户端能够请求它想要的功能集,并且要么得到它,要么它将不得不依赖于基本Foo
功能.
我想对我来说困难的部分是这里存在运行时依赖性......纯静态类型安全方法,其中所有内容都在编译时修复,这意味着我只能依赖于该基本Foo
功能.这种方法对我来说很熟悉,但后来我失去了可能的增强功能.虽然更动态/机会主义的方法可以利用这些功能,但我不确定构建使用它的系统的正确方法.
您可以简单地使用泛型声明您的工厂,并将其余部分保留原样:
static interface FooFactory {
public <T extends Foo> T getFoo();
}
Run Code Online (Sandbox Code Playgroud)
然后由于类型推断,这将编译:
FooFactory f = new EnhancedFooFactoryImpl();
EnhancedFoo e = f.getFoo();
Run Code Online (Sandbox Code Playgroud)
(这在 Java 8 之前可能不起作用)
如果FooFactory
不是您所期望的,该行将EnhancedFoo e = f.getFoo();
抛出一个ClassCastException
。