User Tools

Site Tools


Problem constructing authldap
laboratoare:static-final
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
Next revision Both sides next revision
laboratoare:static-final [2019/10/19 21:03]
Adriana Draghici [Exerciții]
laboratoare:static-final [2019/10/20 14:51]
Radu Matei [Exerciții]
Line 1: Line 1:
  
-= Static și final =+= Static și final; Singleton Design Pattern ​=
  
 == Obiective == == Obiective ==
Line 6: Line 6:
 * Înțelegerea conceptului de static în contextul claselor și instanțelor * Înțelegerea conceptului de static în contextul claselor și instanțelor
 * Utilizarea keywords-urilor static și final din Java * Utilizarea keywords-urilor static și final din Java
 +* Folosirea design-pattern-ului Singleton
 +
 == Cuvântul-cheie "​final"​. Obiecte immutable == == Cuvântul-cheie "​final"​. Obiecte immutable ==
  
Line 223: Line 225:
  
 </​code>​ </​code>​
 +
 +
 +== Singleton Pattern ==
 +
 +Pattern-ul Singleton este utilizat pentru a restricționa numărul de instanțieri ale unei clase la un singur obiect, deci reprezintă o metodă de a folosi o singură instanță a unui obiect în aplicație.
 +
 +=== Utilizari ===
 +
 +Pattern-ul Singleton este util în următoarele cazuri:
 +* ca un subansamblu al altor pattern-uri:​
 + ** impreună cu pattern-urile Abstract Factory, Builder, Prototype etc. De exemplu, în aplicație dorim un singur obiect factory pentru a crea obiecte de un anumit tip.
 +* în locul variabilelor globale. Singleton este preferat variabilelor globale deoarece, printre altele, nu poluează namespace-ul global cu variabile care nu sunt necesare.
 +
 +Singleton este utilizat des în situații în care avem obiecte care trebuie accesate din mai multe locuri ale aplicației:​
 +* obiecte de tip logger
 +* obiecte care reprezintă resurse partajate (conexiuni, sockets etc.)
 +* obiecte ce conțin configurații pentru aplicație
 +* pentru obiecte de tip //​Factory//​.
 +
 +Exemple din API-ul Java: [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​Runtime.html | java.lang.Runtime]],​ [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​awt/​Toolkit.html | java.awt.Toolkit]]
 +
 +Din punct de vedere al design-ului și testarii unei aplicații de multe ori se evită folosirea acestui pattern, în test-driven development fiind considerat un **//​anti-pattern//​**. A avea un obiect Singleton a carei referință o folosim peste tot prin aplicație introduce multe dependențe între clase și îngreunează testarea individuală a acestora. ​
 +
 +In general, codul care folosește stări globale este mai dificil de testat pentru că implică o cuplare mai strânsă a claselor, și împiedică izolarea unei componente și testarea ei individuală. Dacă o clasă testată folosește un obiect singleton, atunci trebuie testat și singleton-ul. Soluția este simularea //mock-up// a singleton-ului în teste. Încă o problemă a acestei cuplări mai strânse apare atunci când două teste depind unul de celălalt prin modificarea singleton-ului,​ deci trebuie impusă o anumită ordine a rulării testelor.
 +
 +<note tip>​Încercați să nu folosiți în exces metode statice și componente Singleton.</​note>​
 +
 +
 +=== Implementare ===
 +
 +Aplicarea pattern-ului Singleton constă în implementarea unei metode ce permite crearea unei noi instanțe a clasei dacă aceasta nu există, și întoarcerea unei referințe către aceasta dacă există deja. În Java, pentru a asigura o singură instanțiere a clasei, constructorul trebuie să fie //​private//,​ iar instanța să fie oferită printr-o metodă statică, publică.
 +
 +În cazul unei implementări Singleton, clasa respectivă va fi instanțiată **lazy** (//lazy instantiation//​),​ utilizând memoria doar în momentul în care acest lucru este necesar deoarece instanța se creează atunci când se apelează ''​getInstance()'',​ acest lucru putând fi un avantaj în unele cazuri, față de clasele non-singleton,​ pentru care se face //eager instantiation//,​ deci se alocă memorie încă de la început, chiar dacă instanța nu va fi folosită (mai multe detalii și exemplu în [[http://​www.javaworld.com/​article/​2077568/​learn-java/​java-tip-67--lazy-instantiation.html |acest articol]])
 +
 +<​imgcaption image_singleton|Diagrama de clase pentru Singleton>​{{ .:​design-patterns:​singletonclassdiagram.png |}}</​imgcaption>​
 +
 +
 +Respectând cerințele pentru un singleton enunțate mai sus, în Java, putem implementa o componentă de acest tip în mai multe feluri, inclusiv folosind ''​enum''​-uri în loc de clase. Atunci când îl implementâm trebuie avut în vedere contextul în care îl folosim, astfel încât să alegem o soluție care să funcționeze corect în toate situațiile ce pot apărea în aplicație (unele implementări au probleme atunci când sunt accesate din mai multe thread-uri sau când trebuie serializate).
 +
 +<code java>
 + ​public class Singleton {
 +
 +   ​private static Singleton instance = null;
 +   
 +   ​private Singleton() {}
 +   
 +   ​public static Singleton getInstance() {
 +      if(instance == null) {
 +          instance = new Singleton();​
 +      }
 +      return instance; ​     ​
 +   }
 +   ...
 + }
 +</​code>​
 +
 +  * Instanța ''​instance''​ este //private//
 +  * Constructorul este privat ca sa nu poata fi apelat decat din clasa respectivă
 +  * Instanța este inițial nulă
 +  * Instanța este creată la prima rulare a //​getInstance()//​
 +
 +//De ce Singleton și nu clase cu membri statici?//
 +
 +O clasă de tip Singleton poate fi extinsă, iar metodele ei suprascrise,​ însă într-o clasă cu metode statice acestea nu pot fi suprascrise (//​overriden//​) (o discuție pe aceasta temă puteți gasi [[http://​geekexplains.blogspot.ro/​2008/​06/​can-you-override-static-methods-in-java.html | aici]], și o comparatie între static și dynamic binding [[http://​geekexplains.blogspot.ro/​2008/​06/​dynamic-binding-vs-static-binding-in.html | aici]]).
  
  
Line 229: Line 295:
     * o constantă MAGIC_NUMBER având orice valoare doriți ​     * o constantă MAGIC_NUMBER având orice valoare doriți ​
     * un String constant MAGIC_STRING,​ lung de minim 20 de caractere, generat random     * un String constant MAGIC_STRING,​ lung de minim 20 de caractere, generat random
-    * un constructor care primește: un String numit ''​firstName'',​ un String numit ''​lastName''​ și un int numit ''​age'' ​+    * un constructor care primește: un String numit ''​name''​
     * o metodă ''​getPassword()''​ care va returna parola ​     * o metodă ''​getPassword()''​ care va returna parola ​
-      * parola se construiește concatenand următoarele șiruri: ​ +      * parola se construiește concatenand următoarele șiruri:
-        * șirul format din ultimele ''​(age % 3)''​ litere din firstName+
         * un șir random de lungime MAGIC_NUMBER,​ generat cu ''​RandomStringGenerator''​ și cu un alfabet obținut din 10 caractere obținute random din MAGIC_STRING         * un șir random de lungime MAGIC_NUMBER,​ generat cu ''​RandomStringGenerator''​ și cu un alfabet obținut din 10 caractere obținute random din MAGIC_STRING
-        * și șirul format prin conversia la String a numărului (age + lungimea ​lui lastName).+        * și șirul format prin conversia la String a lungimii ​lui name + un numar intreg generat random din intervalul [0,100]
     * Pentru subșiruri și alte metode utile consultați documentația clasei [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​String.html | String]]     * Pentru subșiruri și alte metode utile consultați documentația clasei [[http://​docs.oracle.com/​javase/​8/​docs/​api/​java/​lang/​String.html | String]]
-  - (**3p**) Modificati implementarea clasei PasswordMaker astfel incat +  - (**3p**) Modificati implementarea clasei PasswordMaker astfel incat sa respecte conceptul de **Singleton pattern** (sa permita instantierea unei singur obiect) 
-    * Sa respecte conceptul de Singleton pattern (sa permita instantierea unei singur obiect) +        * Pornind de la exemplul de Singleton ​din textul laboratorului implementati o versiune care urmeaza principiul ​de Eager Initialization (singura instanta a clasei este creata la pornirea aplicatiei, indiferent daca este necesar sau nu) 
-        * Implementati ​Singleton ​pattern folosind conceptul ​de Eager Initialization (singura instanta a clasei este creata la pornirea aplicatiei, indiferent daca este necesar sau nu) +        * Implementati o versiune ​de Singleton in care variabila ''​instance'' ​este initializata intr-un bloc static 
-        * Modificati implementarea anterioara urmand conceptul ​de Lazy Initialization (singura instanta a clasei este creata doar atunci cand este nevoie de ea+        * Adaugati un contor care sa numere de cate ori a fost accesata metoda ''​getInstance()''​. E nevoie ​ca acest contor sa fie static? 
-  - (**4p**) Să se implementeze o clasă ''​MyImmutableArray''​ care sa contina:+        * //​Tema ​de gandire:// Ce se va intampla daca folosim conceptul de Singleton pattern intr-un program paralelizat,​ care ruleaza pe mai multe linii de executie (thread-uri). Ce probleme ar putea sa apara? 
 +  - (**3p**) Să se implementeze o clasă ''​MyImmutableArray''​ care sa contina:
     * un field de ''​ArrayList<​Integer>​ immutableArray;''​ neinitializat in prima faza     * un field de ''​ArrayList<​Integer>​ immutableArray;''​ neinitializat in prima faza
     * un constructor care primeste un ArrayList<​Integer>​ si copiaza toate elementele din acel array in ''​immutableArray''​     * un constructor care primeste un ArrayList<​Integer>​ si copiaza toate elementele din acel array in ''​immutableArray''​
laboratoare/static-final.txt · Last modified: 2019/10/23 12:19 by Radu Matei