Sunteți pe pagina 1din 12

MINISTERUL EDUCAŢIEI AL REPUBLICII MOLDOVA

UNIVERSITATEA TEHNICĂ A MOLDOVEI


FACULTATEA CALCULATOARE, INFORMATICǍ ȘI MICROELECTRONICǍ
DEPARTAMENTUL INGINERIA SOFTWARE ȘI AUTOMATICĂ

RAPORT
Lucrarea de laborator nr. 3
Disciplina : Tehnici și mecanisme de proiectare software
Tema : Șabloane de proiectare comportamentale

A efectuat: st.gr. TI–171 F/r


Roșca Doinița

A verificat: asist.univ.
Poștaru Andrei

Chișinău 2021
Sarcina lucrării
De implementat 3 șabloane comportamentale la alegere .

Mersul lucrării
Fiecare şablon descrie o problemă care apare mereu în domeniul nostru de activitate şi indică esenţa
soluţiei acelei probleme într-un mod care permite utilizarea soluţiei de nenumărate ori în contexte diferite .
Un sablon reprezintă o soluţie comună a unei probleme într-un anumit context .
Șabloanele ne usurează viața . Cu ajutorul lor putem să înțelegem “mai bine” POO . Uneori pot reduce
ordinul de complexitate al problemei sau fac definițiile obiectelor mai ușor de înțeles .
După scop avem trei șabloane :
 Şabloanele creaţionale (creational patterns) privesc modul de creare al obiectelor .
 Şabloanele structurale (structural patterns) se referă la compoziţia claselor sau al obiectelor .
 Şabloanele comportamentale (behavioral patterns) caracterizează modul în care obiectele şi clasele
interacţionează şi îşi distribuie responsabilităţile .
După domeniu de aplicare se clasifică în :
 Şabloanele claselor se referă la relaţii dintre clase , relaţii stabilite prin moştenire şi care sunt statice
(fixate la compilare) .
 Şabloanele obiectelor se referă la relaţiile dintre obiecte , relaţii care au un caracter dinamic .

 
Şabloanele comportamentale caracterizează modul în care obiectele şi clasele interacţionează şi îşi
distribuie responsabilităţile .
Șablonul Command
Conform şablonului command un obiect poate încapsula toate informaţiile necesare pentru apelarea unei
metode a altui obiect , cum ar fi : numele metodei de apelat , obiectul ce deţine metoda şi valorile de
transmis parametrilor .

Clientul instanţiază obiectul de tip comandă şi îl pregăteşte pentru a fi apelat la un moment ulterior .
Obiectul invoker decide când va fi apelat obiectul comandă . Obiectul receiver este cel care va efectua o
acţiune ca urmare a lansării în execuţie a comenzii . Beneficiile acestui şablon ţin de faptul că execuţia unei
anumite metode poate fi pregătită din timp , în aşa fel încât aceasta să fie lansată fără să i se ştie numele ,
obiectul de care aparţine şi momentul exact al execuţiei .
Şablonul command poate fi utilizat pentru a realiza aplicaţii cu :
- funcţionalităţi de tip „undo” ;
- comportament tranzacţional ;
- progress bar sincronizat cu execuţia unui grup de comenzi ;
- funcţionalităţi de tip „wizard” ;
- înregistrări de macro-uri ;
De exemplu , dacă un păpuşar (client) doreşte să pună o păpuşă (receiver) să se bucure (concrete
command) foloseşte un invoker , iar acesta îi transmite păpuşii să ţopăie (metoda action din şablon) .
Şablonul command încapsulează o cerere într-un obiect, care permite stocarea comenzii, trimiterea
comenzii la o metodă și întoarcerea comenzii la fel ca orice alt obiect.

Codul sursă Command


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Command
{
class Program
{
static void Main(string[] args)
{
MobileDeviceButton mobileDevice = new SmartPhone();
SmartPhoneVolumeUp volUpCommand = new SmartPhoneVolumeUp(mobileDevice);

VolumeButton volumeButton = new VolumeButton(volUpCommand);

volumeButton.Press();
volumeButton.Press();
volumeButton.Press();

volumeButton.PressUndo();

Console.ReadKey();
}
}

public interface MobileDeviceButton


{
void VolumeUp();
void VolumeDown();
}

class SmartPhone : MobileDeviceButton


{
private int volume = 0;

public void VolumeUp()


{
volume++;
Console.WriteLine("SmartPhone volume is at: " + volume);
}

public void VolumeDown()


{
volume--;
Console.WriteLine("SmartPhone volume is at: " + volume);
}
}

public interface Command


{
void Execute();
void Undo();
}

class SmartPhoneVolumeUp : Command


{
MobileDeviceButton button;

public SmartPhoneVolumeUp(MobileDeviceButton newButton)


{
button = newButton;
}

public void Execute()


{
button.VolumeUp();
}

public void Undo()


{
button.VolumeDown();
}
}
class VolumeButton
{
Command command;

public VolumeButton(Command newCommand)


{
command = newCommand;
}

public void Press()


{
command.Execute();
}

public void PressUndo()


{
command.Undo();
}
}
}

Rezultatul
Șablonul Mediator
Şablonul mediator defineşte un obiect care încapsulează modul în care un set de obiecte interacționează .
Mediator promovează cuplarea slabă împiedicînd obiectele să se refere unul pe altul în mod explicit , și
permite programatorului să varieze interacțiunea lor independent .
De obicei o aplicaţie este alcătuită dintr-un număr important de clase . Cu cât sunt mai multe clase într-o
aplicaţie , problema comunicării între obiecte devine mai complex , ceea ce face programul mai greu de citit
şi întreţinut . Modificarea programelor , în astfel de situaţii , devine mai dificilă din moment ce orice
modificare poate afecta codul din mai multe clase . Cu ajutorul şablonului mediator comunicaţia dintre
obiecte este încapsulată în obiectul mediator . Obiectele nu mai comunică direct între ele , ci comunică în
schimb prin intermediul mediatorului . Acest lucru reduce dependenţa între obiecte , micşorând cuplarea . În
contextul acestei diagrame termenul de coleg este utilizat pentru a desemna un obiect ce doreşte să comunice
cu alte obiecte din acelaşi grup , un grup având un singur moderator .

Mediator - defineşte interfaţa de comunicare între obiecte .


ConcreteMediator - implementează interfaţa Mediator şi coordonează comunicarea între objecte . Ştie
care sunt toate obiectele ce doresc să comunice şi scopurile acestor comunicări .
ConcreteColleague – comunică cu alte obiecte “colegi” cu ajutorul mediatorului .
Şablonul mediator se poate combina cu şablonul singleton , dacă o clasă concretă mediator are sens să fie
instanţiată o singură data . Într-un astfel de caz , dacă aplicaţia abstractizează mai multe grupuri de colegi ,
pentru fiecare grup se poate crea câte o clasă concretă mediator care să fie instanţiată o singură data .
Şablonul mediator nu trebuie confundat cu şablonul proxy . Diferenţa principală este faptul că mediatorii şi
colegii nu sunt creaţi pe baza aceleiaşi interfeţe (sau clase abstracte) . Un proxy este „imaginea” unui alt
obiect , prin urmare structura unui proxy depinde destul de mult de structura obiectului destinaţie . Nu
degeaba şablonul proxy este inclus în grupul şabloanelor structural .
Structura unui mediator nu este imaginea în oglindă a unui obiect coleg , ceea ce îi dă posibilitatea să
transmită mesajele spre mai multe tipuri de clase concrete de colegi , altfel spus să medieze mesajele între
colegi cu structuri diferite .

Codul sursă Mediator


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mediator
{
class Program
{
static void Main(string[] args)
{
MobilePhone mobilePhone = new MobilePhone();

John john = new John(mobilePhone);


George george = new George(mobilePhone);

mobilePhone.John = john;
mobilePhone.George = george;

john.Send("How are you George?");


george.Send("Fine, you?");

Console.ReadKey();
}
}

abstract class AbstractMobilePhone


{
public abstract void Send(string message, Contact colleague);
}

class MobilePhone : AbstractMobilePhone


{
private John john;
private George george;

public John John


{
set { john = value; }
}

public George George


{
set { george = value; }
}

public override void Send(string message, Contact colleague)


{
if (colleague == john)
{
george.Notify(message);
}
else
{
john.Notify(message);
}
}
}

abstract class Contact


{
protected AbstractMobilePhone mediator;

public Contact(AbstractMobilePhone mediator)


{
this.mediator = mediator;
}
}

class John : Contact


{
public John(AbstractMobilePhone mediator)
: base(mediator)
{
}

public void Send(string message)


{
mediator.Send(message, this);
}

public void Notify(string message)


{
Console.WriteLine("George: " + message);
}
}

class George : Contact


{
public George(AbstractMobilePhone mediator)
: base(mediator)
{
}

public void Send(string message)


{
mediator.Send(message, this);
}

public void Notify(string message)


{
Console.WriteLine("John: " + message);
}
}
}

Rezultatul
Șablonul Observer
Şablonul observer defineşte o dependenţă de tip 1-la-n între obiecte , astfel că atunci cînd un obiect se
modifică , cele care depind de el sunt notificate şi actualizate automat .
Şablonul observator este un şablon de proiectare în care un obiect gestionează o listă cu proprii
dependenţi, pe care îi anunţă automat de eventualele modificări de stare , de obicei prin apelarea anumitor
metode . De multe ori acest şablon este folosit pentru implementarea sistemelor distribuite .

Clasa Subject este o clasă abstractă (sau o interfaţă) ce asigură ataşarea şi scoaterea observatorilor . Clasa
conţine pe lângă o listă privată cu observatori şi următoarele metode:
- attach( ) – adaugă un nou observator în listă ;
- detach( ) – elimină un observator din listă ;
- notifyObserver( ) – anuntă fiecare observator asupra unei schimbări de stare prin apelarea metodelor
update( ) ale acestora .
Clasa ConcreteSubject este elementul de interes al observatorilor . Ea trimite o notificare tuturor
observatorilor prin apelarea metodei notifyObserver( ) din clasa ei părinte .
Clasa ConcreteSubject conţine pe lângă interfaţa Subject metoda GetState ce returnează starea
subiectului de observant .
Clasa Observer defineşte o interfaţă pentru anunţarea tuturor observatorilor asupra modificărilor
survenite în subiect . Interfaţa constă într-o metodă ce va fi suprascrisă de fiecare observator concret .
Clasa ConcreteObserver gestionează o referinţă către clasa ConcreteSubject şi conţine operaţia update( ) .
Când acestă operaţie este apelată de către subiect , ConcreteObserver apelează operaţia GetState a
subiectului pentru a-şi actualiza informaţi privind starea subiectului . Operaţia update( ) poate primi eventual
parametri cu informaţii generale ale evenimentului apărut , informaţii utile observatorului .
Şablonul observator este utilizat atunci când modificarea stării unui obiect afectează alte obiecte şi nu se
ştie la momentul scrierii codului exact ce obiecte vor trebui anunţate .
Exemplu de folosire a şablonului observer : implementarea modurilor de lucru , când într-o fereastră de
dialog utilizarea unui obiect poate presupune disponibilizarea sau indisponibilizarea altor obiecte . În
terminologia acestui şablon toate obiectele de pe un formular sunt observatori , iar subiectul concret de
observat este chiar formularul . Fiecare obiect în parte nu trebuie să modifice direct celelalte obiecte de pe
formular pentru că ar trebui să cunoască mulţimea acestora . Aceeaşi funcţionalitate a modurilor de lucru ar
putrea fi implementată şi cu ajutorul şablonului mediator .

Codul sursă Observator


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Observer
{
class Program
{
static void Main(string[] args)
{
NationalGeographics ng = new NationalGeographics();
Subscriber mark = new Subscriber("Mark");
Subscriber smith = new Subscriber("Smith");

ng.Subscribe(mark);
ng.Subscribe(smith);

ng.ArticlesList++;

Console.ReadLine();
}
}

abstract class INationalGeographics


{
public abstract void Subscribe(Subscriber observer);
public abstract void Unsubscribe(Subscriber observer);
public abstract void Notify();
}

class NationalGeographics : INationalGeographics


{
private List<Subscriber> subsribers = new List<Subscriber>();
private int articles;

public int ArticlesList


{
get
{
return articles;
}
set
{
if (value > articles)
Notify();
articles = value;
}
}
public override void Subscribe(Subscriber subscriber)
{
subsribers.Add(subscriber);
}

public override void Unsubscribe(Subscriber subscriber)


{
subsribers.Remove(subscriber);
}

public override void Notify()


{
foreach (Subscriber subscriber in subsribers)
{
subscriber.Update();
}
}
}

class Subscriber
{
public string ObserverName { get; private set; }

public Subscriber(string name)


{
this.ObserverName = name;
}

public void Update()


{
Console.WriteLine("{0}, A new article was posted on the website for you to read",
this.ObserverName);
}
}
}

Rezultatul
Concluzie
Şabloanele comportamentale ne ajută să reducem complexitatea codului , precum și dublarea acestuia ,
oferă o mai bună întreţinere de către alții programatori .
În urma efectuării acestei lucrări , am studiat și analizat șabloanele de proiectare comportamentale , pe
care le-am implementat în cadrul temei alese . Aam studiat posibilitățile de implementare ale acestor
șabloane, dar și însăși conceptul șabloanelor , după care le-am implementat cu ajutorul limbajului C# .

S-ar putea să vă placă și