首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >桥接模式-组合还是聚合?

桥接模式-组合还是聚合?
EN

Stack Overflow用户
提问于 2010-07-11 18:57:28
回答 3查看 2.3K关注 0票数 4

我正在阅读一些关于设计模式的书,虽然有些书将抽象和实现之间的关系描述为组合,但也有一些书将其描述为聚合。现在我想知道:这依赖于实现吗?在语言上?还是上下文?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-07-11 19:17:21

术语“组合”和“聚合”的含义或多或少相同,可以互换使用。当描述诸如列表、动态数组、映射和队列之类的容器类时,可以更频繁地使用聚合,这些容器类中的元素都是相同类型的;然而,这两个术语都可以用来描述以其他类定义的类,而不管这些类型是同质的(都是相同类型的)还是异质的(不同类型的对象)。

为了更清楚地说明这一点:

代码语言:javascript
复制
class Car {
    // ...
    private:
        Engine engine;
        Hood hood;
};

// The car is *composed* of an engine and a hood. Hence, composition. You are
// also bringing together (i.e. *aggregating*) an engine and hood into a car.

抽象和实现之间的关系通常意味着继承,而不是组合/聚合;通常,抽象是接口或虚拟基类,而实现是实现给定接口的完全具体的类。但是,令人困惑的是,组合/聚合可以是接口的一部分(因为,例如,您可能需要设置/获取用作构建块的对象),而且它们也是一种实现方法(因为您可能使用委托来为实现中的方法提供定义)。

为了更清楚地说明这一点:

代码语言:javascript
复制
interface Car {
    public Engine getEngine();
    public Hood getHood();
    public void drive();
}
// In the above, the fact that a car has these building blocks
// is a part of its interface (the abstraction).

class HondaCivic2010 implements Car {
    public void drive(){ getEngine().drive(); }
    // ...
}
// In the above, composition/delegation is an implementation
// strategy for providing the drive functionality.

由于您已经将您的问题标记为" bridge ",我应该指出,bridge模式的定义是一种模式,在该模式中,您使用组合而不是继承来允许多个不同级别的变化。我在大学里学到的一个例子。使用继承,您可能会得到如下内容:

代码语言:javascript
复制
class GoodCharacter;
class BadCharacter;
class Mage;
class Rogue;
class GoodMage : public GoodCharacter, Mage;
class BadMage : public BadCharacter, Mage;
class GoodRogue : public GoodCharacter, Rogue;
class BadRogue : public BadCharacter, Rogue;

正如你所看到的,这种事情变得非常疯狂,你得到了非常多的类。同样的事情,对于桥模式,将如下所示:

代码语言:javascript
复制
 class Personality;
 class GoodPersonality : public Personality;
 class BadPersonality : public Personality;

 class CharacterClass;
 class Mage : public CharacterClass;
 class Rogue : public CharacterClass;

 class Character {
    public:
        // ...
    private:
        CharacterClass character_class;
        Personality personality;
 };
 // A character has both a character class and a personality.
 // This is a perfect example of the bridge pattern, and we've
 // reduced MxN classes into a mere M+N classes, and we've
 // arguably made the system even more flexible than before.
票数 7
EN

Stack Overflow用户

发布于 2010-07-11 19:11:40

桥接模式必须使用委托(聚合/组合,而不是继承)。来自四人帮的书:

在以下情况下使用桥接模式

代码语言:javascript
复制
* you want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at run-time.

* both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.

* changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.

* (C++) you want to hide the implementation of an abstraction completely from clients. In C++ the representation of a class is visible in the class interface.

* you have a proliferation of classes as shown earlier in the first Motivation diagram. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations" [RBP+91] to refer to such class hierarchies.

* you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class [Cop92], in which multiple objects can share the same string representation (StringRep).
票数 2
EN

Stack Overflow用户

发布于 2014-02-05 10:13:14

桥接模式的标准UML消除了所有的混乱。下面是一个简短的例子来解释一下,以澄清这一点。

对于这段冗长的代码,很抱歉,最好的方法是将此代码复制到Visual Studio以便于理解。

通读代码末尾的说明

代码语言:javascript
复制
interface ISpeak
{
    void Speak();
}

class DogSpeak : ISpeak
{
    public void Speak()
    {
        Console.WriteLine("Dog Barks");
    }
}
class CatSpeak : ISpeak
{
    public void Speak()
    {
        Console.WriteLine("Cat Meows");
    }
}

abstract class AnimalBridge
{
    protected ISpeak Speech;

    protected AnimalBridge(ISpeak speech)
    {
        this.Speech = speech;
    }

    public abstract void Speak();
}
class Dog : AnimalBridge
{
    public Dog(ISpeak dogSpeak)
        : base(dogSpeak)
    {

    }
    public override void Speak()
    {
        Speech.Speak();
    }
}

class Cat : AnimalBridge
{
    public Cat(ISpeak catSpeak)
        : base(catSpeak)
    {

    }
    public override void Speak()
    {
        Speech.Speak();
    }
}

-- ISpeak是bot Dog和Cat必须实现的抽象--通过引入由ISpeak组成的桥" Animal“来解耦Dog和Cat类-- Dog和Cat类扩展了Animal类,从而与ISpeak分离。

希望这能澄清

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3222785

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档