装饰器模式和委派模式之间的区别
2022-09-01 13:08:27
装饰器使用委派,但以非常具体的方式。
委托(或组合)与其说是一种模式,不如说是通过协调使用其他几个对象来构建复杂行为的一般方法。它通常以集合或静态方式使用。通过“设置或静态”,我的意思是这样的:
class Delegator {
private final ClassA a = new ClassA();
private final ClassB b = new ClassB();
public void doWork() {
a.setup();
final ResFromA resa = a.getRes();
b.setup();
b.consume(resa);
}
}
请注意,委托人不与 ClassA 或 ClassB 共享任何类型或接口,并且知道 a 和 b 的确切类型。
装饰器是一种动态方式,用于在运行时使用委派向逻辑实体添加行为。在 Decorator 中,所有实体共享一个公共接口,并使用委派来连接其工作。
public interface Item {
public void drawAt(final int x, final int y);
}
public class CircleAround implements Item {
private final Item wrapped;
private final int radius;
public CircleAround(public final Item wrapped, public final int radius) {
this.wrapped = wrapped;
this.radius = radius;
}
public void drawAt(final int x, final int y) {
// First handle whatever we are wrapping
wrapped.drawAt(x,y);
// Then add our circle
Graphics.drawCircle(x, y, radius);
}
}
请注意,与第一个示例不同,CircleAround 不知道它包装的项的确切类型,而是与它共享一个公共接口。
我认为“委派模式”将无法很好地测试什么是模式,什么不是模式。例如,人们仍然一直说“我知道工厂模式”。没有工厂模式。这是一个成语(参见詹姆斯·科普林(James Coplien)的高级C++)。该页面也非常弱。我不认为简单的授权是责任的颠倒。
当必须扩充要修饰的代码时,将使用修饰器。装饰器将自己包裹在被装饰者周围,并且仍然调用其方法,它只是在之前或之后做一些事情。这是你看到人们在Asspects出现时经常谈论Expercor的原因之一:这是一种依赖于中介而不是与其队列合作的模式。(这也是为什么在许多情况下,例如,当您没有源代码时,您必须使用装饰器。
装饰器在你想要获取一些有效的东西并让它做其他事情时效果最好,但根本不改变界面。假设您有一个存储库类,它提出了一个包含 CRUD 方法的接口。现在,您要添加缓存。您可以创建一个装饰存储库的缓存存储库,并且在读取时,它会在缓存中查找,如果它不存在,那么它将调用常规存储库方法,否则,它可以只返回缓存的副本。存储库类中没有更改任何代码,并且该类的用户对缓存一无所知。