Java:如何为不可修改的外部库类定义公共接口实现统一调用
通用实现方案
以下为不同场景下的优雅实现方式:
方案1:静态适配器模式(推荐,类型安全、性能最优)
这是最符合开闭原则的实现,无运行期开销,编译期即可完成类型校验。
- 先定义包含所需方法的公共接口:
public interface GetterCapable { // 按实际返回值调整返回类型,这里用Object做示例 Object getGetter1(); Object getGetter2(); }
- 为外部类A、B分别实现适配器,包装实例并实现公共接口:
// A类适配器 public class AAdapter implements GetterCapable { private final A target; public AAdapter(A target) { this.target = target; } @Override public Object getGetter1() { return target.getter1(); } @Override public Object getGetter2() { return target.getter2(); } } // B类适配器 public class BAdapter implements GetterCapable { private final B target; public BAdapter(B target) { this.target = target; } @Override public Object getGetter1() { return target.getter1(); } @Override public Object getGetter2() { return target.getter2(); } }
如果使用JDK 16及以上版本,可以用record简化适配器代码:
public record AAdapter(A target) implements GetterCapable { @Override public Object getGetter1() { return target.getter1(); } @Override public Object getGetter2() { return target.getter2(); } } public record BAdapter(B target) implements GetterCapable { @Override public Object getGetter1() { return target.getter1(); } @Override public Object getGetter2() { return target.getter2(); } }
- 你的通用方法直接接收公共接口作为参数:
public void yourBusinessMethod(GetterCapable getterCapable) { // 直接调用接口方法,完全不需要感知底层是A还是B的实例 Object val1 = getterCapable.getGetter1(); Object val2 = getterCapable.getGetter2(); // 此处编写你的业务逻辑即可 }
调用时只需用适配器包装对应实例即可:
yourBusinessMethod(new AAdapter(aInstance)); yourBusinessMethod(new BAdapter(bInstance));
方案2:动态代理(减少重复代码,适合多类型场景)
如果需要适配的外部类数量较多,不想写大量重复的适配器代码,可以用动态代理自动生成适配逻辑:
public class GetterAdapter { public static GetterCapable adapt(Object target) { if (!(target instanceof A || target instanceof B)) { throw new IllegalArgumentException("Unsupported type: " + target.getClass().getName()); } return (GetterCapable) Proxy.newProxyInstance( GetterCapable.class.getClassLoader(), new Class[]{GetterCapable.class}, (proxy, method, args) -> target.getClass().getMethod(method.getName()).invoke(target) ); } }
调用方式更简洁:
yourBusinessMethod(GetterAdapter.adapt(aInstance)); yourBusinessMethod(GetterAdapter.adapt(bInstance));
注意:该方案有极小的运行期反射开销,且类型校验需要到运行期才能完成。
方案3:动态语言鸭子类型(适用于Python/JavaScript等无强类型约束的语言)
如果使用动态语言,无需额外适配,直接调用对应方法即可:
def your_business_method(target): val1 = target.getter1() val2 = target.getter2() # 业务逻辑
注意:该方案没有编译期类型检查,若传入的实例没有对应方法会在运行期抛出异常。
内容的提问来源于stack exchange,提问作者NoName
相关产品推荐
相关产品推荐

