如何减少 composite/decorate 模式中的样板代码
How to cut down boilerplate code in composite/decorate pattern
在composite/decorate模式中,外部容器覆盖了一些方法来改变行为,但必须将其余方法委托给子组件。
ex:classA有10个方法,classB包含A但只重写了2个方法,那么B要重写8个方法只是为了委托给A里面的实例。
如何削减 Java 和 Python 中的样板代码?
编辑:我尽量不让 B 扩展 A,因为我试图比继承更复合。
我希望你只是在问这样的事情。我将以 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
而不是 extending/implementing 抽象 class/interface。那么你不需要委托。该行为将被继承。
但是如果您想在那里执行成员方法,使其更通用并赋予运行时决定它的能力,那么您必须委托。没有任何其他解决方案,因为该逻辑仅封装在成员 class 内,并且在运行时注入实际成员之前您不知道确切的类型。
可以参考this example, to see how this decorator pattern delegation can be achieved with 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);
}
}
它将帮助您删除样板代码。
虽然 Java 语言本身没有任何功能可以节省样板文件,但您可以查看 Lombok 的 @Delegate
annotation here 以减少样板文件(这就是项目龙目岛确实如此)。对于您问题中的示例,它可能看起来像这样
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() {
}
}
这里唯一烦人的事情是你需要定义一个额外的 class 来指定你想要覆盖哪些方法,因为没有 excludes-parameter 将 method-names 作为字符串(可能是一件好事,你想要 compile-time 安全)。
Lombok has experimental @Delegate
您可以尝试的功能:
public class DelegationExample {
private interface SimpleCollection {
boolean add(String item);
boolean remove(Object item);
}
@Delegate(types=SimpleCollection.class)
private final Collection<String> collection = new ArrayList<String>();
}
在composite/decorate模式中,外部容器覆盖了一些方法来改变行为,但必须将其余方法委托给子组件。
ex:classA有10个方法,classB包含A但只重写了2个方法,那么B要重写8个方法只是为了委托给A里面的实例。 如何削减 Java 和 Python 中的样板代码?
编辑:我尽量不让 B 扩展 A,因为我试图比继承更复合。
我希望你只是在问这样的事情。我将以 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
而不是 extending/implementing 抽象 class/interface。那么你不需要委托。该行为将被继承。
但是如果您想在那里执行成员方法,使其更通用并赋予运行时决定它的能力,那么您必须委托。没有任何其他解决方案,因为该逻辑仅封装在成员 class 内,并且在运行时注入实际成员之前您不知道确切的类型。
可以参考this example, to see how this decorator pattern delegation can be achieved with 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);
}
}
它将帮助您删除样板代码。
虽然 Java 语言本身没有任何功能可以节省样板文件,但您可以查看 Lombok 的 @Delegate
annotation here 以减少样板文件(这就是项目龙目岛确实如此)。对于您问题中的示例,它可能看起来像这样
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() {
}
}
这里唯一烦人的事情是你需要定义一个额外的 class 来指定你想要覆盖哪些方法,因为没有 excludes-parameter 将 method-names 作为字符串(可能是一件好事,你想要 compile-time 安全)。
Lombok has experimental @Delegate
您可以尝试的功能:
public class DelegationExample {
private interface SimpleCollection {
boolean add(String item);
boolean remove(Object item);
}
@Delegate(types=SimpleCollection.class)
private final Collection<String> collection = new ArrayList<String>();
}