Szerkesztő:Vereczkibalint/Öröklődés helyett objektum-összetétel

A Wikipédiából, a szabad enciklopédiából
Ez a diagram azt mutatja be, hogy miként lehet az állatok repülési és hangviselkedését rugalmasan megtervezni az öröklődés helyett objektum-összetétel tervezési elv alkalmazásával. [1]

Az objektum-orientált programozásban (OOP) öröklődés helyett objektum-összetétel (másnéven összetétel újrafelhasználási elv) alapja, hogy az osztályoknak polimorf viselkedést és a kód újrafelhasználást kell megvalósítania a kompozíciójukkal (azáltal, hogy saját példányokat tárolnak más osztályokból, melyek implementálják a kívánt funkcionalitást) ahelyett, hogy egy ősosztályból öröklődnének.

Alapok[szerkesztés]

Az elv implementációja tipikusan azzal keződik, hogy különféle interfészeket készítünk, melyek leírják a viselkedéseket, melyeket a rendszernek tartalmaznia kell. Az interfészek teszik lehetővé a polimorfizmust. Az osztályok implementálják az interfészeket, így öröklődés nélkül megadhatjuk a rendszer egyes részeinek a működési viselkedését.

Példa[szerkesztés]

Öröklődés[szerkesztés]

Egy példa C++11-ben:

#include <vector>

class Model;

class JátékObjektum {
 public:
 virtual ~JátékObjektum() = default;

 virtual void Frissít() {}
 virtual void Rajzol() {}
 virtual void Ütközés(const std::vector<JátékObjektum*>& objektumok) {}
};

class Látható : public JátékObjektum {
 public:
 void Frissít() override {
  // |model_| rajzolása ezen objektum helyzetére
 };

 private:
 Model* model_;
};

class Test : public JátékObjektum {
 public:
 void Ütközés(const std::vector<JátékObjektum*>& objektumok) override {
  // |objektumok|-al való ütközések ellenőrzése és azokra reagálás
 };
};

class Mozgatható : public JátékObjektum {
 public:
 void Frissít() override {
  // Pozíció frissítése.
 };
};

Vannak konkrét osztályaink:

  • Játékososztály - amely Test, Mozgatható és Látható
  • Felhő osztály - amely Mozgatható és Látható, de nem Test
  • Épület osztály - amely Test és Látható, de nem Mozgatható
  • Csapda osztály - amely Test, de se nem Látható, se nem Mozgatható

Figyelembe kell venni, hogy az öröklődés veszélyes, ha nincs kellő gondossággal implementálva, ugyanis ez a gyémánt problémához vezethet. Egyik megoldás ennek elkerülésére, hogy ilyen osztályokat készítsünk: LáthatóÉsTest,LáthatóÉsMozgatható, LáthatóÉsTestÉsMozgatható , és mindezt az összes lehetséges kombinációra. Ez viszont rengeteg kódismétléshez vezet. A C++ megoldja a gyémánt problémát azzal, hogy engedi a virtuális öröklődést.

Kompozíció és interfészek[szerkesztés]

A következő C # példa bemutatja a kompozíció és az interfészek használatának elvét, hogy megvalósuljon a kód újrafelhasználás, és a polimorfizmus.

class Program {
  static void Main() {
    var játékos = new JátékObjektum(new Látható(), new Mozgatható(), new Test());
    játékos.Frissít(); játékos.Ütközés(); játékos.Rajzol();

    var felhő = new JátékObjektum(new Látható(), new Mozgatható(), new NemTest());
    felhő.Frissít(); felhő.Ütközés(); felhő.Rajzol();

    var épület = new JátékObjektum(new Látható(), new NemMozgatható(), new Test());
    épület.Frissít(); épület.Ütközés(); épület.Rajzol();

    var csapda = new JátékObjektum(new Láthatatlan(), new NemMozgatható(), new Test());
    csapda.Frissít(); csapda.Ütközés(); csapda.Rajzol();
  }
}

interface ILátható {
  void Rajzol();
}

class Láthatatlan : ILátható {
  public void Rajzol() {
    Console.Write("Nem fogok megjelenni.");
  }
}

class Látható : ILátható {
  public void Rajzol() {
    Console.Write("Megjelentem.");
  }
}

interface Ütközhető {
  void Ütközés();
}

class Test : Ütközhető {
  public void Ütközés() {
    Console.Write("Bang!");
  }
}

class NemTest : Ütközhető {
  public void Ütközés() {
    Console.Write("Splash!");
  }
}

interface Frissíthető {
  void Frissít();
}

class Mozgatható : Frissíthető {
  public void Frissít() {
    Console.Write("Előre megyek.");
  }
}

class NemMozgatható : Frissíthető {
  public void Frissít() {
    Console.Write("Egyhelyben maradok.");
  }
}

class JátékObjektum : ILátható, Frissíthető, Ütközhető {
  private readonly ILátható _látható;
  private readonly Frissíthető _frissíthető;
  private readonly Ütközhető _ütközhető;

  public JátékObjektum(ILátható látható, Frissíthető frissíthető, Ütközhető ütközhető) {
    _látható = látható;
    _frissíthető = frissíthető;
    _ütközhető = ütközhető;
  }

  public void Frissít() {
    _frissíthető.Frissít();
  }

  public void Rajzol() {
    _látható.Rajzol();
  }

  public void Ütközés() {
    _ütközhető.Ütközés();
  }
}

[[Kategória:C sharp kód példák]]

  1. Freeman, Eric. Head First Design Patterns. O'Reilly, 23. o. (2004). ISBN 978-0-596-00712-6