Differences

This shows you the differences between two versions of the page.

Link to this comparison view

poo-ca-cd:laboratoare:design-patterns [2022/12/12 12:19]
radu_bogdan.pavel [Exerciții]
poo-ca-cd:laboratoare:design-patterns [2024/11/20 14:42] (current)
bogdan.rusu1707 [Exerciții]
Line 1: Line 1:
-===== Laboratorul ​9: Design patterns - Factory, Strategy, Observer, Command, Builder =====+===== Laboratorul ​7: Design patterns - Factory, Strategy, Observer, Command, Builder =====
  
 **Video introductiv:​** [[https://​www.youtube.com/​watch?​v=khRqWZrz1YU | link]] + [[https://​www.youtube.com/​watch?​v=F2HMN4mvVYY | link]] **Video introductiv:​** [[https://​www.youtube.com/​watch?​v=khRqWZrz1YU | link]] + [[https://​www.youtube.com/​watch?​v=F2HMN4mvVYY | link]]
Line 35: Line 35:
  
  
-În laboratoarele precedente au fost descrise patternurile [[:​poo-ca-cd:laboratoare:static-final#​singleton_pattern|Singleton]] și [[:​poo-ca-cd:laboratoare:visitor|Visitor]]. //​Singleton//​ este un pattern creațional,​ simplu, a cărui folosire este controversată (vedeți în [[:​poo-ca-cd:​laboratoare:​static-final#​singleton_pattern|laborator]] explicația cu anti-pattern). //Visitor// este un pattern comportamental,​ și după cum ați observat oferă avantaje în anumite situații, în timp ce pentru altele nu este potrivit. Pattern-urile comportamentale modelează interacțiunile dintre clasele și componentele unei aplicații, fiind folosite în cazurile în care vrem sa facem un design mai clar și ușor de adaptat și extins.+În laboratoarele precedente au fost descrise patternurile [[https://​ocw.cs.pub.ro/​courses/​poo-ca-cd/laboratoare/​constructori-referinte|Singleton]] și [[https://​ocw.cs.pub.ro/​courses/​poo-ca-cd/laboratoare/visitor|Visitor]]. //​Singleton//​ este un pattern creațional,​ simplu, a cărui folosire este controversată (vedeți în [[:​poo-ca-cd:​laboratoare:​static-final#​singleton_pattern|laborator]] explicația cu anti-pattern). //Visitor// este un pattern comportamental,​ și după cum ați observat oferă avantaje în anumite situații, în timp ce pentru altele nu este potrivit. Pattern-urile comportamentale modelează interacțiunile dintre clasele și componentele unei aplicații, fiind folosite în cazurile în care vrem sa facem un design mai clar și ușor de adaptat și extins.
  
  
Line 187: Line 187:
   * implementează interfața Observator   * implementează interfața Observator
  
-Aceasta schemă se poate extinde, în funcție de aplicație, observatorii pot ține referințe catre subiect sau putem adauga clase speciale pentru reprezentarea evenimentelor,​ notificarilor. Un alt exemplu îl puteți găsi [[http://​www.research.ibm.com/​designpatterns/​example.htm |aici]].+Aceasta schemă se poate extinde, în funcție de aplicație, observatorii pot ține referințe catre subiect sau putem adauga clase speciale pentru reprezentarea evenimentelor,​ notificarilor.
  
  
 === Implementare === === Implementare ===
  
-Tookit-urile GUI, cum este și [[http://​en.wikipedia.org/​wiki/​Swing_%28Java%29|Swing]] folosesc acest design pattern, de exemplu apăsarea unui buton generează un eveniment ce poate fi transmis mai multor //​listeners//​ înregistrați acestuia ​([[http://​www.programcreek.com/​2009/​01/​the-steps-involved-in-building-a-swing-gui-application/​|exemplu]]).+Tookit-urile GUI, cum este și [[http://​en.wikipedia.org/​wiki/​Swing_%28Java%29|Swing]] folosesc acest design pattern, de exemplu apăsarea unui buton generează un eveniment ce poate fi transmis mai multor //​listeners//​ înregistrați acestuia.
  
 API-ul Java oferă clasele [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​Observer.html |Observer]] și [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​Observable.html |Observable]] care pot fi subclasate pentru a implementa propriile tipuri de obiecte ce trebuie monitorizate și observatorii acestora. API-ul Java oferă clasele [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​Observer.html |Observer]] și [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​util/​Observable.html |Observable]] care pot fi subclasate pentru a implementa propriile tipuri de obiecte ce trebuie monitorizate și observatorii acestora.
Line 616: Line 616:
  
  
-=== Exerciții ==== +==== Exerciții ==== 
-Laboratorul trebuie rezolvat pe platforma LambdaCheckerfiind găsit [[https://beta.lambdachecker.io/contest/20 | aici]].+<note important>​ 
 +Pentru a încărca soluțiava trebui să accesați link-ul ​https://code.devmind.ro/login, să intrați pe tab-ul Contests, unde veți găsi laboratorul grupei voastre. 
 +</​note>​
  
 <note important>​ <note important>​
-În cadrul acestui laborator, exercițiile valorează în total 20p. Pentru primirea punctajului maxim pe acest laborator, trebuie să acumulați 10p din rezolvarea exercițiilor,​ orice depășește 10p fiind contorizat ca și bonus.+În cadrul acestui laborator, exercițiile valorează în total 18p. Pentru primirea punctajului maxim pe acest laborator, trebuie să acumulați 10p din rezolvarea exercițiilor,​ orice depășește 10p fiind contorizat ca și bonus.
 </​note>​ </​note>​
  
  
-** [[https://​beta.lambdachecker.io/​problem/​43/​20| ​Task 1]] - Observer, Strategy, Factory (10p) **+**Task 1 - Observer, Strategy, Factory (8p) **
  
-**Part 1. (6p) - Observer** +**Part 1. (4p) - Strategy, Factory ​**
-DataRepository este obiectul nostru observabil in scenariul de fata. O instanta de DataRepository poate primi date, prezentate sub forma unui SensorData pe care acesta le stocheaza intern.+
  
-Creati doua claseConsoleLogger si ServerCommunicationControllercare vor fi Observeri ​pentru ​DataRepository. In momentul in care metoda "​addData"​ dintr-o instanta de DataRepository se apeleaza, comportamentul celor doi observeri va fi urmatorul: +În cadrul acestui exercițiudorim să implementăm un magazince are disponibile mai multe modalități de plată ​pentru ​clienții săi:
-  * ConsoleLogger va afisa urmatorul mesaj: "New server data: " + new_data.toString() +
-  * ServerCommunicationController va afisa urmatorul mesaj: "​Generated server message: " + new_server_message.toString()  +
-unde new_data este instanta de SensorData nou introdusa, iar new_server_message este o instanta de ServerMessage construita pe baza instantei de SensorData nou adaugata.+
  
-Pentru Id-ul din ServerMessage,​ folositi Id-ul din Utils. +   * folosind un voucher 
-Atasati cate o instanta din fiecare observator la instanta de DataRepository.+  *  IBAN-ul 
 +  ​* ​ un card pe care îl posedă
  
-  * Pentru a avea deja mecanismul ​de notificare vom folosi ​interfața ​[[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​util/​Observer.html|Observer]] și clasa [[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​util/​Observable.html|Observable]] din java.util. Dacă doriți și aveți timp puteți ​să vă implementați ​propriile interfețe Oberver-Observable. +Cele 3 modalități ​de plată sunt reprezentate de clase ce implementează ​interfața ​**PaymentStrategy**. 
-   ​Observer-Observable ​din java.util sunt deprecated din java 9 pentru că sunt prea simpleînsă asta le face potrivite pentru acest laborator. Într-aplicație reală puteți folosi alte api-uri care sunt mult mai complexe și oferă foarte multe tipuri ​de obiecte și mecanisme (termenul folosit este //reactive programming//​). + 
-  * Citiți în [[https://​github.com/​oop-pub/​laboratoare/​blob/​master/​design-patterns/​skel/​src/​README|README]] rolul fiecărui observator. +Trebuie ​să implementați: 
-  <note tip>​Vedeți metodele din [[https://​docs.oracle.com/​en/​java/​javase/​11/​docs/​api/​java.base/​java/​util/​Observable.html|Observable]] pentru notificarea observatorilorschimbarea stării obiectului observat și adăugarea de observatori.</​note>​ + 
-   +  * metoda **pay** din cadrul fiecărei metode de plată
-**Part 2. (4p) - StrategyFactory** +  * metoda **getPaymentMethod**ce primește un client ca parametru și instanțiază o tranzacție folosind o anumită metodă de plată, aleasă random
-Fiecare instanta de tip SensorData contine si numarul de pasi facuti la un anumit timestampVrem sa cream un alt observator ​care va calcula numarul total de pasi executati de aplicatie, stocati in instante de SensorData in interiorul lui DataRepository,​ folosind doua strategii de calcul.+ 
 + 
 +**Part 2. (4p) - Observer ** 
 + 
 +În acest context, **subscriber-ul/​observer-ul** este clasa Person. Această clasă implementează interfața **BalanceObserver**Clasa Shop, care este **subiectul/​publisher-ul** care trebuie să implementeze interfața **TransactionPublisher** ​va avea rolul de a **notifica** un client când o tranzacție este efectuată.
  
-Extindeti din interfata StepCountStrategy doua clase, care vor servi drept strategiile noastre+Trebuie să implementați
-  * BasicStepCountStrategy - calculeaza numarul total de pasi dintr-un DataRepository +  * metoda **update** din cadrul clasei **Person**, ce preia notificarea faptului că un client are în cont mai puțini Lei decât o anumită limită, specifică fiecărui client în parte, printr-un mesaj adecvat (”$nume$ $prenume$, ramai fara bani, saracule!”);​ 
-  * FilteredStepCountStrategy - calculeaza numarul total de pasi dintr-un DataRepositoryadaugand la total doar pasii care indeplinesc urmatoarele conditii: sunt pozitivi si nu sunt mai mari cu MAX_STEP_COUNT ​(valoare statica in Utilsegala cu 1000pasi decat numarul ​de pasi precedent.+  * metoda **payBy** din cadrul clasei Personce întoarce valoarea de adevăr a reușitei efectuării unei plăți ​(dacă e posibilefectuează plata), iar în caz negativ afisează și un mesaj adecvat (”$nume$ $prenume$, pleaca ​de aici, saracule!”);​ 
 +  * metoda **createTransaction** din cadrul clasei **Shop**, ce verifică dacă trebuie notificată persoana cu ajutorul metodei **update**, în urma unei tranzacții.
  
-In interiorul acestor clase de strategie se va stoca si instanta de DataRepository,​ pentru a calcula numarul total de pasi. 
  
-Creati un StepCountStrategyFactory care, in functie de un parametru de tip String, va intoarce fie un BasicStepCountStrategy,​ fie un FilteredStepCountStrategy. 
  
-Aceste strategii vor fi folosite intr-un alt observator, DataAggregator. Acesta primeste o strategie, iar la fiecare operatie de tip '​addData'​ va afisa urmatorul mesaj:  +**Task 2 Builder pattern (2p)**
-  ​"Basic strategy, total step count: " + total_steps,​ daca strategia este Basic +
-  ​"​Filtered strategy, total step count: " + total_steps,​ daca strategia este Filtered+
  
-Creati doua strategii pe baza celor doua String-uri primite la intrare, pe care le veti folosi pentru a instantia doi observatori de tip DataAggregator. Atasati cei doi observatori la instanta de DataRepository. 
  
-** [[https://​beta.lambdachecker.io/​problem/​44/​20 | Task 2]] - Builder pattern (2p)**+a) Examinați câmpurile din skeletul clasei ​**House** care includ câteva facilități obligatorii în construcția unei case, spre exemplu:
  
-a) Scrieți câmpuri în skeletul clasei House pentru câteva facilități obligatorii în construcția unei case, spre exemplu ​locația construcțieinumărul de etaje, încălzire, ​camere ​dar și unele opționale pe care le poate selecta sau nu clientul, cum ar fi electrocasnicepiscinăpanouri solaresecuritate ​etc.+   ​* ​locația construcției 
 +  *    ​numărul de etaje 
 +  *    ​camere 
 +  *   unele **opționale** pe care le poate selecta sau nu clientul, cum ar fi
 +    * electrocasnice 
 +    *  ​piscină 
 +    *  ​panouri solare 
 +    *  ​securitate
  
-Completați constructorul privat, metodele de get și metoda toString. 
  
 +Completați constructorul public și metoda toString.
  
-b) În clasa de builder, completați câmpurile, constructorul și metodele de adăugare +b) În clasa **HouseBuilder**, completați câmpurile, constructorul și metodele de adăugare a facilităților opționale.
-a facilităților opționale.+
  
-c) Finalizați metoda build și testați funcționalitatea într-o clasă Main creată de voi, +c) Finalizați metoda build și decomentați codul din Main pentru a putea testa corectitudinea ​funcționalității.
-acoperind cazuri în care se construiește o casa doar cu facilitați obligatorii și +
-altele adăugând și pe cele opționale.+
  
-** [[https://​beta.lambdachecker.io/​problem/​41/​20 | Task 3]] - Command pattern (8p)**+**Task 3 - Command pattern (8p)**
  
-Implementați folosind patternul Command un editor de diagrame foarte simplificat. ​[[https://​github.com/​oop-pub/​oop-labs/​tree/​master/​src/​lab10 | Scheletul de cod]] conține o parte din clase și câteva teste. ​+Implementați folosind patternul Command un editor de diagrame foarte simplificat. Scheletul de cod conține o parte din clase și câteva teste. ​
  
 Componentele principale ale programului:​ Componentele principale ale programului:​
Line 683: Line 686:
   * //Client// - entry-point-ul în program   * //Client// - entry-point-ul în program
  
-(4p) Implementați ​tipuri de comenzi, pentru următoarele acțiuni:+(4p) Implementați ​tipuri de comenzi, pentru următoarele acțiuni:
   * Draw rectangle - crează o DiagramComponent și o adaugă în DiagramCanvas   * Draw rectangle - crează o DiagramComponent și o adaugă în DiagramCanvas
   * Resize - modifică width și height al unei DiagramComponent pe baza unui procent dat   * Resize - modifică width și height al unei DiagramComponent pe baza unui procent dat
   * Change color - modifică culoarea unei DiagramComponent   * Change color - modifică culoarea unei DiagramComponent
   * Change text - modifică textul unei DiagramComponent   * Change text - modifică textul unei DiagramComponent
-  * Connect components - conectează o DiagramComponent la alta 
  
 Implementați pe Invoker metoda execute() care va executa comanda primită ca argument. Implementați pe Invoker metoda execute() care va executa comanda primită ca argument.
Line 698: Line 700:
 Comenzile implementează în afară de metodele interfeței și metoda [[https://​docs.oracle.com/​en/​java/​javase/​13/​docs/​api/​java.base/​java/​lang/​Object.html#​toString()|toString()]] pentru a afișa comanda. Recomandăm folosirea IDE-ului pentru a o genera. Comenzile implementează în afară de metodele interfeței și metoda [[https://​docs.oracle.com/​en/​java/​javase/​13/​docs/​api/​java.base/​java/​lang/​Object.html#​toString()|toString()]] pentru a afișa comanda. Recomandăm folosirea IDE-ului pentru a o genera.
  
-(6p) Implementați în comenzi și în Invoker mecanismul de undo/redo al comenzilor. Recomandăm în Invoker sa folosiți două structuri de date, una care să mențină comenzile efectuate, iar una pentru comenzile făcute undo. Metoda reset() de pe Invoker va avea ca scop resetarea tuturor membrilor acestuia.+(4p) Implementați în comenzi și în Invoker mecanismul de undo/redo al comenzilor. Recomandăm în Invoker sa folosiți două structuri de date, una care să mențină comenzile efectuate, iar una pentru comenzile făcute undo. Metoda reset() de pe Invoker va avea ca scop resetarea tuturor membrilor acestuia.
  
  
poo-ca-cd/laboratoare/design-patterns.1670840385.txt.gz · Last modified: 2022/12/12 12:19 by radu_bogdan.pavel
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0