Bridge template - composition or aggregation?

I read several books on design patterns, and some describe the relationship between abstraction and implementation as a composition, and some describe it as aggregation. Now I wonder: does it depend on the implementation? In the language? Or context?

+3
source share
3 answers

The terms “composition” and “aggregation” mean more or less the same thing and can be used interchangeably. Aggregation can be used more often when describing container classes, such as lists, dynamic arrays, maps, and queues, where all elements are of the same type; however, both terms can be found to describe classes defined in terms of other classes, regardless of whether these types are homogeneous (all of the same type) or heterogeneous (objects of different types).

To make this clear:

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.
+5

(/, ). " ":

Bridge,

* 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 String class [Cop92], in which multiple objects can share the same string representation (StringRep).
+2

UML . , .

Sorry for this long code, the best way is to copy this code into Visual Studio for easy understanding.

Read the explanation at the end of the code.

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 is an abstraction that the Dog and Cat bot must implement - Separated classes of dogs and cats by introducing the Animal bridge, consisting of ISpeak - Dog and Cat classes extend the Animal class and, therefore, disconnect from ISpeak.

Hope this clarifies

0
source

Source: https://habr.com/ru/post/1754087/


All Articles