Tervminták I. (Sablonfüggvény, Stratégia, Egyke, Látogató) Testek térfogata Lények túlélési versenye

Hasonló dokumentumok
OAF Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1.

OEP Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1. Feladat. Elemzés 1

Objektum elvű alkalmazások fejlesztése. Öröklődés. Készítette: Sike Sándor Gregorics Tibor

Elemi Alkalmazások Fejlesztése II.

OOP: Java 8.Gy: Abstract osztályok, interfészek

Programozás II gyakorlat. 6. Polimorfizmus

Bevezetés a Programozásba II 8. előadás. Polimorfizmus Giachetta Roberto

Objektum elvű alkalmazások fejlesztése 3. beadandó

Osztályok. 4. gyakorlat

Programozás C++ -ban 2007/4

Programozás alapjai II. (9. ea) C++ többszörös öröklés, cast, perzisztencia

OOP: Java 11.Gy: Enumok, beágyazott osztályok. 13/1 B ITv: MAN

Programozási nyelvek Java

Tervminták II. (Híd, Bejáró, Gyártófüggvény) Halmaz és bejárása Osztály-sablonok

Programozás II gyakorlat. 8. Operátor túlterhelés

és az instanceof operátor

4. Öröklődés. Programozás II

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

OOP #14 (referencia-elv)

Java programozási nyelv 5. rész Osztályok III.

Objektumorientált programozás C# nyelven

Programozás II gyakorlat. 4. Öröklődés

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

Alkalmazott modul: Programozás 11. előadás. Objektumorientált programozás: öröklődés

500. AA Megoldó Alfréd AA 500.

1. Alapok. Programozás II

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Visual C++ osztály készítése, adattagok, és metódusok, láthatóság, konstruktor, destruktor. Objektum létrehozása, használata, öröklés.

Pénzügyi algoritmusok

JAVA PROGRAMOZÁS 2.ELŐADÁS

Objektum elvű alkalmazások fejlesztése. Öröklődés. Készítette: Sike Sándor Gregorics Tibor

Alkalmazott Modul III 6. előadás. Objektumorientált programozás: öröklődés és polimorfizmus

Maximum kiválasztás tömbben

Széchenyi István Egyetem. Programozás III. Varjasi Norbert

Osztály és objektum fogalma

Programozás C++ -ban

Objektumelvű programozás

Programozás II. 4. Dr. Iványi Péter

JAVA PROGRAMOZÁS 3.ELŐADÁS

Programozás II. 2. Dr. Iványi Péter

117. AA Megoldó Alfréd AA 117.

500. CC Megoldó Alfréd CC 500.

Programozás C++ -ban

128. AA Megoldó Alfréd AA 128.

Pelda öröklődésre: import java.io.*; import java.text.*; import java.util.*; import extra.*;

C# nyelv alapjai. Krizsán Zoltán 1. Objektumorientált programozás C# alapokon tananyag. Általános Informatikai Tanszék Miskolci Egyetem

Virtuális függvények (late binding)

osztályok kapcsolata Származtatatás C++ Izsó Tamás március 19. Izsó Tamás Származtatatás/ 1

A feladat lényege egy felhasználói típusnak a zsák típusnak a megvalósítása.

Programozás. C++ osztályok. Fodor Attila. Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék

Programozás Minta programterv a 2. házi feladathoz 1.

C#, OOP. Osztályok tervezése C#-ban

BME MOGI Gépészeti informatika 8.

3. Osztályok II. Programozás II

Objektumelvű alkalmazások fejlesztése 6. gyakorlat. Öröklődés, polimorfizmus. Öröklődés Kódismétlődés objektum-orientált szerkezetben

Szoftvertechnológia 4. előadás. Objektumorientált tervezés: általánosítás. Giachetta Roberto. Eötvös Loránd Tudományegyetem Informatikai Kar

C++ programozási nyelv Konstruktorok-destruktorok

PHP II. WEB technológiák. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) PHP II / 19

Java VI. Miskolci Egyetem Általános Informatikai Tanszék. Utolsó módosítás: Ficsor Lajos. Java VI.: Öröklődés JAVA6 / 1

Programozás I. Első ZH segédlet

Globális operátor overloading

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

Informatikai Kar. 4. fejezet. Giachetta Roberto

Programozás II. 2. gyakorlat Áttérés C-ről C++-ra

OBJEKTUM ORIENTÁLT PROGRAMOZÁS JAVA NYELVEN. vizsgatételek

Programozás II gyakorlat. 7. Példák a polimorfizmus alkalmazásaira

Szoftvertechnolo gia gyakorlat

Bevezetés a Python programozási nyelvbe

Programozási nyelvek I. 5. előadás (Gregorics Tibor anyagának felhasználásával)

ISA szimulátor objektum-orientált modell (C++)

Bánsághi Anna

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés

Dr. Pál László, Sapientia EMTE, Csíkszereda WEB PROGRAMOZÁS 2.ELŐADÁS. Objektumorientált programozás

Java VI. Egy kis kitérő: az UML. Osztály diagram. Általános Informatikai Tanszék Utolsó módosítás:

C# osztálydeníció. Krizsán Zoltán 1. .net C# technológiák tananyag objektum orientált programozás tananyag

OOP: Java 8.Gy: Gyakorlás

Programozás BMEKOKAA146. Dr. Bécsi Tamás 7. előadás

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Öröklés és Polimorfizmus

Objektum elvű alkalmazások fejlesztése Kifejezés lengyel formára hozása és kiértékelése

C++ programozási nyelv

500. DD Megoldó Alfréd DD 500.

Bevezetés a programozásba. 8. Előadás: Függvények 2.

Programozás C++ -ban 2007/7

Java és web programozás

Programozási technológia

Az alábbi példában a Foo f(5); konstruktor hívása után mennyi lesz f.b értéke? struct Foo { int a, b; Foo(int c):a(c*2),b(c*3) {} };

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

Programozás III KIINDULÁS. Különböző sportoló típusok vannak: futó, magasugró, focista, akik teljesítményét más-más módon határozzuk meg.

Számítógép és programozás 2

Miután létrehoztuk, szeretnénk neki beszédesebb nevet adni. A név változtatásához a következőt kell tenni:

228. AA Default Konstruktor AA 228.

Algoritmizálás + kódolás C++ nyelven és Pascalban

Objektumorientált programozás C# nyelven

Programozás. Osztályok, Származtatott osztályok. Fodor Attila

Informatika terméktervezőknek

Osztályok. construct () destruct() $b=new Book(); $b=null; unset ($b); book.php: <?php class Book { private $isbn; public $title;

Abstract osztályok és interface-ek. 7-dik gyakorlat

Átírás:

Tervminták I. (Sablonfüggvény, Stratégia, Egyke, Látogató) Testek térfogata Lények túlélési versenye

1.Feladat Készítsünk programot, amellyel különféle testek térfogatát számolhatjuk ki, illetve megadhatjuk azt is, hogy az egyes testfajtákból hány objektumot hoztunk létre! A lehetséges fajták: szabályos testek: gömb, kocka, tetraéder, oktaéder; hasáb jellegű testek: henger, négyzet alapú hasáb és szabályos háromszög alapú hasáb; gúla jellegű testek: kúp, négyzetes gúla. 2

Osztálydiagram Test Szabályos Hasábszerű Gömb Kocka Tetraéder Oktaéder Kúpszerű Henger Hasáb Hasáb Kúp Gúla 3

Absztrakt osztály, interfész Absztrakt (abstract) osztály az, amelyből nem példányosítunk objektumokat, kizárólag ősosztályként szolgálnak a származtatásokhoz. az absztrakt osztály nevét dőlt betűvel kell írni. Nyelvi szempontból egy osztály attól lesz absztrakt, hogy konstruktorai nem publikusak, vagy legalább egy metódusa absztrakt, azaz nincs implementálva, és csak a származtatás során írjuk majd felül az absztrakt metódust dőlt betűvel jelöljük Interfésznek, azaz tisztán absztrakt (pure abstract) osztálynak nevezzük azt az osztályt, amelyiknek egyetlen metódusa sincs implementálva. Amikor egy osztály a származtatása során egy interfész minden absztrakt metódusát implementálja, akkor megvalósítja az interfészt. <interfész> <osztály> 4

Absztrakt testek Test # méret : double osztály szintű adattag: - darab : int példányok darabszáma + térfogat():double {virtual, query + darab() : int {query osztály szintű metódus: példányok darabszámát kérdezi le Szabályos Hasábszerű osztály szintű tag nem öröklődik, - darab : int újra kell definiálni # magasság : double - darab : int + térfogat() : double {override + térfogat() : double {override # szorzó() : double {virtual, query # alap() : double {virtual, query + darab() : int {query + darab() : int {query return méret méret méret szorzó() return alap() magasság 5

A testek ősosztálya class Shape { public: virtual ~Shape(); ; virtual double volume() const = 0; static int piece() { return _piece; protected: Shape(double size); double _size; private: static int _piece; virtuális a destruktor osztályszintű adattag osztályszintű metódus egy absztrakt metódusú osztály absztrakt egy védett konstruktorú osztály absztrakt int Shape::_piece = 0; Shape::Shape(double size){ _size = size; ++_piece; Shape::~Shape(){ --_piece; osztályszintű adattag kezdeti értékadása 6

Szabályos absztrakt test class Regular : public Shape{ public: ~Regular(); double volume() const override; static int piece() { return _piece; protected: Regular(double size); virtual double multiplier() const = 0; private: static int _piece; ; int Regular::_piece = 0; Enélkül a konstruktor automatikusan hívná az ősosztály üres (paraméter nélküli) konstruktorát, de olyan most nincs. Regular::Regular(double size) : Shape(size){ ++_piece; a destruktor automatikusan Regular::~Regular(){ hívja az ősosztály destruktorát --_piece; double Regular::volume() const { return _size * _size * _size * multiplier(); 7

Szabályos testek -darab :int Szabályos jellegzetes mintázat a modellezésben: sablonfüggvény tervezési minta +térfogat() :double {override #szorzó() :double {virtual, query +darab() :int return méret méret méret szorzó() ennek definiálása az alosztályok feladata Kocka Gömb Tetraéder Oktaéder -darab :int -darab :int -darab :int -darab :int #szorzó():double {override +darab() :int #szorzó():double {override +darab() :int #szorzó():double {override +darab() :int #szorzó():double {override +darab() :int return 1 return 4π/3 return 2/12 return 2/3 8

Sablonfüggvény (template method) tervezési minta Egy algoritmust úgy adunk meg egy osztály metódusaként, hogy annak egyes lépéseit az algoritmus szerkezetének változtatása nélkül a futási idejű polimorfizmusra támaszkodva meg tudjuk változtatni. templatemethod() # parametermethod1() {virtual # parametermethod2() {virtual A parametermethod1() parametermethod2() B # parametermethod1() {override # parametermethod2() {override A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 9

Gömb class Sphere : public Regular { public: Sphere(double size); ~Sphere(); static int piece() { return _piece; protected: double multiplier() const override { return _multiplier; private: constexpr static double _multiplier = (4.0 * 3.14159) / 3.0; static int _piece; ; konstans osztályszintű kifejezés definiálása int Sphere::_piece = 0; Sphere::Sphere(double size) : Regular(size){ ++_piece; Sphere::~Sphere(){ --_piece; 10

Hasábféle testek sablonfüggvény tervezési minta Hasábszerű #magasság :double -darab :int +térfogat():double {override #alap() :double {virtual, query +darab() :int return alap() magasság Hasáb Henger Hasáb Kúpszerű -darab :int -darab :int -darab :int -darab :int #alap() :double {override +darab():int #alap() :double {override +darab():int #alap() :double {override +darab():int +térfogat() :double {override +darab() :int return méret méret π return (alap() magasság)/3 return 3 méret méret/4 return méret méret 11

Kúpszerű testek Kúpszerű -darab :int sablonfüggvény tervezési minta +térfogat():double {override #alap():double {override +darab() :int return (alap() magasság)/3 Kúp Gúla -darab :int -darab :int #alap() :double {override +darab() :int return méret méret π #alap() :double {override +darab() :int return méret méret Kritika a modellről: redundancia (kódismétlődés) jelent meg a modellben. Ugyanolyan alapterület kiszámolására több metódus is született: például a kör területét a kúpnál is, a hengernél is definiáltuk; négyzet területét a négyzetalapú hasábnál is, a négyzetalapú gúlánál is megadtuk. 12

Főprogram - populálás #include <iostream> #include <fstream> #include <vector> #include "shapes.h" using namespace std; Shape* create(ifstream &inp); void statistic(); int main() { ifstream inp("shapes.txt"); if (inp.fail()) { cout << "Wrong file name!\n"; return 1; int shape_number; inp >> shape_number; vector<shape*> shapes(shape_number); for ( int i = 0; i < shape_number; ++i ){ shapes[i] = create(inp); inp.close(); 8 shapes.txt Cube 5.0 Cylinder 3.0 8.0 Cylinder 1.0 10.0 Tetrahedron 4.0 SquarePyramid 3.0 10.0 Octahedron 1.0 Cube 2.0 SquarePyramid 2.0 10.0 vector<shape> nem lenne jó, mert 1. a Shape absztrakt 2. a Shape-nek nincs üres konstruktora 3. a tömbbe a Shape leszármazottjainak referenciáit vagy pointereit kell betenni, hogy a futási idejű polimorfizmust használni tudjuk 13

Test példányosítása Shape* create(ifstream &inp) { Shape *p; string type; inp >> type; double size, height; inp >> size; if ("Cube" == type ) p = new Cube(size); Lehetne a Shape osztályszintű metódusa is, ha látnia kellene a Shape rejtett elemeit. else if ("Sphere" == type ) p = new Sphere(size); else if ("Tetrahedron" == type ) p = new Tetrahedron(size); else if ("Octahedron" == type ) p = new Octahedron(size); else{ inp >> height; if ("Cylinder" == type ) p = new Cylinder(size, height); else if ("SquarePrism" == type ) p = new SquarePrism(size, height); else if ("TriangularPrism" == type )p = new TriangularPrism(size, height); else if ("Cone" == type ) p = new Cone(size, height); else if ("SquarePyramid" == type ) p = new SquarePyramid(size, height); else cout << "Unknown shape" << endl; return p; A származtatás miatt lehet értékül adni egy Shape* típusú változónak egy Cube* pointert 14

Főprogram folyt. for ( Shape *p : shapes ){ cout << p->volume() << endl; A futási idejű polimorfizmus miatt statistic(); a Shape ősosztály virtuális volume() metódusa helyett a megfelelő test térfogatát számolja. for ( Shape *p : shapes ) delete p; statistic(); A futási idejű polimorfizmus miatt a Test ősosztály virtuális destruktora helyett a megfelelő test destruktora fut le. void statistic(){ cout << Shape::piece() << " " << Regular::piece() << " " << Prismatic::piece() << " " << Conical::piece() << " " << Sphere::piece() << " " << Cube::piece() << " " << Tetrahedron::piece() << " " << Octahedron::piece() << " " << Cylinder::piece() << " " << SquarePrism::piece() << " " << TriangularPrism::piece() << " " << Cone::piece() << " " << SquarePyramid::piece()<< endl; 15

Alapterületet számoló metódusok helyett objektumok <<interface>> Alapterület +terület(double):double {virtual Körterület +terület(double m):double {override Háromszögterület +terület(double m):double {override return π m m Négyzetterület return 3 m m/4 +terület(double m):double {override return m m Itt, és csak itt kell az alapterületeket definiálni megszűnik a redundancia. 16

Stratégia (strategy) tervezési minta Egy algoritmus-családot definiálunk azért, hogy annak algoritmusait felhasználhassuk, de hogy melyiket, azt a kód leírásakor még nem ismerjük. objektum összetétel révén megvalósuló felelősség átruházás: függőség befecskendezés (dependency injection) Environment method() ref.algorithm() ref Ennek a szerepnévnek hivatkozásként vagy pointerként kell az ellentétes oldali objektumban szerepelni, hogy a futásidejű polimorfizmus működjön. Strategy algorithm() {virtual attól függ a működése, hogy a ref mire hivatkozik StrategyA algorithm() StrategyB algorithm() A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 17

Hasábszerű #magasság :double -darab :int +térfogat():double {override +darab() :int return (alap.terület(méret)) magasság a Hasábszerű test konstruktora állítja be # alap Körterület <<interface>> Alapterület +terület(double):double {virtual Négyzetterület Háromszögterület Henger Hasáb Hasáb Kúpszerű -darab :int +darab():int S O L I D ingle responsibility iskov s substitution nterface segregation epedency inversion -darab :int +darab():int -darab :int +darab():int return ((alap.terület(méret)) magasság)/3 Kúp -darab :int +darab():int -darab :int +térfogat() :double {override +darab() :int Gúla -darab :int +darab():int 18

Cylinder::Cylinder( ) : Prismatic( ) { ++_piece; _basis = new CircleArea(); Cylinder::~Cylinder(){ --_piece; delete _basis; SquarePrism::SquarePrism( ) : Prismatic( ){ ++_piece; _basis = new SquareArea(); SquarePrism::~SquarePrism(){ --_piece; delete _basis; TriangularPrism::TriangularPrism( ) : Prismatic( ){ ++_piece; _basis = new TriangularArea(); TriangularPrism::~TriangularPrism(){ --_piece; delete _basis; Cone::Cone( ) : Conical( ){ ++_piece; _basis = new CircleArea(); Cone::~Cone(){ --_piece; delete _basis; SquarePyramid::SquarePyramid( ) : Conical( ){ ++_piece; _basis = new SquareArea(); SquarePyramid::~SquarePyramid(){ --_piece; delete _basis; Kritika a hatékonyságról: A kód-redundancia megszűnt, de előállt egy memória pazarlás: például 5 henger és 3 kúp létrehozásához összesen 8 körterület objektumot kell példányosítani, pedig egy is elég lenne, amelyet mindenki használhatna. 19

Egyke (singleton) tervezési minta Egy osztálynak legfeljebb egy objektumát akarjuk példányosítani függetlenül a példányosítási kérelmek számától. privát konstruktor: az osztály közvetlenül nem példányosítható Singleton - instance : Singleton - Singleton() + instance() : Singleton osztály szintű adattag: egy példányra hivatkozik if instance = nil then instance := new Singleton(); return instance; példányosítási kérelmeket kiszolgáló osztály szintű metódus: visszaad egy példányt A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 20

Egy adott alapterület kiszámolásához elég csak egyetlen objektum <<interface>> Alapterület +terület(double):double {virtual Körterület - példány : Körterület - Körterület() + terület(double m): double {override + példány() : Körterület Négyzetterület - példány:négyzetterület - Négyzetterület() + terület(double m):double {override + példány():négyzetterület Háromszögterület - példány:háromszögterület - Háromszögterület() + terület(double m):double {override + példány() : Háromszögterület if ( példány = nil ) példány := new Körterület(); return példány; if ( példány = nil ) példány := new Négyzetterület(); return példány; if ( példány = nil ) példány := new Háromszögterület(); return példány; 21

Cylinder::Cylinder( ) : Prismatic( ){ ++_piece; _basis = CircleArea::instance(); Cylinder::~Cylinder(){ --_piece; Cone::Cone( ) : Conical( ){ ++_piece; _basis = CircleArea::instance(); Cone::~Cone(){ --_piece; _basis = new CircleArea() helyett SquarePrism::SquarePrism( ) : Prismatic( ){ ++_piece; _basis = SquareArea::instance(); SquarePrism::~SquarePrism(){ --_piece; SquarePyramid::SquarePyramid( ) : Conical( ){ ++_piece; _basis = SquareArea::instance(); SquarePyramid::~SquarePyramid(){ --_piece; TriangularPrism ::TriangularPrism( ) : Prismatic( ){ ++_piece; _basis = TriangularArea::instance(); TriangularPrism::~TriangularPrism(){ --_piece; 22

2.Feladat Készítsünk programot, amellyel lények túlélési versenyét modellezhetjük. A lények három faj (zöldike, buckabogár, tocsogó) valamelyikéhez tartoznak. Minden lénynek van neve (sztring), ismert a faja, és az aktuális életereje (egész szám). A versenyen induló lények sorban egymás után egy olyan pályán haladnak végig, ahol három féle (homokos, füves, mocsaras) terep váltakozik. Amikor egy lény keresztül halad egy terepen, akkor a lény a fajtájától (és az adott tereptől is) függően átalakítja a terepet, miközben változik az életereje. Ha az életereje nulla vagy annál kevesebb értékű lesz, a lény elpusztul. Adjuk meg a pályán végigjutó, azaz életben maradt lények neveit! Zöldike: füvön az életereje eggyel nő, homokon kettővel csökken, mocsárban eggyel csökken; a mocsaras terepet fűvé alakítja, a másik két terep fajtát nem változtatja meg. Buckabogár: füvön az ereje kettővel csökken, homokon hárommal nő, mocsárban néggyel csökken; a füvet homokká, a mocsarat fűvé alakítja, de a homokot nem változtatja meg. Tocsogó: füvön az életereje kettővel, homokon öttel csökken, mocsárban hattal nő; a füvet mocsárrá alakítja, a másik két fajta terepet nem változtatja meg. 23

Hogyan alakít át egy lény egy terepet? átalakít : Lény Terep Lény Terep feltéve, hogy a lény él zöldikék életerő változás terepváltozás homokban -2 - fűben +1 - mocsárban -1 fűre buckabogarak életerő változás terepváltozás homokban +3 - fűben -2 homokra mocsárban -4 fűre tocsogók életerő változás terepváltozás homokban -5 - fűben -2 mocsárra mocsárban +6-24

Megoldási terv A : pálya: Terep m, lények: Lény n, túlélők: String* a pálya i-1-dik állapota az i-dik lény áthaladása előtt Ef : lények = lények 0 pálya = pálya 0 Uf : i [1..n]: (lények[i], pálya i ) = áthalad(lények 0 [i], pálya i-1 ) szimuláció kiválogatás túlélők = i=1..n <lények[i].név()> lények[i].él() közös felsorolóval történő szimuláció = dupla összegzés lények tömbjének összeállítása és a pálya fokozatos átalakítása kiválogatás = összegzés t:enor(e) ~ i = 1.. n f(e) ~ áthalad(lények[i], pálya) H,+,0 ~ Lény n Terep m, (, ), (<>, pálya 0 ) f(e) ~ <lények[i].név()> ha lények[i].él() H,+,0 ~ String*,, <> túlélők := <> i = 1.. n lények[i], pálya := áthalad(lények[i], pálya) lények[i].él() túlélők : write (lények[i].név()) régi új ::= új a pálya i-dik állapota az i-dik lény áthaladása után. (pálya = pálya n ) Egy tömb elemeinek összefűzésekor a megfelelő indexű elemet írjuk felül. 25

Egy lény áthaladása Az i-dik lény a pálya i-1 mezőin egyesével lépked (amíg él), és minden lépése megváltoztathatja az adott terepet, miközben a lény maga is átalakul. pálya i-1 A : pálya: Terep m, lény: Lény Ef : pálya = pálya lény = lény 0 a lények 0 [i] (a verseny előtt) a lények[i] állapota a j-1-dik lépés után Uf: j [1..m]: (lény j, pálya[j]) = átalakít(lény j-1, pálya [j]) lény = lény m pálya i [j] a lények[i] a verseny után ha lény j.él() akkor skip lény, pálya[j] := átalakít(lény, pálya[j] ) a pálya elemeinek összefűzésekor a megfelelő indexű elemet írjuk felül Feltételig tartó dupla összegzés (fokozatos átalakítás és összefűzés) : t:enor(e) ~ j = 1.. m amíg lény.él() f(e) ~ átalakít(lény, pálya[j]) H,+,0 ~ Lény Terep m, (, ), (lény 0, <>) lény, pálya := áthalad(lény, pálya) j := 1 lény.él() j m lény.átalakít(pálya[j]) j := j+1 26

Főprogram // populating // competition for ( int i=0; i < n; ++i ){ for ( int j=0; creatures[i]->alive() && j < m; ++j ){ creatures[i]->transmute(courts[j]); if (creatures[i]->alive() ) cout << creatures[i]->name() << endl; // destroying main.cpp Itt jól jönne a futási idejű polimorfizmus, azaz hogy a creatures[i] és a courts[j] aktuális típusától függjön a transmute(), és az alive() működése. 27

Lények származtatása Lény # név : string # erő : int + átalakít(terep):void {virtual <<getter>> + név():string + él():bool <<setter>> + válterő(p:int):void return név return erő>0 erő := erő + p Zöldike + átalakít(terep):void {override Buckabogár + átalakít(terep):void{override Tocsogó + átalakít(terep):void {override 28

Lények átalakít() metódusai void Greenfinch::transmute(int &court) { if ( alive() ){ switch(court){ O case 0: _power-=2; break; L case 1: _power+=1; break; case 2: _power-=1; court = 1; break; I void DuneBeetle::transmute(int &court) { D if (alive() ){ switch(court){ case 0: _power+=3; break; case 1: _power-=2; court = 0; break; case 2: _power-=4; court = 1; break; Kritika a kódról: - rosszul olvasható: a terepeket azonosító egész számok nem beszédes jelölések - nem rugalmas: újabb terepfajta bevezetése esetén ezeket az elágazásokat módosítani kell, azaz meglévő kódon kell változtatni void Squelchy::transmute(int &court) { if (alive() ){ switch(court){ S ingle responsibility pen-closed iskov s substitution nterface segregation Depedency inversion case 0: _power-=5; break; case 1: _power-=2; court = 2; break; case 2: _power+=6; break; lehetne: enum Ground { sand, grass, marsh 29

Terepek származtatása Homok + átalakít(zöldike):terep {override + átalakít(buckabogár):terep {override + átalakít(tocsogó):terep {override <<interface>> Terep + átalakít (Zöldike):Terep {virtual + átalakít (Buckabogár):Terep {virtual + átalakít (Tocsogó):Terep {virtual Fű pointerekkel vagy referenciaként kell hivatkozunk mind a lények, mind a terepek objektumaira Itt összesen 9 darab, lény és terep függő átalakít() metódus van. Újabb terepfajta esetén új osztályt kell 3 új átalakít() metódussal definiálni. Újabb lényfajta esetén minden osztályba 1-1 újabb átalakít() metódust kell betenni. De meglevő kódon nem kell változtatni. + átalakít(zöldike):terep {override + átalakít(buckabogár):terep {override + átalakít(tocsogó):terep {override Mocsár + átalakít(zöldike):terep {override + átalakít(buckabogár):terep {override + átalakít(tocsogó):terep {override 30

Lények osztálydiagramja újra Lény # név : string # erő : int + átalakít(terep) : void {virtual <<getter>> + él() : bool + név() : string Terep Zöldike + átalakít(t:terep):void {override Buckabogár t = t.átalakít(this) + átalakít(t:terep):void {override Tocsogó t = t.átalakít(this) + átalakít(t:terep):void {override ez lett a három ágú elágazásból t = t.átalakít(this) 31

Látogató (visitor) tervezési minta Amikor egy metódus működése attól függ, hogy egy objektum-készlet melyik objektumát kapja meg paraméterként, de nem akarunk ezen készlet számától függő elágazást használni a metódus leírásához. Element accept(v:visitor) {virtual Visitor visita(elementa) {virtual visitb(elementb) {virtual ElementA ElementB Concrete_Visitor1 Concrete_ Visitor2 accept(v:visitor) {override v.visita(this) accept(v:visitor) {override v.visitb(this) visita(elementa) {override visitb(elementb) {override visita(elementa) {override visitb(elementb) {override A tervezési minták az objektum-alapú modellezést támogató osztálydiagram minták, amelyek az újrafelhasználhatóság, rugalmas módosíthatóság, hatékonyság biztosításában játszanak szerepet. 32

Lények látogatókkal class Creature{ protected: int _power; std::string _name; Creature (const std::string &str, int e = 0) :_name(str), _power(e) { public: std::string name() const { return _name; bool alive() const { return _power > 0; void changepower(int e) { _power += e; virtual void transmute(ground* &court) = 0; virtual ~Creature () { ; creature.h class Greenfinch : public Creature { public: Greenfinch(const std::string &str, int e = 0) : Creature(str, e){ void transmute(ground* &court) override {court = court->transmute(this); ; class DuneBeetle : public Creature { public: DuneBeetle(const std::string &str, int e = 0) : Creature(str, e){ void transmute(ground* &court) override {court = court->transmute(this); ; class Squelchy : public Creature { public: Squelchy(const std::string &str, int e = 0) : Creature(str, e){ void transmute(ground* &court) override {court = court->transmute(this); ; 33

Terep és lény függő metódusok Ground* Sand::transmute(Greenfinch *p){ p->changepower(-2); return this; Ground* Sand::transmute(DuneBeetle *p){ p->changepower(3); return this; Ground* Sand::transmute(Squelchy *p){ p->changepower(-5); return this; Ground* Marsh::transmute(Greenfinch *p){ p->changepower(-1); return new Grass; Ground* Marsh::transmute(DuneBeetle *p){ p->changepower(-4); return new Grass; Ground* Marsh::transmute(Squelchy *p){ p->changepower(6); return this; ground.cpp Ground* Grass::transmute(Greenfinch *p){ p->changepower(1); return this; Ground* Grass::transmute(DuneBeetle *p){ p->changepower(-2); return new Sand; Ground* Grass::transmute(Squelchy *p){ p->changepower(-2); return new Marsh; Kritika a hatékonyságról: - Memória szivárgást okoz a court = court->transmute(this) végrehajtása, hiszen a korábbi court által mutatott objektumot nem szabadítjuk fel. - Ugyanazon fajtájú terep-objektumból sok azonos jön létre a sorozatos transmute() hívásokkal. Elég lenne egy-egy objektum minden terepfajtából. 34

Legyenek a Terep osztályok egykék Ground* Grass::transmute(Greenfinch *p){ p->changepower(1); return this; Ground* Grass::transmute(DuneBeetle *p){ p->changepower(-2); return Sand::instance(); A memóriafoglalást a new helyett az instance() osztály szintű (static) Ground* Grass::transmute(Squelchy *p){ metódus végzi. p->changepower(-2); return Marsh::instance(); void Grass::instance() { if ( nullptr ==_instance ) _instance = new Sand(); return _instance; osztály szintű (static) törlő metódus void Grass::destroy() { if ( nullptr!=_instance ) delete _instance; ground.cpp 35

Feladat felpopulálása // populating ifstream f("input.txt"); if (f.fail()) { cout << "Wrong file name!\n"; return 1; int n; f >> n; vector<creature*> creatures(n); for ( int i=0; i<n; ++i ){ char ch; string name; int p; f >> ch >> name >> p; switch(ch){ 4 input.txt S plash 20 G greenish 10 D bug 15 S sponge 20 10 0 2 1 0 2 0 1 0 1 2 case 'G' : creatures[i] = new Greenfinch(name, p); break; case 'D' : creatures[i] = new DuneBeetle(name, p); break; case 'S' : creatures[i] = new Squelchy(name, p); break; // destroying creatures for (int i=0; i<n; ++i) delete creatures[i]; int m; f >> m; // destroying creatures vector<ground*> courts(m); Sand::destroy(); for ( int j=0; j<m; ++j ) { Grass::destroy(); int k; f >> k; Marsh::destroy(); switch(k){ case 0 : courts[j] = Sand::instance(); break; case 1 : courts[j] = Grass::instance(); break; case 2 : courts[j] = Marsh::instance(); break; main.cpp 36

Csomagok #include "creature.h" körkörös include hivatkozást okozna. Itt azonban elég csak jelezni, hogy vannak ilyen osztályok. #pragma once #include "ground.h" #pragma once #include class Greenfinch; "creature.h" class DuneBeetle; class Squelchy; class Ground{ public: virtual Ground* transmute(greenfinch *g) = 0; virtual Ground* transmute(dunebeetle *d) = 0; virtual Ground* transmute(squelchy *s) = 0; ; class Sand : public Ground { class Grass : public Ground { class Marsh : public Ground { class Creature { ; class Greenfinch : public Creature { void transmute(ground* &court) override {court = court->transmute(this); ; class DuneBeetle : public Creature { ; class Squelchy : public Creature { ; creature.h ground.h #include "ground.h" #include "creature.h" ground.cpp 37