Differences

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

Link to this comparison view

poo:breviare:breviar-13 [2019/01/07 14:18]
carmen.odubasteanu [Decorator]
poo:breviare:breviar-13 [2026/01/12 08:32] (current)
george.tudor1906 [1. Fluxuri (Streams)]
Line 1: Line 1:
-====== Breviar laborator 13 ====== 
  
 +===== Breviar 13 =====
  
-===== 1. Design Patterns =====+==== 1. Fluxuri (Streams) ​====
  
 +=== 1.1 Introducere ===
  
-==== Decorator ====+Dennis Ritchie implementează în 1984 primul sistem I/O pe bază de stream în cadrul 
 +sistemului de operare Unix. Acest concept are la bază crearea unui canal de comunicație 
 +între două entități: **sursă** și **destinație**. Sursa scrie informații în canalul de 
 +comunicație,​ iar destinația poate să citească aceste date, canalul permițând trecerea 
 +fluxului de date într-o singură direcție.
  
 +**Clasificarea fluxurilor:​**
  
-De multe ori in cadrul unei aplicatii apare urmatorul scenariu. Aveti de implementat o anumita functionalitate care trebuie sa poate fi extinsa fara sa stiti in momentul proiectarii in ce mod va fi extinsa. +După direcția canalului ​de comunicație:​ 
-De exemplu lucrati la un joc de tipul shooter. Aveti o lista de arme pe care un user le poate achizitiona si utiliza ​pentru ​a-si impusca oponentii. La un moment dat observati ca incasarile din joc incep sa scada o data ce alternativele ​de pe piata ofera mai multe feature-uri ​pentru ​armele lor. Pentru a nu da faliment va trebui sa adaugati niste feature-uri noi armelor voastre, dar trebui sa tineti cont ca orice modificare de cod creste fragilitatea si sansa de aparitie a unor bug-uri care initial nu existau.  +  * fluxuri ​de intrare (pentru ​citirea datelor) 
-Rezolvarea este foarte simpla: O sa creati o clasa abstracta wrapper peste o instanta de arma. Daca de exemplu vreti ca toate armele voastra sa poata fi mortale dar silentioase,​ creati clasa WeaponSilencer ce implementeaza interfata de baza a armelor si are un obiect de tip arma intern. In metoda fire, in decorator, o sa setati eventual +  * fluxuri ​de ieșire (pentru ​scrierea datelor)
-sunetul jocului mai incet. +
-  +
-{{ :​poo:​breviare:​img1.jpg?​600 |}}+
  
-Un alt exemplu la indemana sunt fluxurile din java.+După tipul de date pe care le operează:​ 
 +  * fluxuri de octeți (transfer serial pe 8 biți) 
 +  * fluxuri de caractere (transfer serial pe 16 biți)
  
-''​1 ​// some long mad code , c i s declared +După acțiunea lor: 
-2 CipherOutputStream cos = new CipherOutputStream(new FileOutputStream( " f i l e " ) , c ) ; +  * fluxuri primare de citire/scriere a datelor 
-3 Pr intWr i ter pw = new Pr intWr i ter (new OutputStreamWriter ( cos ) ) ; +  * fluxuri pentru procesarea datelor
-4 pw. pr int ln ( "Stand and unfold your s e l f " ) ; +
-5 pw. close ( ) ;''​+
  
-La baza avem un flux de iesire care va scrie in fisierul "​file"​ niste octeti. CipherOutputStream este o clasa decorator si adauga peste fluxul ​de octeti proprietatea ca acesta este criptat. Deoarece aceasta clasa nu ofera suport de lucru decat pentru ​octeti avem nevoie ​de un alt decorator care sa ne permita sa adaugam text in fluxul ​de iesireDe aceea folosim clasa PrintWriter. Observati ca atat PrintWriterOutputStreamWriter cat si CipherOutputStream sunt doar niste decoratoare ​ele modificand intr-un anumit mod fluxul, totusi acest flux trebuie sa apara de undeva si de accea toata aceasta decorare trebuie sa aiba la baza un flux instantiat (FileOutputStream).+Datorită faptului că există două direcții ​de comunicare, există două tipuri mari de 
 +stream-uri ​pentru ​orice nod de comunicație:​ **input stream** și **output stream**. 
 +Tastatura ar fi un exemplu ​de input stream, iar monitorul un output stream. 
 +Sursa și destinația nu trebuie să fie neapărat periferice, ele pot fi și module soft.
  
- +=== 1.2 Fluxuri de octeți ===
  
-Mapand ​pe diagrama exemplul nostru, FileOutputStream ​joaca rolul de componenta concretaPrintWriterOutputStreamWriter si CipherOutputStream joaca rolul de decoratoare concrete+Programele folosesc fluxuri de octeți pentru a citi sau scrie date pe 8 biți (un octet). 
-AtentieDaca in tot lantul de decorari ​nu exista un decorator ​care sa aiba la baza componenta concreta constructia ​nu va functiona.+Fluxurile la nivel de octet utilizează două ierarhii având drept clase rădăcină:​ 
 +**InputStream** și **OutputStream**. 
 + 
 +Cele mai utilizate clase sunt **FileInputStream** și **FileOutputStream**. 
 + 
 +<code java> 
 +public class Copy { 
 +    private String inputoutput; 
 + 
 +    public Copy(String input, String output) { 
 +        this.input = input; 
 +        this.output = output; 
 +    } 
 + 
 +    public void copyFile() { 
 +        InputStream in = null; 
 +        OutputStream out = null; 
 +        try { 
 +            in = new FileInputStream(input);​ 
 +            out = new FileOutputStream(output); 
 +            while (in.available() > 0) 
 +                out.write(in.read());​ 
 +        } catch (FileNotFoundException e) { 
 +            e.printStackTrace();​ 
 +        } catch (IOException e) { 
 +            e.printStackTrace();​ 
 +        } finally { 
 +            try { 
 +                if (out != null) out.close();​ 
 +                if (in != null) in.close();​ 
 +            } catch (IOException e) { 
 +                e.printStackTrace();​ 
 +            } 
 +        } 
 +    } 
 +
 +</​code>​ 
 + 
 +<note warning>​ 
 +IMPORTANT! Fișierele text trebuie să se afle în folderul rădăcină al proiectului 
 +care conține clasele care prelucrează informația din aceste fișiere. 
 +</​note>​ 
 + 
 +=== 1.3 Fluxuri ​de caractere === 
 + 
 +Limbajul Java stochează valorile de tip caracter folosind convenții Unicode. 
 +Fluxurile de caractere I/O își translatează automat formatul intern de la setul 
 +de caractere locale. 
 + 
 +Toate clasele de fluxuri de caractere moștenesc clasele **Reader** și **Writer**. 
 +Pentru operațiile I/O cu fișiere: **FileReader** și **FileWriter**. 
 + 
 +<code java> 
 +public class Read { 
 +    private String input; 
 + 
 +    public Read(String input) { 
 +        this.input = input; 
 +    } 
 + 
 +    public void read() { 
 +        FileReader stream = null; 
 +        BufferedReader br = null; 
 +        try { 
 +            stream = new FileReader(input);​ 
 +            br = new BufferedReader(stream);​ 
 +            String line = br.readLine();​ 
 +            while (line != null) { 
 +                System.out.println(line);​ 
 +                line = br.readLine();​ 
 +            } 
 +        } catch (FileNotFoundException e) { 
 +            e.printStackTrace();​ 
 +        } catch (IOException e) { 
 +            e.printStackTrace();​ 
 +        } finally { 
 +            try { 
 +                if (stream != null) stream.close();​ 
 +                if (br != null) br.close();​ 
 +            } catch (IOException e) { 
 +                e.printStackTrace();​ 
 +            } 
 +        } 
 +    } 
 +
 +</​code>​ 
 + 
 +<​note>​ 
 +Observație:​ Obiectul BufferedReader creează un flux de intrare a caracterelor cu 
 +stocare temporară (și posibilitate de citire a caracterelor sub formă de linii) 
 +din fluxul de intrare a caracterelor primit ca parametru. 
 +</​note>​ 
 + 
 +=== 1.4 Fluxuri cu zone tampon (Buffer) === 
 + 
 +Pentru un flux I/O fără zone tamponfiecare cerere de citire sau scriere este 
 +administrată direct de sistemul de operare. Aceasta face ca programul să fie mai 
 +puțin eficientdeoarece fiecare cerere declanșează accesul la disc, activitate 
 +în rețea sau alte operații care consumă timp. 
 + 
 +Pentru a reduce timpul ​de procesare, platforma Java implementează fluxuri I/O cu 
 +zone tampon: 
 +  * Fluxurile de intrare cu zone tampon citesc datele dintr-o zonă de memorie cunoscută ca **buffer** 
 +  * API-ul de intrare este apelat numai când tamponul este gol 
 +  * Similar, fluxurile de ieșire scriu datele în zona de tampon și API-ul de ieșire este apelat când tamponul este plin 
 + 
 +Un program poate converti un flux fără zonă tampon într-un flux cu zonă tampon 
 +astfel: un obiect de tip flux fără zonă tampon este trecut ca argument unui 
 +constructor pentru o clasă de tip flux cu zonă tampon
 + 
 +=== 1.5 Fluxuri standard === 
 + 
 +Limbajul Java pune la dispoziția utilizatorului trei fluxuri standard pentru 
 +comunicare cu consola: 
 + 
 +| **Flux** | **Descriere** | **Referință** | 
 +| Standard Input | pentru citirea datelor | System.in (InputStream) | 
 +| Standard Output | pentru afișarea datelor | System.out (PrintWriter) | 
 +| Standard Error | pentru afișarea erorilor | System.err (PrintWriter) | 
 + 
 +<​note>​ 
 +Observație:​ Nu este necesară instanțierea acestor trei stream-uri, deoarece ele 
 +se deschid automat înaintea execuției aplicației. De asemenea, acestea nici nu 
 +se închid prin apelul metodei close(). 
 +</​note>​ 
 + 
 +**Exemplu cu InputStreamReader și BufferedReader:​** 
 + 
 +<code java> 
 +public class Suma { 
 +    int a, b; 
 + 
 +    public void read() { 
 +        InputStreamReader stream = null; 
 +        BufferedReader br = null; 
 +        try { 
 +            stream = new InputStreamReader(System.in);​ 
 +            br = new BufferedReader(stream);​ 
 +            String line = br.readLine();​ 
 +            a = Integer.parseInt(line);​ 
 +            line = br.readLine();​ 
 +            b = Integer.parseInt(line);​ 
 +        } catch (IOException e) { 
 +            e.printStackTrace();​ 
 +        } finally { 
 +            try { 
 +                if (stream != null) stream.close();​ 
 +                if (br != null) br.close();​ 
 +            } catch (IOException e) { 
 +                e.printStackTrace();​ 
 +            } 
 +        } 
 +    } 
 +
 +</​code>​ 
 + 
 +**Exemplu cu Scanner:​** 
 + 
 +<code java> 
 +public class Test { 
 +    public static void main(String args[]) throws Exception { 
 +        Scanner in = new Scanner(System.in);​ 
 +        int a, b; 
 +        a = in.nextInt();​ 
 +        b = in.nextInt();​ 
 +        int result = a + b; 
 +        System.out.println(a + " + " + b + " = " + result); 
 +        in.close();​ 
 +    } 
 +
 +</​code>​ 
 + 
 +==== 2. Funcționale ==== 
 + 
 +=== 2.1 Introducere === 
 + 
 +În paradigma funcțională,​ funcțiile sunt valori de ordinul 1 ce pot fi manipulate 
 +ca orice altă valoare. **Funcționalele** sunt funcții ​care manipulează alte funcții, 
 +primindu-le ca argumente sau returnându-le ca rezultat. 
 + 
 +=== 2.2 Lista funcționalelor === 
 + 
 +== foldl(function,​ init, list) == 
 + 
 +Returnează rezultatul aplicării funcției **function** pe rând asupra unui element 
 +din listă și a unui acumulator **init**. Ordinea folosirii elementelor din listă 
 +este de la **stânga la dreapta**. 
 + 
 +<​code>​ 
 +foldl(f(x, y) = x + y, 5, [0, 1, 2, 3]) 
 += f(f(f(f(5, 0), 1), 2), 3) 
 += f(f(f(5, 1), 2), 3) 
 += f(f(6, 2), 3) 
 += f(8, 3) 
 += 11 
 +</​code>​ 
 + 
 +== foldr(function,​ init, list) == 
 + 
 +Are un comportament similar cu foldl, însă ordinea folosirii elementelor din listă 
 +este de la **dreapta la stânga**. 
 + 
 +<​code>​ 
 +foldr(f(x, y) = y, 4, [0, 1, 2, 3]) 
 += f(0, f(1, f(2, f(3, 4)))) 
 += f(0, f(1, f(2, 4))) 
 += f(0, f(1, 4)) 
 += f(0, 4) 
 += 0 
 +</​code>​ 
 + 
 +== map(function,​ list) == 
 + 
 +Returnează lista rezultatelor aplicării unei funcții **f** asupra fiecărui element 
 +dintr-listă. 
 + 
 +<​code>​ 
 +map(f(x) = 2*x, [0, 1, 2, 3]) => [0, 2, 4, 6] 
 +</​code>​ 
 + 
 +== filter(predicat,​ list) == 
 + 
 +Returnează lista elementelor dintr-o listă care satisfac un predicat **p**. 
 +Un predicat este o funcție care are un rezultat de tip Boolean. 
 + 
 +<​code>​ 
 +filter(f(x) = x % 2 == 0, [0, 1, 2, 3]) => [0, 2] 
 +</​code>​ 
 + 
 +== reduce(function,​ list) == 
 + 
 +Aplică funcția pentru primele două elemente din listă, apoi pentru rezultatul 
 +obținut anterior și următorul element și tot așa. 
 + 
 +<​code>​ 
 +reduce(f(x, y) = x + y, [47, 11, 42, 13]) 
 += f(f(f(47, 11), 42), 13) 
 += f(f(58, 42), 13) 
 += f(100, 13) 
 += 113 
 +</​code>​ 
 + 
 +== all(predicat,​ list) == 
 + 
 +Primește un predicat și verifică dacă **toate** elementele din listă satisfac predicatul. 
 + 
 +<​code>​ 
 +all(f(x) = x > 0, [0, 1, 2, 3])   => False  (0 nu e > 0) 
 +all(f(x) = x >= 0, [0, 1, 2, 3]) => True 
 +</​code>​ 
 + 
 +== any(predicat,​ list) == 
 + 
 +Primește un predicat și verifică dacă există **cel puțin un element** în listă 
 +care satisface predicatul. 
 + 
 +<​code>​ 
 +any(f(x) = x < 0, [1, 2, 3, 4])   => False 
 +any(f(x) = x % 2 == 0, [1, 2, 3]) => True   (2 e par) 
 +</​code>​ 
 + 
 +=== 2.3 Rezumat funcționale === 
 + 
 +| **Funcțională** | **Descriere** | **Exemplu** | 
 +| **foldl** | Agregare stânga→dreapta cu acumulator | foldl(+, 0, [1,2,3]) = 6 | 
 +| **foldr** | Agregare dreapta→stânga cu acumulator | foldr(-, 0, [1,2,3]) = 2 | 
 +| **map** | Transformă fiecare element | map(x→x*2,​ [1,2]) = [2,4] | 
 +| **filter** | Păstrează elementele care satisfac predicatul | filter(par, [1,2,3]) = [2] | 
 +| **reduce** | Agregare fără acumulator inițial | reduce(+, [1,2,3]) = 6 | 
 +| **all** | Toate satisfac predicatul? | all(>0, [1,2]) = True | 
 +| **any** | Există cel puțin unul care satisface? | any(<0, [1,2]) = False |
  
poo/breviare/breviar-13.1546863528.txt.gz · Last modified: 2019/01/07 14:18 by carmen.odubasteanu
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