This shows you the differences between two versions of the page.
|
poo:laboratoare:13 [2023/12/09 11:42] carmen.odubasteanu |
poo:laboratoare:13 [2026/01/12 08:46] (current) george.tudor1906 |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ===== Laboratorul 11. ===== | ||
| - | === Problema 1 - Singleton === | + | ===== Laboratorul 13 – Fluxuri I/O. Funcționale ===== |
| - | Implementați o clasa **Catalog** care conține o lista cu obiecte de tip **Course**. | + | {{:poo:laboratoare:arhiva_13.zip|Arhiva laborator}} |
| - | Va trebui sa va asigurați ca pentru aceasta clasa va putea exista o singura instanța care sa poata fi accesata din orice clasa a proiectului. Implementati metoda **toString** pentru clasa **Catalog**. | + | |
| - | <code java> | + | === Problema 1 === |
| - | public class Catalog { | + | |
| - | // TODO -- Adaugati aici implementarea exercitiului | + | |
| - | } | + | |
| - | public class Course { | + | |
| - | } | + | |
| - | </code> | + | |
| - | === Problema 2 - Factory === | + | Să se scrie un program pentru afișarea pe ecran a liniilor aflate pe poziții impare |
| - | Pornind de la clasa abstracta **User**, definiți clasele **Student**, **Parent**, **Assistant** și **Teacher** care vor moșteni clasa **User**: | + | dintr-un fișier text. Fiecare linie va fi precedată de numărul ei și un spațiu. |
| - | <code java> | + | În implementare, se va folosi un obiect de tip **LineNumberReader**. |
| - | public abstract class User { | + | |
| - | protected String firstName, lastName; | + | |
| - | public User(String firstName, String lastName) { | + | |
| - | this.firstName = firstName; | + | |
| - | this.lastName = lastName; | + | |
| - | } | + | |
| - | public String toString() { | + | |
| - | return firstName + " " + lastName; | + | |
| - | } | + | |
| - | } | + | |
| - | </code> | + | |
| - | Pentru a putea realiza o instanțiere ușoara a obiectelor pentru aceste tipuri de clase, veți implementa o clasa **UserFactory** care va avea o metoda __statica__ **createUser** ce va returna un obiect de tip **User** (se va folosi șablonul de proiectare **Factory**). | + | Cerințe: |
| + | * Tratați toate excepțiile care ar putea să apară exact acolo unde apar! | ||
| + | * Atenție la închiderea fișierelor – să se facă chiar dacă apare excepție la citire! | ||
| - | Pentru testare folositi clasa **Test** de mai jos, in care veti comenta cerintele neimplementate inca: | + | Pentru validarea acestei cerințe, puteți folosi fișierul text //test01.in// pus la |
| + | dispoziție în arhiva laboratorului. | ||
| - | <code java> | + | === Problema 2 === |
| - | class Test { | + | |
| - | public static void main(String[] args) { | + | |
| - | //testare exercitiu 2 | + | |
| - | User studentA = UserFactory.createUser("Student", "A", "Popescu"); | + | |
| - | User studentB = UserFactory.createUser("Student", "B", "Ionescu"); | + | |
| - | User studentC = UserFactory.createUser("Student", "C", "Ionescu"); | + | |
| - | User mother = UserFactory.createUser("Parent", "M_AC", "Ionescu"); | + | Să se scrie un program care citește un text de la tastatură și îl salvează într-un |
| - | User father = UserFactory.createUser("Parent", "T_AC", "Ionescu"); | + | fișier pe disc. Citirea se va face până la introducerea cuvântului **exit**. |
| - | + | ||
| - | User teacher = UserFactory.createUser("Teacher", "Teacher", "Georgescu"); | + | |
| - | User assistant = UserFactory.createUser("Assistant", "Assistant", "Popescu"); | + | |
| - | + | ||
| - | //testare exercitiu 3+5 | + | |
| - | Course course = new Course.CourseBuilder("POO").teacher((Teacher) teacher) | + | |
| - | .assistant((Assistant) assistant).grade(new Grade("POO", (Student) studentA, 4d,5d)) | + | |
| - | .grade(new Grade("POO", (Student) studentB,3d,3d)).strategy(new BestExamScore()).build(); | + | |
| - | + | ||
| - | System.out.println("Curs: "+ course); | + | |
| - | System.out.println("Best Student:" + course.getBestStudent()); | + | |
| - | + | ||
| - | //testare exercitiu 1+3+5 | + | |
| - | Catalog catalog = Catalog.getInstance(); | + | |
| - | catalog.addCourse(course); | + | |
| - | + | ||
| - | //testare exercitiu 4 | + | |
| - | ((Student) studentB).setMother((Parent) mother); | + | |
| - | ((Student) studentB).setFather((Parent) father); | + | |
| - | ((Student) studentC).setMother((Parent) mother); | + | |
| - | catalog.addObserver((Parent) mother); | + | În implementare se va utiliza metoda **readLine()** pentru un obiect de tip |
| - | catalog.addObserver((Parent) father); | + | **DataInputStream** sau **BufferedReader**. |
| - | catalog.notifyObservers(new Grade("POO", (Student)studentB,2.5d,3d)); | + | |
| - | + | ||
| - | //testare exercitiu 6 | + | |
| - | HashMap<Teacher, ArrayList<Pair<Student, String, Double>>> examScores=new HashMap<>(); | + | |
| - | ArrayList<Pair<Student, String, Double>> ar1=new ArrayList<>(); | + | |
| - | ar1.add(new Pair(studentA,"POO",3.6d)); | + | |
| - | examScores.put((Teacher)teacher,ar1); | + | |
| - | + | ||
| - | HashMap<Assistant, ArrayList<Pair<Student, String, Double>>> partialScores= new HashMap<>(); | + | |
| - | ArrayList<Pair<Student, String, Double>> ar2=new ArrayList<>(); | + | |
| - | ar2.add(new Pair(studentC,"POO",4.6d)); | + | |
| - | partialScores.put((Assistant)assistant,ar2); | + | |
| - | + | ||
| - | Visitor v=new ScoreVisitor(examScores,partialScores); | + | |
| - | + | ||
| - | v.visit((Teacher)teacher); | + | |
| - | System.out.println("Actualizare teacher:" + catalog); | + | |
| - | + | ||
| - | v.visit((Assistant)assistant); | + | |
| - | System.out.println("Actualizare assistant:" + catalog); | + | |
| - | + | ||
| - | } | + | |
| - | } | + | |
| - | </code> | + | |
| - | === Problema 3 - Builder === | + | Tratați toate excepțiile care ar putea să apară! |
| - | Pe baza claselor definite anterior, veți completa implementarea clasei **Course**. În cadrul aplicației noastre, un obiect de tipul **Course** o sa conțina: un nume (de tipul **String**), un profesor titular, o lista de asistenți, o colecție ordonata cu obiecte de tipul **Grade** și o lista de studenți. | + | === Problema 3 === |
| - | Pentru a putea seta câmpurile unui obiect de tip **Course**, veți folosi șablonul de proiectare **Builder**. | + | Să se implementeze un program care citește din fișierul //test02.in// un text și |
| - | ! Definiti **toString** pentru clasa **Course**. | + | determină numărul de cuvinte din text. |
| - | <code java> | + | Pentru citire se vor utiliza un obiect de tip **FileReader** și unul de tip **StreamTokenizer**. |
| - | public class Grade { | + | |
| - | private Double partialScore, examScore; | + | |
| - | private Student student; | + | |
| - | private String course; | + | |
| - | + | ||
| - | public Grade(String course, Student student) { | + | |
| - | partialScore = 0.0; | + | |
| - | examScore = 0.0; | + | |
| - | this.course = course; | + | |
| - | this.student = student; | + | |
| - | } | + | |
| - | + | ||
| - | public Grade(String course, Student student,Double partialScore, Double examScore ) { | + | |
| - | this.partialScore = partialScore; | + | |
| - | this.examScore = examScore; | + | |
| - | this.course = course; | + | |
| - | this.student = student; | + | |
| - | } | + | |
| - | + | ||
| - | public void setPartialScore(Double score) { | + | |
| - | partialScore = score; | + | |
| - | } | + | |
| - | public void setExamScore(Double score) { | + | |
| - | examScore = score; | + | |
| - | } | + | |
| - | public Double getTotal() { | + | |
| - | return partialScore + examScore; | + | |
| - | } | + | |
| - | } | + | |
| - | </code> | + | |
| - | + | ||
| - | Modificați clasa **Grade** astfel încât doua obiecte de tip **Grade** vor putea sa fie comparate (în funcție de punctajul total). | + | |
| - | De asemenea, va trebui sa adaugați în clasa **Catalog** o lista cu obiecte de tip **Course**. | + | |
| - | + | ||
| - | <note> Folositi pentru testare main-ul de la Factory! </note> | + | |
| - | + | ||
| - | === Problema 4 - Observer === | + | |
| - | Aplicația noastra le permite parinților unui student sa se aboneze la **Catalog** pentru a putea primi notificari în momentul în care copilul este notat de catre un profesor sau de catre un asistent. | + | |
| - | Pentru a putea realiza acest lucru, veți folosi șablonul de proiectare **Observer** și veți implementa o clasa **Notification ** (stabiliți voi care sunt atributele și metodele din aceasta clasa – este obligatoriu sa fie suprascrisa metoda **toString**). | + | |
| - | + | ||
| - | Ce clasa va implementa interfața **Observer** și ce clasa va implementa interfața **Subject**? | + | |
| <code java> | <code java> | ||
| - | public interface Observer { | + | FileReader in = new FileReader(new File("test02.in")); |
| - | void update(Notification notification); | + | StreamTokenizer str = new StreamTokenizer(in); |
| - | } | + | |
| - | + | ||
| - | public interface Subject { | + | |
| - | void addObserver(Observer observer); | + | |
| - | void removeObserver(Observer observer); | + | |
| - | void notifyObservers(Grade grade); | + | |
| - | } | + | |
| </code> | </code> | ||
| - | <note> | + | === Problema 4 – Funcționale === |
| - | Hint! | + | |
| - | + | ||
| - | 1.Parent va tine minte si o lista a notificarilor, iar Catalog o lista a Observatorilor. | + | |
| - | + | ||
| - | 2. Atentie! Primesc notificari doar parintii studentului respectiv! Modificati clasa Student astfel incat sa avem memorati si parintii pentru fiecare Student si adaugati o metoda isParent(Observer parent) care verifica daca un observator este parintele studentului current. | + | |
| - | </note> | + | |
| - | <note> Folositi pentru testare main-ul de la Factory! </note> | + | |
| - | + | ||
| - | === Problema 5 - Strategy === | + | |
| - | + | ||
| - | Fiecare profesor va aplica o politica prin care la sfârșitul semestrului selecteaza cel mai bun student. Pentru a realiza acest lucru în cadrul implementarii, va trebui sa folosiți șablonul de proiectare **Strategy**. Veți defini câte o clasa pentru fiecare din urmatoarele strategii: | + | |
| - | + | ||
| - | - 1. **BestPartialScore** – aceasta strategie va selecta studentul care are cel mai mare punctaj în timpul semestrului; | + | |
| - | - 2. **BestExamScore** – aceasta strategie va selecta studentul care are cel mai mare punctaj în examen; | + | |
| - | - 3. **BestTotalScore** – aceasta strategie va selecta studentul care are punctajul total maxim. | + | |
| - | + | ||
| - | <code java> | + | |
| - | interface Strategy { | + | |
| - | Student getBestStudent(Collection<Grade> grades); | + | |
| - | } | + | |
| - | </code> | + | |
| - | + | ||
| - | Veți adauga în clasa **Course** un atribut **Strategy**, si o metoda cu antetul: | + | |
| - | public Student **getBestStudent**(); | + | |
| - | Metoda va returna cel mai bun student, tinand cont de strategia setata de profesor pentru curs. | + | |
| - | + | ||
| - | <note> Folositi pentru testare main-ul de la **Factory**! </note> | + | |
| - | + | ||
| - | === Problema 6 - Visitor === | + | |
| - | + | ||
| - | Folosind șablonul de proiectare **Visitor**, vom implementa funcționalitatea prin care fiecare asistent o sa poata completa notele de pe parcurs ale studenților, iar fiecare profesor o sa poata completa notele de la examen ale studenților sai. | + | |
| - | Pentru acest lucru, vom porni de la urmatoarele 2 interfețe: **Element** și **Visitor**. | + | |
| - | <code java> | + | |
| - | public interface Element { | + | |
| - | void accept(Visitor visitor); | + | |
| - | } | + | |
| - | public interface Visitor { | + | |
| - | void visit(Assistant assistant); | + | |
| - | void visit(Teacher teacher); | + | |
| - | } | + | |
| - | </code> | + | |
| - | Clasele **Assistant** și **Teacher** vor implementa interfața **Element**, iar clasa **ScoreVisitor** va implementa interfața **Visitor**. | + | |
| - | În clasa **ScoreVisitor** vom avea doua dicționare în care sunt stocate notele studentilor pentru examene și pentru parcurs. | + | |
| - | - Dicționarul **examScores** va avea cheia de tip **Teacher** și valoare de tip lista de **Pair** **(Student, Numele cursului – ca String, nota pe care a acordat-o studentului pentru cursul indicat – ca Double).** | + | |
| - | - Dicționarul **partialScores** cu semnificație similara, dar pentru notele de pe parcurs atribuite de asistenți. | + | |
| - | + | ||
| - | În continuare, se va prezenta implementarea de la care veți porni pentru aceasta clasa: | + | |
| - | + | ||
| - | <code java> | + | |
| - | class Pair<K, V1, V2> { | + | |
| - | private K key; | + | |
| - | private V1 value1; | + | |
| - | private V2 value2; | + | |
| - | public Pair(K key, V1 value1, V2 value2) { | + | |
| - | this.key = key; | + | |
| - | this.value1 = value1; | + | |
| - | this.value2 = value2; | + | |
| - | } | + | |
| - | public K getKey() { | + | |
| - | return key; | + | |
| - | } | + | |
| - | public V1 getValue1() { | + | |
| - | return value1; | + | |
| - | } | + | |
| - | public V2 getValue2() { | + | |
| - | return value2; | + | |
| - | } | + | |
| - | } | + | |
| - | public class ScoreVisitor implements Visitor { | + | |
| - | private HashMap<Teacher, ArrayList<Pair<Student, String, Double>>> examScores; | + | |
| - | private HashMap<Assistant, ArrayList<Pair<Student, String, Double>>> partialScores; | + | |
| - | public ScoreVisitor(HashMap<Teacher, ArrayList<Pair<Student, String, Double>>> examScores, HashMap<Assistant, ArrayList<Pair<Student, String, Double>>> partialScores){ | + | |
| - | this.examScores=examScores; | + | |
| - | this.partialScores=partialScores; | + | |
| - | } | + | |
| - | public void visit(Assistant assistant) { | + | |
| - | // **TODO1** | + | |
| - | } | + | |
| - | public void visit(Teacher teacher) { | + | |
| - | // **TODO2** | + | |
| - | } | + | |
| - | } | + | |
| - | </code> | + | |
| - | • **TODO1** – veți determina toate notele pe care le are de trecut asistentul primit ca parametru de metoda respectiva. Veți verifica daca pentru o intrare din lista de note exista sau nu un obiect de tip **Grade** pentru cursul indicat corespunzator studentului. | + | Realizați o arhitectură unificată, similară cu Collections, pentru manipularea listelor |
| - | Daca exista, atunci se va seta nota de pe parcurs pentru acel obiect, daca nu exista, se va crea un nou obiect **Grade** și se va adauga cursului. | + | care să conțină: |
| - | • **TODO2** – veți determina toate notele pe care le are de trecut profesorul primit ca parametru de metoda respectiva. Veți verifica daca pentru o intrare din lista de note exista sau nu un obiect de tip **Grade** pentru cursul indicat corespunzator studentului. | + | * Interfața **Function**, parametrizată corespunzător, care conține o metodă **execute**, având ca parametru un obiect de tip **A** și un rezultat de tip **B**, unde **A** și **B** sunt două tipuri formale; |
| - | Daca exista, atunci se va seta nota de la examen pentru acel obiect, daca nu exista, se va crea un nou obiect **Grade** și se va adauga cursului. | + | |
| - | <note>**Hint!** | + | * Interfața **Addition** folosită pentru a calcula suma a două numere de tip **T**, unde **T** este un subtip al lui **Number** (aceasta va conține o metodă **zero** care va întoarce elementul neutru al operației de adunare și o metodă **add**, care primește două obiecte de tip **T** și returnează suma lor); |
| - | Veti adauga metodele de care aveti nevoie in clasele utilizate. | + | |
| - | Exemple: | + | * Doi algoritmi polimorfici: **reverse** care inversează elementele unei liste și **sum** care calculează suma elementelor din listă; acești algoritmi trebuie să poată fi folosiți pe implementări diferite de liste, deoarece le abordează la nivel de interfață; |
| - | In **Catalog** veti adauga o metoda public **Course** **getCourse**(**String** name), care intoarce obiectul Course corespunzator numelui trimis ca parametru. | + | |
| - | In **Course** o metoda **addGrade**(**Grade** g); | + | * O serie de metode care au un comportament similar cu funcționalele din paradigma funcțională. |
| - | Etc. | + | |
| - | </note> | + | |
| - | <note> Folositi pentru testare main-ul de la **Factory**! </note> | + | Veți porni implementarea de la clasa **ListUtil**, pusă la dispoziție în arhiva laboratorului. |
| - | <hidden>{{:poo:laboratoare:arhiva_13.zip|Arhiva laborator}} | + | |
| - | </hidden> | + | |