Бублик Володимир Васильович Програмування - 2 Лекція  4 . Об'єктне програмування. Ієрархія об’єктів: композиція і агрегація  Лекції для студентів 2 курсу
Типи ієрархії об'єктів // Layering : вкладання class  AnyClass {   T _composee;   T& _refferee;   T* _agregee; };
Композиція об'єктів Композит  складається з  компонентів Компонент  служить атрибутом  композиту
Приклад   1. Відрізок // Composite class  Segment { private : // Components Point _a, _b; ……………… };
Приклад 2. Трикутник // Композиція вершин class  Triangle { private : Point _a, _b, _c; ........................ };
Приклад 3. Знову трикутник // Композиція сторін   class  Triangle { private : Segment  _a b , _b c , _c a ; …………………………… . }; Композити  самі можуть бути  компонентами  інших об'єктів: Композит  Triangle  містить компонентами   три композити  Segment
Приклад 4. Все той же трикутник // Композиція вершин і сторін class  Triangle { private : Point _a, _b, _c; Segment _ab, _bc, _ca; ........................ };
Тривалість життя: створення компонент Компоненти створюються конструктором композиту: звичайним або копіювальним Triangle::Triangle ( const  Point& a,  const  Point& b,  const  Point &c): // Ініціалізація компонент _a(a), _b(b), _c(c) { return; }
Тривалість життя: видалення компонент Компоненти не вимагають окремого видалення, оскільки вони видаляються автоматично власними деструкторами при видаленні композиту як його атрибути ~ Triangle ::Triangle() { // _a.~Point(); // _b.~Point(); // _c.~Point(); return ; }
Права доступу Звичайно доступ до компонент та їх методів зовні композиту  закрито  (компоненти служать атрибутами композиту, а атрибути, як правило, закриті) Композит сам  не має  доступу до закритої частини компоненту Композит має доступ до відритої частини компоненту, при необхідності   він може  делегувати  цей доступ нагору
Доступ до атрибутів: селектор Оскільки компоненти закриті, доступ (модифікація) забезпечуються селекторами (модифікаторами) class  Triangle { private : Point _a, _b, _c; public : const  Point& apexA()  const ; const  Point& apexB()  const ; const  Point& apexC()  const ; };
Реалізація селектора const  Point& Triangle::apexA()  const { return  _a; } Чим відрізняються одна від одної ці реалізації? const  Point Triangle::apexA()  const { return  _a; }
Делегування // Delegation of methods class  Triangle { private :   Segment  _a b , _b c , _c a ;   public : // delegators double   length_ab ()  const ; double   length_bc ()  const ; double   length_ca ()  const ; };
Реалізація делегатів // Delegator // трикутник делегує довжину відрізку double  Triangle::length_ab()  const { // Delegate // метод трикутника звертається // до методу сегмента, недоступного зовні return  _ab.length(); }
Неделеговані методи Реалізація методів композиту може використовувати відкриту частину компоненти або асоційованого об'єкту як будівельний матеріал double  Triangle::square() const { //   length()  і  distance(_a)  методи відрізка return  0.5*side_a().length()*side_a().distance(_a); } Звідки візьмуться відрізки у варіанті трикутника, складеного лише з вершин?
Асоційовані об'єкти  Об'єкти не завжди вкладаються один в інший Асоційовані об'єкти  ( associate )  можуть будуватися на замовлення і існувати поза асоціатором  ( associator )
Асоційовані об'єкти  // Associator class  Triangle { private: Point _a, _b, _c; public : // Associate : сторона трикутника const  Segment side_a()  const ; };
Створення асоційованої сторони t.side_a();  // Візьмемо трикутник  t
Створення асоційованої сторони t.side_a();  // Він має селектори вершин,
Створення асоційованої сторони t.side_a();  // Він має селектори вершин,   // але не сторін
Створення асоційованої сторони t.side_a();  // Візьмемо дві потрібні вершини
Створення асоційованої сторони t.side_a();  // і побудуємо відрізок
Варіант надлишкової композиції class  Triangle { private : Point _a, _b, _c; //  Асоціанти стали компонентами Segment _ab, _bc, _ca;  public : const  Point& apexA()  const ; // Делегати стали селекторами const  Segment &  side_a() c onst ;  } ;
Селектор замість делегата // Селектор сторони трикутника const  Segment& Triangle::side_a()  const { return  _bc; // return Segment(_b, _c); }
Конструювання компонентів Triangle::Triangle ( const  Point& a,  const  Point& b,  const  Point &c): // Багато зайвих копій _a(a), _b(b), _c(c), _ab(Segment(a, b)), _bc(Segment(b, c)),  _ca(Segment(c, a)) { return ; }
Consistency ( сумісність ) Надлишкове копіювання шкідливе можливою несумісністю Візьмемо трикутник  t,  з вершинами  a, b  і  c;  сторонами  _bc, _ca  і  _ab .  Змінимо значення вершини  a , але забудемо змінити значення сторін  _ca  і  _ab. Трикутник  t  виявиться несумісним. Проблема сумісності не виникає, якщо трикутник задано лише вершинами
Як правильно обрати компоненти композиту? // Трикутник за трьома сторонами class  Triangle { private : Segment _ab, _bc, _ca; public : // а конструктор, як раніше за трьома вершинами Triangle(const Point &,   const Point&,   const Point&); } ;
Конструювання сторін Triangle::Triangle ( const  Point& a,  const  Point& b,  const  Point &c): _ab(Segment(a, b)), _bc(Segment(b, c)), _ca(Segment(c, a)) { return ; }
Тепер вершини делегуються // Вершина трикутника const  Point& Triangle::apexA()  const { // return _a; return  _ab.start(); }
Знову по сумісність Трикутник складений із сторін знову може стати несумісним при спробі змінити одну із сторін, не змінивши іншої, прилеглої сторони. Проблема:  надлишкове кодування приводить до несумісності Рішення:  використовувати розвиненіші форми вкладень, а саме  агрегацію.
Підсумок композицій Вершини компоненти ,   сторони асоціанти
Підсумок композицій Вершини і  сторони   компоненти
Підсумок композицій Сторони   компоненти ,  вершини асоціанти
Агрегація Кожен нетривіальний об'єкт є агрегатом, складеним зі своїх атрибутів Атрибути можуть бути об'єктами  ― композиція; указниками ― агрегація указниками;   відсилками  ― агрегація відсилками
Агрегація указниками Агрегація указниками відрізняється від композиції тривалістю життя: деструктор агрегату сам відповідає за видалення агрегованого об'єкту class  Agregate { private : Agregee *  _agregee ; public :   Agregate(): _agregee(0){}; ~Agregate() {  delete   _agregee ; } };
Сторони, агреговані в трикутник class  Triangle { private : Point _a, _b, _c; Segment *_ab, *_bc, *_ca; public : Triangle( const  Point &,  const  Point&,  const  Point& c); ~Triangle(); }
Конструктор агрегату Triangle::Triangle ( const  Point& a,  const  Point& b,  const  Point &c): _a(a), _b(b), _c(c), // Сторони обчислюються і агрегуються // на замовлення  (on demand) _ab(0), _bc(0), _ca(0) { return ; }
Деструктор агрегату Triangle::~Triangle() { if  (_ab!=0)  delete  _ab; // vs  delete _ab; if  (_bc!=0)  delete  _bc; if  (_ca!=0)  delete  _ca; }; Питання:  чи необхідна перевірка на нуль?
Модифікований селектор // Сторона трикутника const  Segment& Triangle::side_a()  const { // Якщо не обчислювали раніше if  (_bc == 0)  // Обчислюємо і запам'ятовуємо _bc =  new  Segment(_b, _c); return  *_bc; }
Агрегація сторін указниками вершини   компоненти сторони агреговані Проблема сумісності відкрита
Агрегація відсилкою Використовується для агрегування об'єктів, тривалість життя яких перевищує тривалість життя агрегату. За створення і видалення агрегованих відсилкою об'єктів агрегат відповідальності не несе class  Agregate { private : Agregee &  _agregee ; public :   Agregate ( const  Agregee & original): _agregee (original) {}; };
Вершини, агреговані в сторону class  Segment { private : // Агреговані вершини Point  & _a,  & _b; ……………… }; Що гарантує сумісність?
Збалансований трикутник // Кінці відрізків // відсилають // до вершин // трикутника class  Segment { private : Point  & _a,  & _b; }; //Сторони трикутника // агреговані указниками class  Triangle { private: Point _a, _b, _c; Segment  * _ab,  * _bc,  * _ca; };
Збалансований трикутник
Збалансований трикутник
Збалансований трикутник
Збалансований трикутник
Гарантована сумісність
Висновок Головна проблема у створенні агрегатів полягає у виборі правильного типу вкладень залежно від тривалості життя об'єктів з метою досягнення максимальної сумісності

04 Object Hierarchy

  • 1.
    Бублик Володимир ВасильовичПрограмування - 2 Лекція 4 . Об'єктне програмування. Ієрархія об’єктів: композиція і агрегація Лекції для студентів 2 курсу
  • 2.
    Типи ієрархії об'єктів// Layering : вкладання class AnyClass { T _composee; T& _refferee; T* _agregee; };
  • 3.
    Композиція об'єктів Композит складається з компонентів Компонент служить атрибутом композиту
  • 4.
    Приклад 1. Відрізок // Composite class Segment { private : // Components Point _a, _b; ……………… };
  • 5.
    Приклад 2. Трикутник// Композиція вершин class Triangle { private : Point _a, _b, _c; ........................ };
  • 6.
    Приклад 3. Зновутрикутник // Композиція сторін class Triangle { private : Segment _a b , _b c , _c a ; …………………………… . }; Композити самі можуть бути компонентами інших об'єктів: Композит Triangle містить компонентами три композити Segment
  • 7.
    Приклад 4. Всетой же трикутник // Композиція вершин і сторін class Triangle { private : Point _a, _b, _c; Segment _ab, _bc, _ca; ........................ };
  • 8.
    Тривалість життя: створеннякомпонент Компоненти створюються конструктором композиту: звичайним або копіювальним Triangle::Triangle ( const Point& a, const Point& b, const Point &c): // Ініціалізація компонент _a(a), _b(b), _c(c) { return; }
  • 9.
    Тривалість життя: видаленнякомпонент Компоненти не вимагають окремого видалення, оскільки вони видаляються автоматично власними деструкторами при видаленні композиту як його атрибути ~ Triangle ::Triangle() { // _a.~Point(); // _b.~Point(); // _c.~Point(); return ; }
  • 10.
    Права доступу Звичайнодоступ до компонент та їх методів зовні композиту закрито (компоненти служать атрибутами композиту, а атрибути, як правило, закриті) Композит сам не має доступу до закритої частини компоненту Композит має доступ до відритої частини компоненту, при необхідності він може делегувати цей доступ нагору
  • 11.
    Доступ до атрибутів:селектор Оскільки компоненти закриті, доступ (модифікація) забезпечуються селекторами (модифікаторами) class Triangle { private : Point _a, _b, _c; public : const Point& apexA() const ; const Point& apexB() const ; const Point& apexC() const ; };
  • 12.
    Реалізація селектора const Point& Triangle::apexA() const { return _a; } Чим відрізняються одна від одної ці реалізації? const Point Triangle::apexA() const { return _a; }
  • 13.
    Делегування // Delegationof methods class Triangle { private : Segment _a b , _b c , _c a ; public : // delegators double length_ab () const ; double length_bc () const ; double length_ca () const ; };
  • 14.
    Реалізація делегатів //Delegator // трикутник делегує довжину відрізку double Triangle::length_ab() const { // Delegate // метод трикутника звертається // до методу сегмента, недоступного зовні return _ab.length(); }
  • 15.
    Неделеговані методи Реалізаціяметодів композиту може використовувати відкриту частину компоненти або асоційованого об'єкту як будівельний матеріал double Triangle::square() const { // length() і distance(_a) методи відрізка return 0.5*side_a().length()*side_a().distance(_a); } Звідки візьмуться відрізки у варіанті трикутника, складеного лише з вершин?
  • 16.
    Асоційовані об'єкти Об'єкти не завжди вкладаються один в інший Асоційовані об'єкти ( associate ) можуть будуватися на замовлення і існувати поза асоціатором ( associator )
  • 17.
    Асоційовані об'єкти // Associator class Triangle { private: Point _a, _b, _c; public : // Associate : сторона трикутника const Segment side_a() const ; };
  • 18.
    Створення асоційованої сторониt.side_a(); // Візьмемо трикутник t
  • 19.
    Створення асоційованої сторониt.side_a(); // Він має селектори вершин,
  • 20.
    Створення асоційованої сторониt.side_a(); // Він має селектори вершин, // але не сторін
  • 21.
    Створення асоційованої сторониt.side_a(); // Візьмемо дві потрібні вершини
  • 22.
    Створення асоційованої сторониt.side_a(); // і побудуємо відрізок
  • 23.
    Варіант надлишкової композиціїclass Triangle { private : Point _a, _b, _c; // Асоціанти стали компонентами Segment _ab, _bc, _ca; public : const Point& apexA() const ; // Делегати стали селекторами const Segment & side_a() c onst ; } ;
  • 24.
    Селектор замість делегата// Селектор сторони трикутника const Segment& Triangle::side_a() const { return _bc; // return Segment(_b, _c); }
  • 25.
    Конструювання компонентів Triangle::Triangle( const Point& a, const Point& b, const Point &c): // Багато зайвих копій _a(a), _b(b), _c(c), _ab(Segment(a, b)), _bc(Segment(b, c)), _ca(Segment(c, a)) { return ; }
  • 26.
    Consistency ( сумісність) Надлишкове копіювання шкідливе можливою несумісністю Візьмемо трикутник t, з вершинами a, b і c; сторонами _bc, _ca і _ab . Змінимо значення вершини a , але забудемо змінити значення сторін _ca і _ab. Трикутник t виявиться несумісним. Проблема сумісності не виникає, якщо трикутник задано лише вершинами
  • 27.
    Як правильно обратикомпоненти композиту? // Трикутник за трьома сторонами class Triangle { private : Segment _ab, _bc, _ca; public : // а конструктор, як раніше за трьома вершинами Triangle(const Point &, const Point&, const Point&); } ;
  • 28.
    Конструювання сторін Triangle::Triangle( const Point& a, const Point& b, const Point &c): _ab(Segment(a, b)), _bc(Segment(b, c)), _ca(Segment(c, a)) { return ; }
  • 29.
    Тепер вершини делегуються// Вершина трикутника const Point& Triangle::apexA() const { // return _a; return _ab.start(); }
  • 30.
    Знову по сумісністьТрикутник складений із сторін знову може стати несумісним при спробі змінити одну із сторін, не змінивши іншої, прилеглої сторони. Проблема: надлишкове кодування приводить до несумісності Рішення: використовувати розвиненіші форми вкладень, а саме агрегацію.
  • 31.
    Підсумок композицій Вершиникомпоненти , сторони асоціанти
  • 32.
    Підсумок композицій Вершиниі сторони компоненти
  • 33.
    Підсумок композицій Сторони компоненти , вершини асоціанти
  • 34.
    Агрегація Кожен нетривіальнийоб'єкт є агрегатом, складеним зі своїх атрибутів Атрибути можуть бути об'єктами ― композиція; указниками ― агрегація указниками; відсилками ― агрегація відсилками
  • 35.
    Агрегація указниками Агрегаціяуказниками відрізняється від композиції тривалістю життя: деструктор агрегату сам відповідає за видалення агрегованого об'єкту class Agregate { private : Agregee * _agregee ; public : Agregate(): _agregee(0){}; ~Agregate() { delete _agregee ; } };
  • 36.
    Сторони, агреговані втрикутник class Triangle { private : Point _a, _b, _c; Segment *_ab, *_bc, *_ca; public : Triangle( const Point &, const Point&, const Point& c); ~Triangle(); }
  • 37.
    Конструктор агрегату Triangle::Triangle( const Point& a, const Point& b, const Point &c): _a(a), _b(b), _c(c), // Сторони обчислюються і агрегуються // на замовлення (on demand) _ab(0), _bc(0), _ca(0) { return ; }
  • 38.
    Деструктор агрегату Triangle::~Triangle(){ if (_ab!=0) delete _ab; // vs delete _ab; if (_bc!=0) delete _bc; if (_ca!=0) delete _ca; }; Питання: чи необхідна перевірка на нуль?
  • 39.
    Модифікований селектор //Сторона трикутника const Segment& Triangle::side_a() const { // Якщо не обчислювали раніше if (_bc == 0) // Обчислюємо і запам'ятовуємо _bc = new Segment(_b, _c); return *_bc; }
  • 40.
    Агрегація сторін указникамивершини компоненти сторони агреговані Проблема сумісності відкрита
  • 41.
    Агрегація відсилкою Використовуєтьсядля агрегування об'єктів, тривалість життя яких перевищує тривалість життя агрегату. За створення і видалення агрегованих відсилкою об'єктів агрегат відповідальності не несе class Agregate { private : Agregee & _agregee ; public : Agregate ( const Agregee & original): _agregee (original) {}; };
  • 42.
    Вершини, агреговані всторону class Segment { private : // Агреговані вершини Point & _a, & _b; ……………… }; Що гарантує сумісність?
  • 43.
    Збалансований трикутник //Кінці відрізків // відсилають // до вершин // трикутника class Segment { private : Point & _a, & _b; }; //Сторони трикутника // агреговані указниками class Triangle { private: Point _a, _b, _c; Segment * _ab, * _bc, * _ca; };
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
    Висновок Головна проблемау створенні агрегатів полягає у виборі правильного типу вкладень залежно від тривалості життя об'єктів з метою досягнення максимальної сумісності