This shows you the differences between two versions of the page.
poo-ca-cd:laboratoare:design-patterns [2023/12/08 19:31] aconstantinescu0606 [Summary] |
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 LambdaChecker, fiind găsit [[https://beta.lambdachecker.io/contest/20 | aici]]. | + | <note important> |
+ | Pentru a încărca soluția, va 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> | ||
Line 624: | Line 626: | ||
- | ** [[https://beta.lambdachecker.io/problem/43/20| Task 1]] - Observer, Strategy, Factory (10p) ** | + | **Task 1 - Observer, Strategy, Factory (8p) ** |
- | **Part 1. (4p) - Strategy, Factory** | + | **Part 1. (4p) - Strategy, Factory ** |
- | În cadrul acestui exercițiu, dorim să implementăm un magazin, ce are disponibile mai multe modalități de plată pentru clienții săi(folosind un voucher, IBAN-ul sau direct un card pe care îl posedă). | + | În cadrul acestui exercițiu, dorim să implementăm un magazin, ce are disponibile mai multe modalități de plată pentru clienții săi: |
- | Cele 3 modalități de plată sunt reprezentate de clase ce implementează interfața PaymentStrategy. | + | * folosind un voucher |
+ | * IBAN-ul | ||
+ | * un card pe care îl posedă | ||
- | Trebuie sa implementați: | + | Cele 3 modalități de plată sunt reprezentate de clase ce implementează interfața **PaymentStrategy**. |
- | * Metoda pay din cadrul fiecărei metode de plată. | + | Trebuie să implementați: |
- | * Metoda getPaymentMethod, ce primește un client ca parametru și instanțiază o tranzacție folosind o anumită metodă de plată, aleasă random. | + | |
- | <note tip> **HINT:** getPaymentMethod va fi folosită in cadrul unei metode va trebui implementată în cadrul părții de Observer </note> | + | |
- | | + | * metoda **pay** din cadrul fiecărei metode de plată. |
- | **Part 2. (4p) - Observer** | + | * metoda **getPaymentMethod**, ce primește un client ca parametru și instanțiază o tranzacție folosind o anumită metodă de plată, aleasă random. |
- | În acest context, subiectul(cel care este Observable) este clasa Person. Această clasă implementează interfața BalanceObserver (care este Observer-ul). Clasa Shop (ce joacă rol de Publisher, întrucât implementeaza interfața Transactionpublisher) va avea rolul de a notifica un client cand o tranzacție este efectuată. | + | |
+ | **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ă. | ||
Trebuie să implementați: | Trebuie să implementați: | ||
- | *Motoda update din cadrul clasei Person, ce notifică faptul ca un client are mai puțini Lei in cont decât o anumită limită, specifică fiecărui client în parte, printr-un mesaj adecvat( nume prenume, ramai fara bani, saracule!). | + | * 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!”); |
- | *Metoda payBy din cadrul clasei Person, ce întoarce valoarea de adevăr a reușitei efectuării unei plăți(și o efectuează dacă e posibil), iar în caz negative și un mesaj adecvat( nume prenume, pleaca de aici, saracule!). | + | * metoda **payBy** din cadrul clasei Person, ce întoarce valoarea de adevăr a reușitei efectuării unei plăți (dacă e posibil, efectuează plata), iar în caz negativ afisează și un mesaj adecvat (”$nume$ $prenume$, pleaca de aici, saracule!”); |
- | *Metoda createTransaction din cadrul clasei Shop, ce verifică daca trebuie notificată persoana cu ajutorul metodei update, în urma unei tranzacții(HINT trebuie folosită și metoda payBy). | + | * metoda **createTransaction** din cadrul clasei **Shop**, ce verifică dacă trebuie notificată persoana cu ajutorul metodei **update**, în urma unei tranzacții. |
+ | |||
+ | **Task 2 - Builder pattern (2p)** | ||
- | ** [[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ției, numărul de etaje, încălzire, camere dar și unele opționale pe care le poate selecta sau nu clientul, cum ar fi electrocasnice, piscină, panouri solare, securitate 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 674: | Line 686: | ||
* //Client// - entry-point-ul în program | * //Client// - entry-point-ul în program | ||
- | (4p) Implementați 5 tipuri de comenzi, pentru următoarele acțiuni: | + | (4p) Implementați 4 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 689: | 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. |