代码之家  ›  专栏  ›  技术社区  ›  helpermethod

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

  •  3
  • helpermethod  · 技术社区  · 16 年前

    3 回复  |  直到 10 年前
        1
  •  7
  •   Michael Aaron Safyan    16 年前

    术语“组合”和“聚合”的意思大致相同,可以互换使用。在描述容器类(如列表、动态数组、映射和队列)时,可以更频繁地使用聚合,其中元素都是相同类型的;但是,这两个术语都可以用来描述根据其他类定义的类,而不管这些类型是同质的(所有相同的类型)还是异质的(不同类型的对象)。

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

    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.
    

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

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

    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模式的定义是这样一种模式,即您使用组合而不是继承来允许在多个不同级别上的变化。我在大学学到的一个例子。。。使用继承,您可能会遇到以下情况:

    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;
    

    正如你所看到的,这种事情变得非常疯狂,你得到了一个荒谬的类数量。同样的事情,在桥的模式下,看起来是这样的:

     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.
    
        2
  •  2
  •   Ray Tayek    16 年前

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

    * 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).
    
        3
  •  0
  •   Kiran Vedula    12 年前

    桥接模式的标准UML清除了混乱周围的所有空气。下面用一个简单的例子来说明这个问题。

    很抱歉,这个冗长的代码,最好的方法是复制这个代码到visualstudio,以便于理解。

    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是botdog和Cat必须实现的抽象 --狗和猫类扩展了动物类,因此与ISpeak分离。

    希望这能澄清