桥接模式与装饰器模式
Posted
技术标签:
【中文标题】桥接模式与装饰器模式【英文标题】:bridge pattern vs. decorator pattern 【发布时间】:2011-01-16 07:22:21 【问题描述】:谁能为我详细说明 Bridge 设计模式和 Decorator 模式。我发现它在某些方面很相似。不知道怎么区分?
我的理解是,在Bridge中,实现与接口是分开的,一般只能应用一种实现。装饰器是一种包装器,你可以尽可能多地包装。
例如,
桥梁模式
class Cellphone
private:
Impl* m_OS; // a cellphone can have different OS
装饰器模式
class Shirt
private:
Person * m_p; //put a shirt on the person;
【问题讨论】:
【参考方案1】:装饰器应该与你正在装饰的对象的界面相匹配。即它具有相同的方法,并允许在传入的过程中截取参数,并在传出的过程中截取结果。您可以使用它为装饰对象提供额外的行为,同时保持相同的接口/合同。请注意,装饰器的接口可以提供附加功能来创建更有用的对象。
The Bridge 没有这样的限制。面向客户端的接口可能与提供实现的底层组件不同,因此它在客户端接口和实际实现(可能对客户端不友好,可能会发生变化等)之间架起桥梁。 )
【讨论】:
装饰器还可以为它正在装饰的界面添加便利方法。【参考方案2】:您的装饰器模式实现不太正确 - 如果您这样做会更有意义:
class PersonWearingShirt : IPerson
private:
IPerson * m_p; //put a shirt on the person;
这个想法是,当你装饰一个类时,你暴露了完全相同的接口。这使您的“装饰”实例看起来和行为与原始实例一样。这允许您使用多个装饰器多次包装一个实例,但对待它的处理方式与处理原始实例完全相同。
【讨论】:
这与代理设计模式有何不同? 装饰器旨在添加功能,“包装”现有对象。可以围绕单个对象分配多个装饰器(即:每个都包装前一个)。代理基本上充当中介,出于某种原因对其进行调整 - 通常是为了处理某些功能(资源分配)、延迟加载等 - 但通常,您有一个代理来间接提供对一个实例的访问。【参考方案3】:装饰者:
-
在运行时向对象添加行为。继承是实现这一功能的关键,这既是这种模式的优点也是缺点。
它增强了界面的行为。
装饰器可以被视为只有一个组件的退化组合。但是,装饰器增加了额外的职责 - 它不适合对象聚合。
装饰器支持递归组合
Decorator 类声明了与 LCD(最低类分母)接口的组合关系,并且该数据成员在其构造函数中初始化。
装饰器旨在让您无需子类化即可向对象添加职责
详情请参阅sourcemaking 文章。
来自wikipedia的装饰器UML图:
桥接模式:
-
桥是结构模式
抽象和实现在编译时不受约束
抽象和实现 - 两者都可以变化而不会对客户端产生影响
在以下情况下使用桥接模式:
-
您想要实现的运行时绑定,
由于耦合接口和众多实现,您拥有大量的类,
您想在多个对象之间共享一个实现,
您需要映射正交的类层次结构。
来自wikipedia的Bridge的UML图:
从UML图中,可以看出区别:
在Decorator模式中,Decorator实现的是Component,在运行时会被ConcreteComponent代替。
在桥接模式中,RedefinedAbstraction 没有实现 Implementor。相反,它使用组合,以便实现者可以在运行时动态变化,而无需客户知道。
与桥接模式不同,装饰器无法将抽象与实现分离。
一些更有用的帖子:
When to Use the Decorator Pattern?
When do you use the Bridge Pattern? How is it different from Adapter pattern?
【讨论】:
【参考方案4】:布赖恩是正确的。我将在概念上补充一点,客户端将“知道”它正在使用到底层对象的桥接,但是使用装饰器,客户端将无法知道它和目标对象之间存在装饰器层。
网桥的目的是创建一个抽象层来保护客户端。装饰器的目的是在客户不知道的情况下向对象添加功能。大多数装饰器会将所有函数调用直接传递给指向其父类的指针,但与装饰器旨在更改的内容直接相关的函数除外。
【讨论】:
以上是关于桥接模式与装饰器模式的主要内容,如果未能解决你的问题,请参考以下文章