пятница, 10 июля 2015 г.

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

Агрегация

Иногда в рамках одного класса нам необходимо создать один или несколько экземпляров другого класса (других классов). Например, если мы проектируем класс «Дом», то внутри экземпляра этого класса вполне могут существовать экземпляры классов «Стена», «Окно», «Дверь». Для реализации такой конструкции используется понятие «Агрегация». Т.е., агрегация – это вхождение экземпляра/ов одного класса в экземпляры другого класса в качестве полей.
    /// 
    /// Стена
    /// 
    public class Wall { }

    /// 
    /// Окно
    /// 
    public class Window { }

    /// 
    /// Дверь
    /// 
    public class Door { }

    /// 
    /// Дом
    /// 
    public class House
    {
        protected Wall _wall1;
        protected Wall _wall2;
        protected Wall _wall3;
        protected Wall _wall4;
        protected Window _window;
        protected Door _door;
    }

Композиция

Композиция – это более сложный случай агрегации. Отличие композиции от агрегации в том, что в случае композиции класс-контейнер не может обойтись (не имеет смысла) без экземпляров класса-содержимого. В описанном выше примере дом не может существовать без стен. Это композиция. Но, дом спокойно может обойтись без печной трубы (например, если в нём электрическое отопление) – это агрегация.

Агрегация массивов

Поля класса контейнера могут агрегировать не только одиночные экземпляры другого класса, но и массивы (любые коллекции, но об этом позже) этих экземпляров. Для этого надо создать поле типа «массив» и использовать его в дальнейшем.
    /// 
    /// Дом
    /// 
    public class House
    {
        /// 
        /// Массив стен дома
        /// 
        protected Wall[] _walls;

        /// 
        /// Массив окон дома
        /// 
        protected Window _windows;
        
        /// 
        /// А дверь в нарушение пожарной безопасности - одна
        /// 
        protected Door _door;
    }

Использование конструкторов

Если в классе-контейнере мы используем экземпляр другого класса, то перед использованием этот экземпляр надо создать. Для этого мы используем конструктор класса-содержимого. Если экземпляр класса-содержимого не создавать, то при попытке его использовать мы получим Exception.
        /// 
        /// Конструктор - инициализирует агрегированные поля класса
        /// 
        public House()
        {
            _walls = new Wall[4]
            {
                new Wall(), new Wall(), new Wall(), new Wall()
            };
            _windows = new Window[4] { new Window(), new Window(), new Window(), new Window() };
            _door = new Door();
        }

Агрегация или наследование?

В некоторых случаях рекомендуется использовать агрегацию вместо наследования для расширения функциональности класса. Так, скажем, если в классе А нам надо реализовать функциональность классов B и C, то нам будет затруднительно выбрать класс-предок для А. Логичным решением будет создание в классе А полей типа В и С. Впрочем, правильный подход к решению подобных задач мы рассмотрим позже.
    /// 
    /// Класс камеры
    /// 
    public class Camera
    {
        /// 
        /// Сфотографировать
        /// 
        public void Photo() { }
    }

    /// 
    /// Класс телефона
    /// 
    public class Phone
    {
        /// 
        /// Позвонить
        /// 
        public void Call() { }
    }


    /// 
    /// Смартфон
    /// 
    public class Smartphone
    {
        /// 
        /// Встроенная камера
        /// 
        protected Camera _camera;
        /// 
        /// Встроенный телефон
        /// 
        protected Phone _phone;

        /// 
        /// Конструктор
        /// 
        public Smartphone()
        {
            //Инициализация агрегированных полей 
            _camera = new Camera();
            _phone = new Phone();
        }

        /// 
        /// Сфотографировать
        /// 
        public void Photo() { _camera.Photo(); }

        /// 
        /// Позвонить
        /// 
        public void Call() { _phone.Call(); }
    }

Заключение


Агрегация и композиция позволяют включать экземпляры одного класса в экземпляры другого класса. Композиция отличается от агрегации тем, что в композиции экземпляр класса-контейнера не может существовать без экземпляра класса-содержимого.

Комментариев нет:

Отправить комментарий