在 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 轻松完成,但需要进行少量修改。考虑这些修改是否比方法的实际委托更难。
你需要扩展classes,这可以通过向classA添加无参数构造函数来完成,我们仍然会委托所有方法所以不要担心无法访问的参数,我们不担心丢失数据,我们只需要方法
您需要在 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 的帮助下立即更改方法。
我想在另一个 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 轻松完成,但需要进行少量修改。考虑这些修改是否比方法的实际委托更难。
你需要扩展classes,这可以通过向classA添加无参数构造函数来完成,我们仍然会委托所有方法所以不要担心无法访问的参数,我们不担心丢失数据,我们只需要方法
您需要在 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 的帮助下立即更改方法。