桥接模式 vs 装饰器模式

13
谁能为我详细解释桥接模式和装饰器模式,因为我发现它们在某些方面很相似。我不知道如何区分它们?
我的理解是,桥接模式将实现与接口分离,通常只能应用一种实现。而装饰器则是一种包装器,可以包装尽可能多的内容。
例如:
桥接模式
class Cellphone {
private:
Impl* m_OS;         // a cellphone can have different OS

}

装饰器模式

class Shirt {
private:
Person * m_p;           //put a shirt on the person;

}
4个回答

20
装饰器应该匹配您要装饰的对象的接口。也就是说,它具有相同的方法,并允许拦截进入的参数以及返回结果时的拦截。您可以使用此功能为装饰对象提供附加行为,同时保持相同的接口/合同。请注意,装饰器的接口可以提供额外的功能来创建更有用的对象。
桥接模式没有这种限制。面向客户端的接口可以与提供实现的基础组件不同,因此它“桥接”了客户端的接口和实际实现(可能不适合客户端友好性、易于修改等)。

装饰器还可以向其所装饰的接口添加便捷方法。 - user177800

6

你的装饰器模式实现并不完全正确 - 如果你这样做会更有意义:

class PersonWearingShirt : IPerson
{
private:
    IPerson * m_p;           //put a shirt on the person;

}

装饰器的思想是,当你装饰一个类时,你暴露了完全相同的接口。这使得你的“装饰”实例看起来和原始实例一样。这允许你用多个装饰器多次包装一个实例,但与处理原始实例完全相同。


这与代理设计模式有何不同? - Thomas Matthews
装饰器旨在为现有对象添加功能,"包装"它。可以在单个对象周围分配多个装饰器(即:每个装饰器都包装前一个)。代理基本上充当中介,适应某些原因 - 通常是为了处理某些功能(资源分配),延迟加载等 - 但通常情况下,您只有一个代理来间接提供对一个实例的访问。 - Reed Copsey

5

装饰者模式:

  1. 在运行时为对象添加行为。继承是实现此功能的关键,这既是该模式的优点,也是缺点。
  2. 它增强了接口的行为
  3. 装饰者可以被视为只有一个组件的退化复合体。但是,装饰者添加了额外的职责 - 它不是用于对象聚合。
  4. 装饰者支持递归组合
  5. 装饰者类声明与LCD(最低类分母)接口的组合关系,并且该数据成员在其构造函数中初始化。
  6. 装饰者旨在让您在不使用子类的情况下向对象添加职责

请参阅sourcemaking文章以获取更多详细信息。

来自维基百科的装饰者UML图:

enter image description here

桥接模式:

  1. 桥接是一种结构性模式
  2. 抽象和实现在编译时不绑定
  3. 抽象和实现 - 二者都可以在客户端中变化而不影响

使用桥接模式的情况包括:

  1. 您想要实现的绑定在运行时,
  2. 由于耦合的接口和众多实现而导致类的大量增加,
  3. 您希望在多个对象之间共享一个实现, 您需要映射正交类层次结构。

来自维基百科的桥接UML图:

enter image description here

从UML图中可以观察到两者的不同之处:

在装饰者模式中,装饰者实现组件,该组件将在运行时由ConcreteComponent替换。

在桥接模式中,重新定义的抽象类没有实现Implementor。相反,它使用组合,以便Implementor可以在运行时动态变化,而客户端不知道。

装饰者模式不能像桥接模式那样将抽象与实现解耦。

更多有用的文章:

何时使用装饰者模式?

何时使用桥接模式?它与适配器模式有什么不同?


1

Brian是正确的。我想补充的是,从概念上讲,客户端将“知道”它正在使用一个桥接到底层对象,但是使用装饰器时,客户端将无法知道在它和目标对象之间有一个装饰器层。

桥接的目的是创建一个抽象层以保护客户端。装饰器的目的是在不让客户端知道的情况下为对象添加功能。大多数装饰器将直接将所有函数调用传递给指向它们的父类的指针,除了与装饰器设计要更改的内容直接相关的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接