Агрегация и композиция. C#

Агрегация и композиция

В предыдущей статье я рассказывал о том, как можно заменить наследование используя композицию, если главное что Вам нужно — это избежать повторного написания некого кода. К примеру, Вам доступен какой-то класс (причем, его разработчиком можете быть даже не Вы), функциональность которого Вы хотите расширить. Вы можете написать класс-наследник (если исходный класс не помечен как sealed, о том что такое sealed-классы, я рассказывал в этой статье), получив при этом ряд «побочек», или воспользоваться принципом композиции. Но не одной композицией можно решать подобные проблемы. Есть еще так называемая агрегация. И в этой статье, я хочу вкратце рассказать о том, что же такое агрегация и в чем её отличие от композиции.

И так, скажу сразу, что агрегация и композиция очень близкие понятия! В обоих случаях есть объемлющий объект (объект-контейнер, если хотите) и объект-содержимое (этого контейнера). Объект-содержимое, как привило является полем объекта-контейнера. Но в тоже время, между композицией и агрегацией есть одно важное отличие: при использовании композиции, объект-содержимое не может существовать без своего контейнера, а случае агрегации, такое вполне возможно. Да еще и при использовании агрегации, объект-содержимое может принадлежать даже нескольким контейнерам (но тут нужно быть осторожным) или у одного объекта-контейнера, в течении «жизни», может быть разное содержимое (причем, агрегация позволяет использовать даже содержимое разных типов одном у тому же контейнеру).

На самом деле, можно сказать, что композиция — это частный, более строгий, вариант агрегации.

А теперь, я покажу как на практике выглядит агрегирование (использование композиции я показывал в предыдущей статье, ссылку на которую приводил выше):

//Класс, отправляющий данные 
class Sender
{
    public void Send(byte[] aData)
    { 
        //Отправка данных
    }

    //Поля класса, для хранения настроек и прочего
}

//Класс, отправляющий данные, сжимая их перед отправкой
class SenderM
{
    //Конструктор
    public SenderM(Sender aSender)
    {
        sender = aSender;
    }

    //Модифицированный метод отправки (предварительно сжимающий данные)
    public void SendM(byte[] aData)
    {
        //Сжимаем данные aData

        //Отправляем данные (вызывая метод базового класса)
        sender.Send(aData);
    }

    //Ссылка на объект класса Sender
    private Sender sender;
 
    //Какие-то другие поля класса...
}

Как можно заметить, в отличии от композиции, в данном примере, мы не создаем объект типа «Sender» внутри класса «SenderM». Такой объект будет создаваться за пределами класса, а конструктор типа «SenderM» будет принимать ссылку на этот объект. Вот в этом и есть главное отличие агрегирования от композиции.

//Создаем объект, который будет частью другого
Sender tmpSender = new Sender();

//Создаем объект-контейнер
SenderM mainSender = new SenderM(tmpSender); 

//Какие-то данные
byte[] someData = new byte[512];

//Какое-то заполнение данных...

//Отправка уже данных со сжатием
mainSender.SendM(someData);

Как видите, использовать такие классы тоже несложно…

Добавить комментарий