Образец моста - состав или агрегация? - PullRequest
3 голосов
/ 11 июля 2010

Я читаю несколько книг о шаблонах проектирования, и хотя некоторые описывают связь между абстракцией и реализацией как композицию, некоторые описывают ее как совокупность. Теперь я задаюсь вопросом: это зависит от реализации? На языке? Или контекст?

Ответы [ 3 ]

5 голосов
/ 11 июля 2010

Термины «состав» и «агрегация» означают более или менее одно и то же и могут использоваться взаимозаменяемо.Агрегация может использоваться чаще при описании контейнерных классов, таких как списки, динамические массивы, карты и очереди, в которых все элементы одного типа;однако можно найти оба термина для описания классов, определенных в терминах других классов, независимо от того, являются ли эти типы однородными (все одного типа) или разнородными (объекты разных типов).

Чтобы сделать это более понятным:

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.

Поскольку вы отметили свой вопрос как «мост», я должен отметить, чтоопределение шаблона моста - это шаблон, в котором вы используете композицию, а не наследование, чтобы учесть вариации на нескольких разных уровнях.Пример, который я изучил в колледже ... используя наследование, у вас может быть что-то вроде:

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 голосов
/ 11 июля 2010

шаблон моста должен использовать делегирование (агрегация / композиция, а не наследование). из книги банды четырех:

Используйте шаблон Мост, когда

* 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).
0 голосов
/ 05 февраля 2014

Стандартный шаблон UML of Bridge очищает воздух от путаницы. Ниже приведено объяснение с кратким примером, чтобы прояснить ситуацию вокруг этого.

Извините за этот длинный код, лучший способ - скопировать этот код в Visual Studio, чтобы его было легко понять.

Прочитайте объяснение, написанное в конце кода

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 - это абстракция, которую должны реализовать боты Dog и Cat - Разделить классы собак и кошек, введя мост "Animal", который состоит из ISpeak - Классы Dog и Cat расширяют класс Animal и, таким образом, отделены от ISpeak.

Надеюсь, это прояснит

...