在复合/装饰模式中,外部容器会覆盖某些方法来更改行为,但对于其他方法,则必须委托给子组件。
ex:类A有10个方法,类B包含A但仅覆盖2个方法,然后B必须覆盖8个方法才可以委托给A内部的实例。 如何减少Java和Python中的样板代码?
编辑:我尝试不使B扩展为A,因为我尝试比继承更复杂。
答案 0 :(得分:0)
我希望您只是在问这样的事情。我将以decorator模式为例(但是您也可以将其应用于其他模式)。
class A implements Decorator{
@Override
public void decorate(){
System.out.print("Decorate A");
}
@Override
public void help(){
System.out.print("Help");
}
}
class B implements Decorator{
private Decorator member;
public B(Decorator decorator){
this.member = decorator;
}
@Override
public void decorate(){
member.decorate();
System.out.print("Decorate B");
}
@Override
public void help(){
//***you need the behaviour of A here
member.help();
}
}
Decorator d = new B(new A());
b.help();
所以在// **行中,如果您想在那里A的行为,只需执行B extends A
而不是扩展/实现抽象类/接口。然后,您无需委托。该行为将被继承。
但是,您想在其中执行成员方法的任何方式,使其保持更通用,并使运行时能够决定它,则必须委托。没有其他解决方案,因为该逻辑仅封装在成员类内部,并且在运行时注入实际成员之前,您不知道确切的类型。
您可以参考this示例,以了解如何使用lombok来实现这种装饰器模式委托。
public class RemovalCountingList<E> implements List<E> {
@Delegate(excludes = ExcludedListMethods.class)
private final List<E> delegate;
private final AtomicInteger removalCount = new AtomicInteger();
public RemovalCountingList(List<E> delegate) {
this.delegate = delegate;
}
@Override
public E remove(int index) {
System.out.println("Removal count: " + removalCount.incrementAndGet());
return delegate.remove(index);
}
@Override
public boolean remove(Object o) {
boolean isRemoved = delegate.remove(o);
if (isRemoved) {
System.out.println("Removal count: " + removalCount.incrementAndGet());
}
return isRemoved;
}
/**
* Excluded methods that Lombok will not implement, we will implement/override these methods.
*/
private abstract class ExcludedListMethods {
public abstract E remove(int index);
public abstract boolean remove(Object o);
}
}
public class ClientMain {
public static void main(String[] args) {
RemovalCountingList<String> cities = new RemovalCountingList<>(new ArrayList<>());
cities.add("London");
cities.add("Paris");
cities.add("Istanbul");
cities.add("Tokyo");
String removedCity = cities.remove(0);
System.out.println("Removed city: " + removedCity);
boolean isRemoved = cities.remove("Istanbul");
System.out.println("Is removed?: " + isRemoved);
}
}
它将帮助您删除样板代码。
答案 1 :(得分:0)
尽管Java语言本身没有可为您节省样板的功能,但您可以看看Lombok的@Delegate
注释here,以减少样板(这是Lombok项目所做的事情)。对于您在问题中的示例,可能看起来像这样
interface A {
void method1();
void method2();
// ... 8 more methods
}
public class B implements A {
private interface AOverride {
void method1();
}
@Delegate(types = A.class, excludes = AOverride.class)
private final A delegate;
public B(final A delegate) {
this.delegate = delegate;
}
@Override
public void method1() {
}
}
这里唯一令人讨厌的事情是,您将需要定义一个额外的类来指定要覆盖的方法,因为没有将方法名作为字符串的excludes-parameter(可能是一件好事,您希望编译时的安全性。
答案 2 :(得分:0)