Documente Academic
Documente Profesional
Documente Cultură
Curs 5
1
Introducere în Şabloanele Creaţionale
2
Diagrama de clase pentru Labirint
4 MapSite
enter()=0;
1
rooms Room Wall Door
Maze
1 * enter()
enter() enter()
setSide()
getSide() isOpen
roomNumber
3
Clase abstracte comune tuturor Componentelor
Labirintului
enum Direction {North, South, East, West};
class MapSite {
public:
virtual void enter() = 0;
};
4
Componentele labirintului – Perete & Uşă & Cameră
class Wall : public MapSite {
public:
Wall();
class Room : public MapSite {
virtual void enter();
public:
};
Room(int roomNo);
MapSite* getSide(Direction) const;
void setSide(Direction, MapSite*);
class Door : public MapSite {
void enter(); public:
private: Door(Room* = 0, Room* = 0);
MapSite* sides[4]; virtual void enter();
int roomNumber; Room* otherSideFrom(Room*);
} private:
Room* room1;
Room* room2;
bool isOpen;
};
5
Componentele labirintului – Maze
6
Desfăşurarea jocului!
4
MapSite
MazeGame enter()=0;
1
1
rooms Room Wall Door
Maze 1 1..n enter()
enter() enter()
setSide()
getSide() isOpen
1..n
roomNumber
Player
7
Crearea Labirintului
Maze* MazeGame::createMaze() {
Maze* aMaze = new Maze;
Room* r1 = new Room(1);
Room* r2 = new Room(2);
Door* theDoor = new Door(r1, r2);
aMaze->addRoom(r1);
aMaze->addRoom(r2);
8
Dorim Flexibilitate în Crearea Labirintului
9
Ideea 1:
Derivăm MazeGame, suprascriem createMaze
Maze* BombedMazeGame::createMaze() {
Maze* aMaze = new Maze;
Room* r1 = new RoomWithABomb(1);
Room* r2 = new RoomWithABomb(2);
Door* theDoor = new Door(r1, r2);
aMaze->addRoom(r1);
aMaze->addRoom(r2);
10
Ideea 2:
Folosim Metoda Factory
4 MapSite
MazeGame enter()=0;
makeWall()
createMaze()
1
Room Wall Door
enter()
enter() enter()
BombedMazeGame setSide()
getSide() isOpen
makeWall()
roomNumber
BombedWall
return new BombedWall
enter()
12
Aspecte de Bază
Scop
Defineşte o interfaţă pentru crearea unui obiect, dar lasă subclasele să
decidă ce clasă să instanţieze.
Metoda Factory permite unei clase să defere instanţierea subclaselor
Cunoscut şi ca
Constructor Virtual
Aplicabilitate
O clasă nu poate anticipa clasa obiectelor pe care trebuie să le creeze
O clasă doreşte ca subclasele sale să specifice obiectele pe care le
creează
Clasele delegă responsibilitatea uneia sau mai multor subclase ajutătoare
13
Structură
14
Participanţi & Colaborări
Product
defineşte interfaţa obiectelor ce vor fi create de FM
Produs Concret implementează interfaţa
Creator
declară FM, care returnează un produs de tip Product.
poate defini o implementare implicită a FM
poate apela FM pentru crearea unui produs
ConcreteCreator
suprascrie FM pentru a furniza o instanţă a ConcreteProduct
Facilitează derivarea
subclasele pot astfel modifica produsul creat
16
Conectarea Ierarhiilor Paralele de Clase
17
Detalii de Implementare
Varietăţi ale Metodelor Factory
Clasa Creator e abstractă
nu implementează FM declarată
necesită subclase
folosită pentru instanţierea claselor neprevăzute
Clasa Creator e concretă
creează o implementare implicită
FM folosite pentru flexibilitate
Creează obiecte într-o operaţie separată astfel încât subclasele o
pot suprascrie
Parametrizarea Metodelor Factory
O variaţie a şablonului lasă metodele factory să creeze mai
multe tipuri de produse
un parametru identifică tipul de Product de creat
Toate obiectele create au aceeaşi interfaţă cu Product
18
Parametrizarea Metodei Factory
class Creator {
public:
virtual Product * create(productId);
};
class Creator {
private String productType;
public FactoryMethod( ) {
Class productClass = Class.forName(productType);
return (Product) productClass.newInstance();
}
20
Metoda Factory poate fi parametrizată:
class ProductA extends Product {
import java.util.*; public void doSomething()
{System.out.println("ProductA");
class AbstractFactory { }}
public Product make(String c) {
try { class ProductB extends Product {
Class prod = Class.forName(c); public void doSomething()
{System.out.println("ProductB");
return }}
(Product)prod.newInstance();}
class Main {
catch(Exception e) { public static void main(String[] args)
System.out.println("Error"); {AbstractFactory af = new
System.exit(1); AbstractFactory();
return null; } }} af.make(args[0]).doSomething();
}}
abstract class Product {
abstract public void
doSomething();
}
21
C++: Template-uri pentru evitarea derivării
// ....
Creator<ConcreteProduct> theBest;
22
Soluţia Problemei Labirintului (reluare)...
4 MapSite
MazeGame enter()=0;
makeWall()
createMaze()
1
Room Wall Door
enter()
enter() enter()
BombedMazeGame setSide()
getSide() isOpen
makeWall()
roomNumber
BombedWall
return new BombedWall
enter()
23
Clasa MazeGame şi metoda CreateMaze()
class MazeGame {public: Maze* MazeGame::CreateMaze ()
Maze* createMaze(); {Maze* aMaze = makeMaze();
// metode factory: Room* r1 = makeRoom(1);
virtual Maze* makeMaze() const Room* r2 = makeRoom(2);
Door* theDoor =makeDoor(r1, r2);
{ return new Maze; }
aMaze->addRoom(r1);
virtual Room* makeRoom(int n) const aMaze->addRoom(r2);
{ return new Room(n); } r1->SetSide(North, makeWall());
r1->SetSide(East, theDoor);
virtual Wall* makeWall() const r1->SetSide(South, makeWall());
{ return new Wall; }
r1->SetSide(West, makeWall());
r2->SetSide(North, makeWall());
virtual Door* makeDoor(Room* r1,
Room* r2) const
r2->SetSide(East, makeWall());
r2->SetSide(South, makeWall());
{ return new Door(r1, r2); }};
r2->SetSide(West, theDoor);
return aMaze; }
24
Ideea 3:
Metodă Factory în Product
25
Cod exemplu- este acesta un Prototype?
26
Şablonul Prototype
27
Introducere
Scop
Specificaţi tipul obiectelor care se creează folosind o
instanţă prototipică
Creaţi obiecte noi copiind acest prototip
Aplicabilitate
când un sistem trebuie să fie independent de cum
sunt create, compuse şi reprezentate produsele sale şi
când clasele de instanţiat sunt specificate la execuţie
evitaţi construirea unei ierarhii de clase-factory
paralelă cu ierarhia claselor de produse
28
Structură
29
Participanţi & Colaborări
Prototype
declară o interfaţă pentru a se clona.
ConcretePrototype
implementează o operaţie pentru a se clona.
Client
creează un obiect nou cerând prototipului să se cloneze.
30
Consecinţe
Adăugarea şi ştergerea produselor la execuţie
Mai puţină derivare
evită ierarhia paralelă pentru creatori
Specificarea de obiecte noi prin varierea valorilor
prototipurilor
clientul se comportă diferit prin delegarea către prototip
Specificarea de obiecte noi prin varierea structurii
prototipurilor
produse compuse
31
Detalii de Implementare
Iniţializarea clonelor
eterogenitatea metodelor de iniţializare
scrieţi o metodă Initialize
32
Copie de Suprafaţă vs. Copie de Profunzime
Original
Copie de suprafaţă
33
Copie de Suprafaţă vs. Copie de Profunzime (2)
Original
Copie de Profunzime
34
Clonarea în C++ – Constructorii de Copiere
class Door {
public:
Door();
Door( const Door&);
virtual Door* clone() const;
virtual void Initialize( Room*, Room* );
private:
Room* room1; Room* room2;
};
//constructor de copiere
Door::Door ( const Door& other ) {
room1 = other.room1; room2 = other.room2;
}
Door* Door::clone() {
return new Door( *this );
}
35
Clonarea în Java – Object clone()
36
Rezolvarea Problemei Labirintului
class MazePrototypeFactory { Wall* MazePrototypeFactory::MakeWall () const
public: {return _prototypeWall->Clone();}
MazePrototypeFactory(Maze*, Wall*,
Room*, Door*); Door* MazePrototypeFactory::MakeDoor (
Room* r1, Room *r2) const {
virtual Maze* MakeMaze() const; Door* door = _prototypeDoor->Clone();
virtual Room* MakeRoom(int) const; door->Initialize(r1, r2);
virtual Wall* MakeWall() const; return door;}
virtual Door* MakeDoor(Room*, Room*)
const; Crearea unui labirint pentru un joc…
private: MazePrototypeFactory simpleMazeFactory
Maze* _prototypeMaze; (new Maze, new Wall, new Room, new Door);
Room* _prototypeRoom; MazeGame game;
Wall* _prototypeWall; Maze* maze =
Door* _prototypeDoor;}; game.CreateMaze(simpleMazeFactory);
MazePrototypeFactory::MazePrototypeFactory (
Maze* m, Wall* w, Room* r, Door* d)
{ _prototypeMaze = m;
_prototypeWall = w;
_prototypeRoom = r;
_prototypeDoor = d;}
37
Abstract Factory
38
Exemplu Introductiv
39
Aspecte de bază
Scop
Oferă o interfaţă pentru crearea de familii de obiecte înrudite
sau dependente fără specificarea claselor lor concrete
Aplicabilitate
Sistemul trebuie să fie independent de cum sunt create, compuse
şi reprezentate produsele sale
Sistemul trebuie configurat de una din mai multe familii de
produse
Trebuie forţat ca o familie de obiecte produs să fie folosite
împreună
40
Structură
41
Participanţi & Colaborări
Abstract Factory
declară o interfaţă pentru operaţii pentru crearea de produse
abstracte
ConcreteFactory
implementează operaţiile de creare a produselor
AbstractProduct
declară o interfaţă pentru un tip de obiecte produs
ConcreteProduct
implementează o interfaţă pentru un tip de obiecte produs
Client
foloseşte doar interfeţe decl. de AbstractFactory şi
AbstractProduct
43
Detalii de Implementare
Fabrici ca Singleton-uri
pentru a asigura că doar un singur ConcreteFactory este creat
pentru fiecare familie de produse
Crearea Produselor
colecţie de Metode Factory
poate fi implementat şi folosind Prototype
definiţi o instanţă prototipică pentru fiecare produs din
ConcreteFactory
44
Crearea Produselor folosind propriile metode factory
45
Crearea Produselor folosind metodele factory ale produselor
46
Rezolvarea Problemei Labirintului....
class MazeFactory { Maze* MazeGame::CreateMaze (MazeFactory&
public: factory) {
MazeFactory(); Maze* aMaze = factory.MakeMaze();
Room* r1 = factory.MakeRoom(1);
virtual Maze* MakeMaze() const Room* r2 = factory.MakeRoom(2);
{ return new Maze; } Door* aDoor = factory.MakeDoor(r1, r2);
virtual Wall* MakeWall() const
{ return new Wall; } aMaze->AddRoom(r1);
virtual Room* MakeRoom(int n) const aMaze->AddRoom(r2);
{ return new Room(n); }
virtual Door* MakeDoor(Room* r1, Room* r2) r1->SetSide(North, factory.MakeWall());
const r1->SetSide(East, aDoor);
{ return new Door(r1, r2); } r1->SetSide(South, factory.MakeWall());
}; r1->SetSide(West, factory.MakeWall());
r2->SetSide(North, factory.MakeWall());
r2->SetSide(East, factory.MakeWall());
r2->SetSide(South, factory.MakeWall());
r2->SetSide(West, aDoor);
return aMaze;
}
47
Singleton
48
Introducere
Scop
Asigură ca o clasă să aibă doar o singură instanţă şi furnizează un
punct de acces global la ea
Aplicabilitate
dorim exact o instanţă a unei clase
accesibilitate pentru clienţi dintr-un singur punct
dorim ca instanţa să fie extensibilă
poate permite deasemenea şi un set numărabil de instanţe
optimizare faţă de vizibilitatea globală
mai bine decât o clasă statică:
nu se poate răzgândi
metode niciodată virtuale
49
Structura Şablonului
50
Participanţi şi Colaborări
Singleton
defineşte o metodă Instance care devine singura “poartă" prin
care clienţii pot accesa instanţa sa unică.
Instance este o metodă a clasei (funcţie membră statică în C++)
Poate fi responsabil cu crearea propriei sale instanţe unice
51
Consecinţe
52
Implementare: Asigurarea Instanţei Unice
53
Implementare: Derivarea Singleton
54
Crearea unei singure MazeFactory
55
Şi dacă există subclase ale MazeFactory?
56