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

Next revision
Previous revision
Next revision Both sides next revision
laboratoare:static-final [2019/10/19 20:58]
Adriana Draghici created
laboratoare:static-final [2019/10/20 14:45]
Radu Matei [Exerciții]
Line 1: Line 1:
  
-= Static și final =+= Static și final; Singleton Design Pattern ​=
  
 == Obiective == == Obiective ==
 +
 +* Înțelegerea conceptului de static în contextul claselor și instanțelor
 +* 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 221: 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 297:
     * 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 ''​firstName'',​ un String numit ''​lastName''​ și un int numit ''​age'' ​
     * 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         * ș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 numărului (age + lungimea lui lastName).
     * 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? 
 +        * //​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:   - (**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
laboratoare/static-final.txt · Last modified: 2019/10/23 12:19 by Radu Matei