创建一个在Java中具有附加功能的包装类。

huangapple go评论70阅读模式
英文:

create a wrapper class with additional features in java

问题

I want to create a wrapper class over another class so that it hides the functionality of the wrapped class and also the wrapper provides certain methods of its own.

For example, let's say we have class A as:

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

Now I want another class B which wraps class A, so that it has its own methods, and also if someone asks for a method of class A, it should delegate it to class A.

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

I can't use inheritance (i.e., B extends A) because it's not easy with my use case (where A has a concrete constructor with some parameters which we can't get ... but we can get the object of A).

I can't simply delegate each function in A using an object of A (because there are several functions in A).

Is there any other way to obtain class B with said restrictions?

Important Note: Class A is handled by someone else. We can't change any part of it.

英文:

I want to create a wrapper class over another class so that it hides the functionality of wrapped class and also the wrapper provides certain methods of its own.

For example, lets say we have class A as

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

Now I want another class B which wraps class A, so that it has its own methods, and also if someone asks method of class A, it should delegate it to 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 ... }
}

I can't use inheritance (i.e B extends A) because its not easy with my use case (where A has concrete constructor with some parameters which we can't get ... but we can get the object of A).

I can't simply delegate each function in A using object of A (because there are several functions in A)

Is there any other way to obtain class B with said restrictions?

Important Note: Class A is handled by someone else. We can't change any part of it.

答案1

得分: 0

以下是您要翻译的内容:

这可以很容易地通过CGLIB完成,但需要进行一些修改。请考虑这些修改是否比实际方法的委托更难实现。

  1. 您需要扩展这些类,可以通过向类A添加无参数构造函数来完成,我们仍然会委托所有方法,所以不必担心无法访问的参数,我们不担心缺少的数据,我们只想要这些方法。

  2. 您需要在类路径上拥有CGLIB cglib maven,也许您已经拥有它了。

然后

A将如下所示

public class A {

    private String arg = "test";

    public A() {
        // 仅用于扩展
    }

    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(); // 将打印出delegated

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

英文:

This can be easily done with CGLIB but will require few modifications. Consider if those modifications may not be harder to do that the actual delegation of the methods.

  1. You need to extend the classes, this can be done by adding the no arg constructor to class A, we will still delegate all the methods so do not worry about unreachable params, we are not worried about missing data, we just want the methods

  2. You need to have CGLIB on you classpath cglib maven, maybe you already have it

Than

A would look like

public class A {

    private String arg = &quot;test&quot;;

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

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

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

B would look like

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(&quot;a&quot;);
    }


    @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&lt;?&gt; clazz, Method method) throws Throwable {
        try {
            return clazz.getDeclaredMethod(method.getName(), method.getParameterTypes());
        } catch (NoSuchMethodException e) {
            return null;
        }
    }

}

That you can do

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

This is not very nice solution and you probably do not need it, please consider refactoring your code before doing this. This should be used only in very specific cases.

答案2

得分: 0

以下是翻译好的部分:

你所描述的是GOF提出的装饰器模式。有许多关于它的互联网资源。它类似于代理模式(正如Pavel Polivka的回答中所提到的),但意图不同。你需要装饰器模式:
> 动态地将附加职责添加到对象上。装饰器为扩展功能提供了一种灵活的替代方法,而不是通过子类化。sourcemaking.com

正如你在评论中所写的
> 类A继承自包含多个方法的单一接口

我假设A实现了AIntf并包含了你想要的所有方法。

public class BDecorator implements AIntf {
    private A delegate;

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

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

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

> 类A中有几个函数,我不想手动编写每个方法在B中。

Java是一种冗长的语言。然而,你不需要手动完成这项工作,每个体面的IDE都提供了委托方法的自动生成。因此,无论方法的数量多少,都只需要5秒钟的时间。

> 类A不在我的控制之下,我的意思是有人可能会更新其方法签名,在这种情况下,我需要监视类A并对我的类B进行更改。

如果你创建了B,你就有责任管理它。你至少会注意到任何变化。而且再次提醒,你可以在瞬间通过IDE的帮助重新生成已更改的方法。

英文:

What you have described is a Decorator pattern coined by GOF. There is plenty of sources on the Internet about it. It is similar to the Proxy pattern (as in the answer of Pavel Polivka) but the intent is different. You need the Decorator pattern:
> Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. sourcemaking.com

As you have written in a comment
> class A inherits from single interface containing several methods

I assume A implements AIntf and contains all the methods you want.

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 is a verbose language. However, you don't need to do this by hand, every decent IDE provides automatic generation of delegate methods. So it will take you 5 seconds for any amount of methods.

> 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.

If you create B you are responsible for it. You at least notice if anything changed. And once again, you can re-generate the changed method with the help of an IDE in an instant.

huangapple
  • 本文由 发表于 2020年8月5日 22:22:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/63267244.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定