User Tools

Site Tools


Problem constructing authldap
laboratoare:design-patterns2
Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
laboratoare:design-patterns2 [2017/12/12 17:43]
theodor.stoican [Exerciții]
laboratoare:design-patterns2 [2020/01/05 19:42] (current)
Adriana Draghici [Exerciții] fixed typo
Line 1: Line 1:
-= Design patterns - Command, Strategy ​= += Design patterns - Command =
- +
-* Responsabil:​ [[theo.stoican@gmail.com|Theodor Stoican]] +
-* Data ultimei modificări:​ 12.12.2017 +
  
 == Obiective == == Obiective ==
  
-Scopul acestui laborator este familiarizarea cu folosirea ​unor pattern-uri des întâlnite în design-ul atât al aplicațiilor,​ cât și al API-urilor - //Command// și //Strategy//.+Scopul acestui laborator este familiarizarea cu folosirea ​design ​pattern-ului comportamental ​//​Command//​.
  
  
 == Introducere == == Introducere ==
  
-Design ​pattern-urile reprezintă soluții generale ​și reutilizabile ale unei probleme comune în design-ul software. Un design pattern este o descriere ​soluției sau un template ​ce poate fi aplicat pentru rezolvarea problemeinu o bucata de cod ce poate fi aplicata directÎn general ​pattern-urile orientate pe obiect arată relațiile și interacțiunile ​dintre ​clase sau obiectefără a specifica însă forma finală a claselor sau a obiectelor implicate.+În laboratoarele precedent am prezentat ​pattern-uri ce vă ajută în realizarea unei arhitecturi mai decuplate, modulare ​și extensibile ​aplicațiilor: 
 +  * pattern-uri creaționale ​ce decuplează logica creării obiectelor: [[.static-final#​singleton-pattern|Singleton]][[.design-patterns#​factory|Factory]] 
 +  * pattern-uri comportamentale ce decuplează comunicarea ​dintre ​componente: [[.visitor#​visitor|Visitor]][[.design-patterns#​observer-pattern|Observer]],​ [[design-patterns#​strategy-pattern|Strategy]]
  
-Se consideră că există aproximativ 2000 de design patterns [[http://ptgmedia.pearsoncmg.com/images/9780321711922/​samplepages/​0321711920.pdf|[2]]]iar principalul mod de a le clasifica este următorul: +În acest laborator vom //Command//, un pattern comportamental care decuplează obiectele care execută anumite acțiuni de obiectele care le invocă.
- * **"​Gang of Four" patterns** +
- * Concurrency patterns +
- * Architectural patterns ​ - sunt folosite la un nivel mai inalt decat design patterns, stabilesc nivele și componente ale sistemelor/​aplicațiilor,​ interacțiuni ​între acestea (e.g. Model View Controller şi derivatele sale). Acestea descriu structura întregului sistem, iar multe framework-uri vin cu ele deja încoporate,​ sau faciliteaza aplicarea lor (e.g. Java Spring). ​ În cadrul laboratoarelor nu ne vom lega de acestea+
  
-O carte de referință pentru design patterns este "Design ​Patterns: Elements of Reusable Object-Oriented Software"​ [1], denumită și "Gang of Four" (GoF). Aceasta definește 23 de design patterns, foarte cunoscute și utilizate în prezent. Aplicațiile pot încorpora mai multe pattern-uri pentru a reprezenta legături dintre diverse componente (clase, module). +Design pattern-ul //​Command// ​incapsulează un apel cu tot cu parametri într-o clasă cu interfată generică. Acesta este //​Behavioral//​ pentru ​că modifică interacțiunea dintre componente, mai exact felul în care se efectuează apelurile. ​  
-În afară de GoF, și alți autori au adus în discuție pattern-uri orientate în special pentru aplicațiile enterprise și cele distribuite. +   
- + Acest pattern este recomandat în următoarele cazuri: ​  
-Pattern-urile GoF sunt clasificate în felul următor: + * pentru a ușura crearea de structuri de delegare, de callback, de apelare ​intarziată  
-* **Creational Patterns** - definesc mecanisme de creare a obiectelor + * pentru a reține lista de comenzi efectuate asupra obiectelor  
-   * Singleton, Factory etc. +     ​* accounting  
-* **Structural Patterns** - definesc relații între entități +     ​* liste de Undo, Rollback pentru tranzacții-suport pentru operații reversibile (//undoable operations//​)  
-   * Decorator, Adapter, Facade, Composite, Proxy etc. +   
-* **Behavioural Patterns** - definesc comunicarea între entități + ​Exemple de utilizare:  
-   * Visitor, Observer, Command, Mediator, Strategy etc. + * sisteme de logging, accounting pentru tranzacții  
- + * sisteme de undo (ex. editare imagini)  
-<note important>​ + * mecanism ordonat pentru delegare, apel întârziat,​ callback  
-Design pattern-urile nu trebuie privite drept niște rețete care pot fi aplicate direct pentru a rezolva o problemă din design-ul aplicației,​ pentru că de multe ori pot complica inutil arhitectura. Trebuie întâi înțeles dacă este cazul să fie aplicat un anumit pattern, si de-abia apoi adaptat pentru situația respectivă. Este foarte probabil chiar să folosiți un pattern (sau o abordare foarte similară acestuia) fără să vă dați seama sau să îl numiți explicit. Ce e important de reținut după studierea acestor pattern-uri este un mod de a aborda o problemă de design. +   
-</note> +== Funcționare și necesitate ==  
- +În esentă, Command pattern (așa cum v-ați obișnuit și lucrând ​cu celelate Pattern-uri pe larg cunoscute) presupune ​încapsularea ​unei informații ​referitoare la acțiuni/comenzi folosind un wrapper pentru a "ține minte această informație" ​și pentru a o folosi ulterior. Astfel, un astfel de wrapper va deține informații ​referitoare la tipul acțiunii ​respective (în general un asemenea wrapper va expunde o metodă ​execute(), care va descrie comportamentul pentru ​acțiunea respectivă).  
- +   
-În laboratorul [[.:​visitor|Visitor Pattern]] au fost introduse design pattern-urile și aplicabilitatea Visitor-ului. Acesta 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 afară de acest tip de pattern-uri,​ mai se folosesc și cele //​structural//​ și //​creational//,​ prezentate în clasificarea următoare:​ +Mai mult încăcând vorbim de Command Pattern, ​în terminologia OOP o să întâlniți ​deseori ​și noțiunea ​de //Invoker//. Invoker-ul este un middleware ca funcționalitate ​care realizează ​managementul comenzilor. Practic, un //Client//, care vrea să facă anumite ​acțiune, va instanția ​clase care implementează ​interfață //Command//. Ar fi incomod ca, în cazul în care aceste ​instanțieri ​de comenzi provin din mai multe locuri, acest management de comenzi ​să se facă local, ​în fiecare parte (din rațiuni ​de economie, nu vrem să duplicăm ​cod). Invoker-ul apare ca o necesitate de a centraliza acest proces ​și de a realiza intern management-ul comenzilor (le ține într-o listăține cont de eventuale ​dependințe între ​ele, totul în funcție ​de context).  
- +   
-* //​Creational Patterns// - mecanisme de creare a obiectelor +Un client (generic spus, un loc de unde se lansează ​comenzi) ​instanțiază ​comenzile ​și le pasează ​Invoker-ului. Din acest motiv Invoker-ul este un middleware ​între ​client ​și receiver, ​fiindcă ​acesta va apela execute pe fiecare Command, ​în funcție ​de logica ​să internă
-   * **Singleton**,​ **Factory** etc +
-* //​Structural Patterns// - definesc relații între entități +
-   * Decorator, Adapter, Facade, Composite, Proxy etc. +
-* //​Behavioural Patterns// - definesc comunicarea între entități +
-  * Visitor,** Observer**, **Command**, Mediator, Strategy etc. +
- +
-== Command Pattern == +
- +
-Design pattern-ul ​//Command// încapsulează un apel cu tot cu parametri într-o clasă cu interfață generică. Acesta este //​Behavioral//​ pentru ​ca modifică interacțiunea dintre componente, mai exact felul în care se efectuează apelurile.  +
- +
-Acest pattern este recomandat în următoarele cazuri:  +
-* pentru a ușura crearea de structuri de delegare, de callback, de apelare ​întârziată +
-* pentru a reține lista de comenzi efectuate asupra obiectelor +
-    * accounting +
-    * liste de Undo, Rollback pentru tranzacții - suport pentru operații reversibile (//undoable operations//​) +
- +
-Exemple de utilizare:​ +
-* sisteme de logging, accounting pentru tranzacții +
-* sisteme de undo (ex. editare imagini) +
-* mecanism ordonat pentru delegare, apel întârziat,​ callback +
- +
-=== Functionare si necesitate ​=== +
-In esenta, Command pattern (asa cum v-ati obisnuit si lucrand ​cu celelate Pattern-uri pe larg cunoscute) presupune ​incapsularea ​unei informatii ​referitoare la actiuni/comenzi folosind un wrapper pentru a "tine minte aceasta informatie" ​si pentru a o folosi ulterior. Astfel, un astfel de wrapper va detine informatii ​referitoare la tipul actiunii ​respective (in general un asemenea wrapper va expunde o metoda ​execute(), care va descrie comportamentul pentru ​actiunea respectiva). +
- +
-Mai mult incacand vorbim de Command Pattern, ​in terminologia OOP o sa intalniti ​deseori ​si notiunea ​de Invoker. Invoker-ul este un middleware ca functionalitate ​care realizeaza ​managementul comenzilor. Practic, un Client, care vrea sa faca anumite ​actiune, va instantia ​clase care implementeaza ​interfata ​Command. Ar fi incomod ca, in cazul in care aceste ​instantieri ​de comenzi provin din mai multe locuri, acest management de comenzi ​sa se face local, ​in fiecare parte (din ratiuni ​de economie, nu vrem sa duplicam ​cod). Invoker-ul apare ca o necesitate de a centraliza acest proces ​si de a realiza intern management-ul comenzilor (le tine intr-o listatine cont de eventuale ​dependinte intre ele, totul in functie ​de context). +
- +
-Si nu in cele din urma, un client (generic spus, un loc de unde se lanseaza ​comenzi) ​instantiaza ​comenzile ​si le paseaza ​Invoker-ului. Din acest motiv Invoker-ul este un middleware ​intre client ​si receiver, ​fiindca ​acesta va apela execute pe fiecare Command, ​in functie ​de logica ​sa interna.+
  
 //​__Recomandare__//:​ La Referinte aveti un link catre un post pe StackOverflow,​ pentru a intelege mai bine de ce aveti nevoie de Pattern-ul Command si de ce nu lansati comenzi pur si simplu. //​__Recomandare__//:​ La Referinte aveti un link catre un post pe StackOverflow,​ pentru a intelege mai bine de ce aveti nevoie de Pattern-ul Command si de ce nu lansati comenzi pur si simplu.
  
- +== Structura ==
-=== Structura ​===+
  
 Ideea principală este de a crea un obiect de tip //Command// care va reține parametrii pentru comandă. Comandantul reține o referință la comandă și nu la componenta comandată. Comanda propriu-zisă este anunțată obiectului //Command// (de către comandant) prin execuția unei metode specificate asupra lui. Obiectul //Command// este apoi responsabil de trimiterea (//​dispatch//​) comenzii către obiectele care o îndeplinesc (//​comandați//​). ​ Ideea principală este de a crea un obiect de tip //Command// care va reține parametrii pentru comandă. Comandantul reține o referință la comandă și nu la componenta comandată. Comanda propriu-zisă este anunțată obiectului //Command// (de către comandant) prin execuția unei metode specificate asupra lui. Obiectul //Command// este apoi responsabil de trimiterea (//​dispatch//​) comenzii către obiectele care o îndeplinesc (//​comandați//​). ​
Line 93: Line 60:
 În diagrama din <imgref cmd_image>,​ comandantul este clasa //Invoker// care conține o referință la o instanță (command) a clasei (Command). //Invoker// va apela metoda abstractă ''​execute()''​ pentru a cere îndeplinirea comenzii. //​ConcreteCommand//​ reprezintă o implementare a interfeței //​Command//,​ iar în metoda ''​execute()''​ va apela metoda din //​Receiver//​ corespunzătoare acelei acțiuni/​comenzi. În diagrama din <imgref cmd_image>,​ comandantul este clasa //Invoker// care conține o referință la o instanță (command) a clasei (Command). //Invoker// va apela metoda abstractă ''​execute()''​ pentru a cere îndeplinirea comenzii. //​ConcreteCommand//​ reprezintă o implementare a interfeței //​Command//,​ iar în metoda ''​execute()''​ va apela metoda din //​Receiver//​ corespunzătoare acelei acțiuni/​comenzi.
   ​   ​
-=== Implementare ​===+=== Exemplu ​===
  
 Diagrama de secvență din <imgref cmd_flow_image>​ prezintă apelurile în cadrul unei aplicație de editare a imaginilor, ce este structurată folosind pattern-ul Command. În cadrul acesteia, Receiver-ul este //Image//, iar comenzile //​BlurCommand//​ și //​CropCommand//​ modifică starea acesteia. Structurând aplicația în felul acesta, este foarte ușor de implementat un mecanism de undo/redo, fiind suficient să menținem în Invoker o listă cu obiectele de tip //Command// aplicate imaginii. ​ Diagrama de secvență din <imgref cmd_flow_image>​ prezintă apelurile în cadrul unei aplicație de editare a imaginilor, ce este structurată folosind pattern-ul Command. În cadrul acesteia, Receiver-ul este //Image//, iar comenzile //​BlurCommand//​ și //​CropCommand//​ modifică starea acesteia. Structurând aplicația în felul acesta, este foarte ușor de implementat un mecanism de undo/redo, fiind suficient să menținem în Invoker o listă cu obiectele de tip //Command// aplicate imaginii. ​
Line 102: Line 69:
 <​imgcaption cmd_flow_image2|Diagrama de secvență pentru comenzile de aprindere/​stingere a switch-ului>​{{ .:​design-patterns:​command_switch_sequence.png | }}</​imgcaption>​ <​imgcaption cmd_flow_image2|Diagrama de secvență pentru comenzile de aprindere/​stingere a switch-ului>​{{ .:​design-patterns:​command_switch_sequence.png | }}</​imgcaption>​
  
-== Strategy Pattern == 
  
-Design pattern-ul //​Strategy//​ încapsulează algoritmii în clase ce oferă o anumită interfață de folosire, și pot fi selecționați la runtime. Ca și Command, acest pattern este //​behavioral//​ pentru ca permite decuplarea unor clase ce oferă un anumit comportament și folosirea lor independentă în funcție de situația de la runtime.+== Exerciții ==
  
-Acest pattern este recomandat în cazul în care avem nevoie de un tip de algoritm (strategie) cu mai multe implementări posibile si dorim să alegem dinamic care algoritm îl folosim, fără a face sistemul prea strâns cuplat.+Implementați folosind patternul Command ​un editor de diagrame foarte simplificat. Scheletul ​de cod conține o parte din clase și câteva teste.
  
-**Exemple de utilizare**+Componentele principale ale programului
-sisteme ​de tip Layout Managers din API-urile pentru ​UI +  //​DiagramCanvas//​ - reprezintă o diagramă care conține obiecte ​de tip DiagramComponent 
-selectarea in mod dinamic la runtime a unor algoritmi de sortare, compresie, criptare etc.+  * //​DrawCommand// ​interfață ​pentru ​comenzile făcute asupra diagramei sau a componentelor acesteia 
 +  //Invoker// - primește comenzile și le execută 
 +  * //Client// - entry-point-ul în program
  
-**Structură**:​ +** Task 1 - Implementarea comenzilor ​(4p) **
-* trebuie să definiți o **interfață comună** pentru strategiile pe care le implementați ​(fie ca o <<​interface>>​ sau ca o clasa abstractă) +
-* implementați strategiile respectând interfața comună +
-* clasa care are nevoie să folosească strategiile **va ști doar despre interfața lor**, nu va fi legată de implementările concrete+
  
-Denumirile uzuale în exemplele acestui pattern sunt: //​Strategy//​ (pt interfață sau clasa abstractă)//​ConcreteStrategy// ​pentru ​implementare,​ //​Context//,​ clasa care folosește/execută strategiile.+Implementați 5 tipuri de comenzi, pentru ​următoarele acțiuni: 
 +  * Draw rectangle - crează o DiagramComponent ​și o adaugă în DiagramCanvas 
 +  * Resize - modifică width și height al unei DiagramComponent pe baza unui procent dat 
 +  * Change color - modifică culoarea unei DiagramComponent 
 +  * Change text - modifică textul unei DiagramComponent 
 +  * Connect components - conectează o DiagramComponent la alta
  
-//​__Recomandare__//:​ Urmariti link-ul de la referinte catre postul de pe Stack Overflow care descrie necesitatea pattern-ului Strategy. Pe langa motivul evident de incapsulare ​prelucrarilor/​algoritmilor (care reprezinta strategiile efective), se prefera o anumita abordare: la runtime se verifica mai multe conditii si se decide asupra strategieiConcretfolosind mecanismul de polimorfism dinamic, se foloseste o anumita instanta a tipului de strategie (//ex. Strategy str = new CustomStrategy//​),​ care se paseaza in toate locurile unde este nevoie de Strategy. Practic, in acest fel, utilizatorii unei anumite strategii vor deveni agnostici in raport cu strategia utilizata, ea fiind instantiata intr-un loc anterior si putand fi gata utilizata. Ganditi-va la browserele care trebuie sa detecteze daca device-ul este PC, smartphone, tableta sau altceva si in functie de acest lucru sa randeze in mod diferit. Fiecare randare poate fi implementata ca o strategie, iar instantierea strategiei se va face intr-un punct, fiind mai apoi pasata in toate locurile unde ar trebui sa se tina cont de aceasta strategie.+Comenzile primesc în __constructor__ referințcătre DiagramCanvas și alte argumente necesare lorDe exemplucomanda pentru schimbarea culorii ​trebuie sa primească și culoarea nouă și indexul componentei.
  
 +Pentru acest task nu este nevoie să implementați și metoda //undo()//, doar //​execute()//​.
  
 +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.
  
 +** Task 2 - Testarea comenzilor (2p) **
  
 +Scheletul conține în clasa ''​Test''​ metode pentru a testa comportamentul comenzilor. O parte sunt deja implementate,​ iar o parte trebuie implementate.
  
 +** Task 3 - Undo/redo (2p) **
  
 +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.
  
-== Exerciții ==+** Task 4 - Test undo/redo (2p) **
  
-Acest laborator și [[laboratoare:​design-patterns|cel precedent]] au ca temă comună a exercițiilor realizarea unui joc controlat din consolă. Jocul constă dintr-lume (aka hartă) în care se plimbă eroi de trei tipuri, colectează comori ​și se bat cu monștriiÎn acestă săptămână terminam jocul inceput in laboratorul precedent folosind pattern-urile studiate (//Strategy//, //​Command//​).+Scheletul conține în clasa Test o metodă pentru ​verificare simplă a corectitudinii implementării undo și redoCompletați metoda ​//testComplexUndoRedo// în care să faceți multiple undo-uri și redo-uri pentru diverse tipuri de comenzi.
  
-Detalii joc: 
-* //Harta// 
-   * reprezentată printr-o matrice. Fiecare element din matrice reprezintă o zonă care poate fi liberă, poate conține obstacole sau poate conține o comoară (în laboratorul următor poate conține și monștrii). 
-   * este menținută în clasa ''​GameState''​. 
-* //​Eroii// ​ 
-   * sunt reprezentați prin clase de tip ''​Hero''​ și sunt de trei tipuri: //Mage//, //​Warrior//,​ //Priest//. 
-   * puteți adăuga oricâți eroi doriți pe hartă (cât vă permite memoria :)) 
-   * într-o zonă pot fi mai mulți eroi 
-   * acțiunile pe care le pot face: 
-     * ''​move''​ - se mută într-o zonă învecinată 
-     * ''​attack''​ - ataca un monstru cand se afla pe aceeasi pozitie cu el 
-     * ''​collect''​ - eroul ia comoara găsită în zona în care se află 
-* Entry-point-ul în joc îl consitituie clasa ''​Main''​. 
-* **(5p)** Folosiți design pattern-ul //Command// pentru a implementa functionalitatea de undo si redo la comanda ''​move''​. 
-   * Momentan, aveti erori de compilare in clasele Main si GameState. Dupa ce veti implementa acest exercitiu, se vor rezolva, nu modificati in mod direct acolo. 
-   * Va trebui sa completati clasa ''​MoveCommand''​ care implementeaza interfata ''​Command''​. Urmariti //​TODO-urile//​ din aceasta clasa. ​ 
-   * //​__Hint__//:​ Pentru Undo, de exemplu, daca v-ati deplasat la dreapta, ar trebui sa va deplasati la stanga. Creati-va o metoda ajutatoare care trateaza astfel de cazuri. 
-   * Precum si clasa ''​CommandManager''​ care va tine evidenta comenzilor si ordinea lor.  
-   * //​__Hint__//:​ Amintiti-va de la cursul de Structuri de Date cum se implementeaza operatiile Redo si Undo. Folositi doua stive. 
-* **(5p)** Folosiți design pattern-ul //​Strategy//​ pentru a implementa logica de atac a unui monstru. 
-   * Pentru acest exercitiu va trebui sa implementati 2 strategii: **AttackStrategy** si **DefenseStrategy**. Ambele vor implementa Strategy si metodele aferente. Fiecare din aceste Strategy, va retine o referinta interna la un Hero. Abordarea este urmatoarea: 
-    * Exista 3 clase Hero, fiecare cu cate un DamageType aferent: Warrior - Blunt, Mage - Magic, Priest - Poison ​ 
-    * Fiecare monstru are un weakness (slabiciune la atacurile de tip Blunt, Magic sau Poison) 
-    * **AttackStrategy**:​ In metoda attack(), veti itera prin inventory-ul eroului si veti verifica daca exista un obiect Treasure care are DamageType-ul identic cu cel al eroului. Daca da, atunci damage-ul pe care il veti da unui obiect Monster este **3 x damage-ul treasure-ului**. Daca nu aveti un astfel de Treasure, atunci cautati un Treasure cu un DamageType identic cu cel al mob-ului (mobul poate fi vulnerabil la Magic, de ex.). Daca gasiti un astfel de Treasure, damage-ul pe care il veti imprima mob-ului este **2 x damage-ul treasure-ului**. Daca nu, veti scade din HP-ul mob-ului rezultatul apelului metodei getBaseDamage() asupra Hero-ului. 
-    * **DefenseStrategy**:​ In metoda attack(), veti itera prin inventory-ul eroului si veti verifica, la fel, daca exista un obiect Treasure care are DamageType-ul identic cu cel al eroului. Daca da, atunci veti da un boost de HP egal cu treasure.getBoostHp() + getBaseHpBoost() eroului (getBaseHpBoost este implementata in clasa Hero). Daca nu, veti da doar un boost egal cu ce va intoarce getBaseHpBoost(). Damage-ul imprimat mobului va fi, de asemenea, egal cu ce va intoarce getBaseDamage(). Adaugati log-uri in clasa DefenseStrategy,​ pentru a va asigura ca i se mareste viata eroului. 
-    * Urmariti si TODO-urile din cele doua clase 
-   * Implementati metoda //attack// din clasa **Hero** astfel incat, daca eroul are mai mult de 50HP, folositi strategia **AttackStrategy**. Altfel, folositi **DefenseStrategy**. Urmariti TODO-urile din cod. 
-* (**Bonus 2p**) Implementați coliziunile cu obstacolele de pe harta 
-  * Va trebui sa creati un nou obiect ''​Obstacle''​ precum si un ''​ObstacleObserver''​ 
-  * Cand eroul ajunge pe un obstacol se va printa un mesaj ''​Can'​t move there !''​ si se va apela automat undo pe ultima comanda de move pentru a reveni in pozitia anterioara coliziunii. Acest feature de wall collision va fi implementat in ''​ObstacleObserver''​ 
  
 +/*
  
 +TODO pt 2020 (acum nu am avut timp):
 +- builder pattern in textul labului
 +- un exercitiu care sa ia exemplul de cod pus la partea de teorie si sa il ruleze si sa ii aplice doar o mica modificare
 +
 +*/
  
 == Resurse == == Resurse ==
  
-* {{.:​design-patterns:​src.zip|Schelet}} +* {{ :​laboratoare:​design-patterns:​design-patterns-part2-skel.zip |Schelet}} 
-{{|Soluții}} +[[laboratoare:​old-exercises|Exerciții din alți ani]]
-* <​html><​a class="​media mediafile mf_pdf"​ href="/​poo/​laboratoare/​design-patterns2?​do=export_pdf">​PDF laborator</​a></​html>​+
  
 == Referințe == == Referințe ==
  
-* [[http://​www.codeproject.com/​Articles/​15207/​Design-Patterns-Command-Pattern |Descriere Command Pattern si exemplu pentru operatii undo/​redo]] +* [[https://​sourcemaking.com/​design_patterns/​command | Command ​design ​pattern]]
-* [[https://​sourcemaking.com/​design_patterns/​command | O resursa buna pentru a intelege cele mai des intalnite ​design ​patterns]]+
 * [[https://​stackoverflow.com/​questions/​32597736/​why-should-i-use-the-command-design-pattern-while-i-can-easily-call-required-met | De ce avem nevoie de Command Pattern? ]] * [[https://​stackoverflow.com/​questions/​32597736/​why-should-i-use-the-command-design-pattern-while-i-can-easily-call-required-met | De ce avem nevoie de Command Pattern? ]]
-* [[https://​stackoverflow.com/​questions/​1710809/​when-and-why-should-the-strategy-pattern-be-used | De ce avem nevoie de Strategy Pattern? ]]+
  
laboratoare/design-patterns2.1513093425.txt.gz · Last modified: 2017/12/12 17:43 by theodor.stoican