在 java 中创建具有附加功能的包装器 class

create a wrapper class with additional features in java

我想在另一个 class 上创建一个包装器 class 以便它隐藏包装器 class 的功能并且包装器提供它自己的某些方法。

例如,假设我们有 class A as

public class A{
    void method1(){ ... do something ... }
    void method2(){ ... do something ... }
    void method3(){ ... do something ... }
}

现在我想要另一个 class B 包裹 class A,这样它就有自己的方法,而且如果有人问 class A 的方法,它应该委托它至 class A.

public class B{
     // if someone asks method1() or method2() or method3() ... it should delegate it to A
     
     // and also it has own methods
     void method4(){ ... do something ... }
     void method5(){ ... do something ... }
}

我不能使用继承(即 B 扩展 A),因为它对我的用例来说并不容易(其中 A 具有具体的构造函数,其中包含一些我们无法获取的参数......但我们可以获得A).

我不能简单地使用 A 的对象委托 A 中的每个函数(因为 A 中有几个函数)

是否有任何其他方式获得具有上述限制的class B?

重要提示:ClassA是别人处理的。我们无法更改它的任何部分。

这可以使用 CGLIB 轻松完成,但需要进行少量修改。考虑这些修改是否比方法的实际委托更难。

  1. 你需要扩展classes,这可以通过向classA添加无参数构造函数来完成,我们仍然会委托所有方法所以不要担心无法访问的参数,我们不担心丢失数据,我们只需要方法

  2. 您需要在 class路径 cglib maven 上安装 CGLIB,也许您已经安装了它

A 看起来像

public class A {

    private String arg = "test";

    public A() {
        // noop just for extension
    }

    public A(String arg) {
        this.arg = arg;
    }

    public void method1() {
        System.out.println(arg);
    }
}

B 看起来像

public class B extends A implements MethodInterceptor {

    private A delegate;

    private B(A delegate) {
        this.delegate = delegate;
    }

    public static B createProxy(A obj) {
        Enhancer e = new Enhancer();
        e.setSuperclass(obj.getClass());
        e.setCallback(new B(obj));
        B proxifiedObj = (B) e.create();
        return proxifiedObj;
    }

    void method2() {
        System.out.println("a");
    }


    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Method m = findMethod(this.getClass(), method);
        if (m != null) { return m.invoke(this, objects); }
        Object res = method.invoke(delegate, objects);
        return res;
    }

    private Method findMethod(Class<?> clazz, Method method) throws Throwable {
        try {
            return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
        } catch (NoSuchMethodException e) {
            return null;
        }
    }

}

你能做到

MyInterface b = B.createProxy(new A("delegated"));
b.method1(); // will print delegated

这不是一个很好的解决方案,您可能不需要它,请在执行此操作之前考虑重构您的代码。这应该只在非常特殊的情况下使用。

你所描述的是GOF创造的Decorator模式。互联网上有很多关于它的资源。它类似于代理模式(如 Pavel Polivka 的回答)但意图不同。您需要装饰器模式:

Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. sourcemaking.com

正如您在评论中所写

class A inherits from single interface containing several methods

我假定 A implements AIntf 并包含您想要的所有方法。

public class BDecorator implements AIntf {
    private A delegate;

    private BDecorator(A delegate) {
        this.delegate = delegate;
    }

    void method1(){ delegate.method1(); }
    // ...

    void method4(){ /* something new */ }

There are several functions in A, and I don't want to do tedious work of writing each method explicitly in B.

Java 是冗长的语言。但是,您不需要手动执行此操作,每个体面的 IDE 都提供自动生成委托方法。因此,无论使用多少种方法,都将花费您 5 秒的时间。

The class A is not in my control, I mean someone might update its method signatures, In that case I need to watch over class A and made changes to my class B.

如果您创建了 B,您将对此负责。您至少会注意到是否有任何变化。再一次,您可以 re-generate 在 IDE 的帮助下立即更改方法。