您可以使用接口并使您的类型适应它。
界面:
public interface Crushable {
public void crush();
}
示例调用:
public class Crusher {
public static void crush(Crushable crushable) {
crushable.crush();
}
}
示例适配器工厂方法:
public final class Dreams {
public static Crushable asCrushable(final Dream dream) {
class DreamCrusher implements Crushable {
@Override
public void crush() {
dream.crush();
}
}
return new DreamCrusher();
}
private Dreams() {}
}
消费者代码如下所示:
Dream dream = new Dream();
Crushable crushable = Dreams.asCrushable(dream);
Crusher.crush(crushable);
如果你有很多类型需要适应,你可以考虑反射。这是一个使用Proxy类型的(未优化的)适配器工厂:
public final class Crushables {
private static final Class<?>[] INTERFACES = { Crushable.class };
public static Crushable adapt(final Object crushable) {
class Handler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return crushable.getClass()
.getMethod(method.getName(), method.getParameterTypes())
.invoke(crushable, args);
}
}
ClassLoader loader = Thread.currentThread()
.getContextClassLoader();
return (Crushable) Proxy.newProxyInstance(loader, INTERFACES, new Handler());
}
private Crushables() {}
}
对于 API 使用者来说,这并不难看:
Dream dream = new Dream();
Crushable crushable = Crushables.adapt(dream);
Crusher.crush(crushable);
但是,与反射一样,您牺牲了编译时类型检查。