Laboratorul 11 – Design Patterns (1)

Problema 1 - Singleton

Implementați o clasă Catalog care conține o listă cu obiecte de tip Course. Va trebui să vă asigurați că pentru această clasă va putea exista o singură instanță care să poată fi accesată din orice clasă a proiectului. Implementați metoda toString pentru clasa Catalog.

public class Catalog {
    // TODO -- Adaugati aici implementarea exercitiului
}
 
public class Course {
}

Problema 2 - Factory

Pornind de la clasa abstractă User, definiți clasele Student, Parent, Assistant și Teacher care vor moșteni clasa User:

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;
    }
}

Pentru a putea realiza o instanțiere ușoară a obiectelor pentru aceste tipuri de clase, veți implementa o clasă UserFactory care va avea o metodă statică createUser ce va returna un obiect de tip User (se va folosi șablonul de proiectare Factory).

Problema 3 - Builder

Pe baza claselor definite anterior, veți completa implementarea clasei Course. În cadrul aplicației noastre, un obiect de tipul Course o să conțină:

  • un nume (de tipul String)
  • un profesor titular
  • o listă de asistenți
  • o colecție ordonată cu obiecte de tipul Grade
  • o listă de studenți

Pentru a putea seta câmpurile unui obiect de tip Course, veți folosi șablonul de proiectare Builder. Definiți toString pentru clasa Course.

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;
    }
}

Modificați clasa Grade astfel încât două obiecte de tip Grade vor putea să fie comparate (în funcție de punctajul total). De asemenea, va trebui să adăugați în clasa Catalog o listă cu obiecte de tip Course.

Problema 4 - Observer

Aplicația noastră le permite părinților unui student să se aboneze la Catalog pentru a putea primi notificări în momentul în care copilul este notat de către un profesor sau de către un asistent. Pentru a putea realiza acest lucru, veți folosi șablonul de proiectare Observer și veți implementa o clasă Notification (stabiliți voi care sunt atributele și metodele din această clasă – este obligatoriu să fie suprascrisă metoda toString).

Ce clasă va implementa interfața Observer și ce clasă va implementa interfața Subject?

public interface Observer {
    void update(Notification notification);
}
 
public interface Subject {
    void addObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers(Grade grade);
}

Hint:

  • Parent va ține minte și o listă a notificărilor, iar Catalog o listă a Observatorilor.
  • Atenție! Primesc notificări doar părinții studentului respectiv! Modificați clasa Student astfel încât să avem memorați și părinții pentru fiecare Student și adăugați o metodă isParent(Observer parent) care verifică dacă un observator este părintele studentului curent.

Problema 5 - Strategy

Fiecare profesor va aplica o politică prin care la sfârșitul semestrului selectează cel mai bun student. Pentru a realiza acest lucru în cadrul implementării, va trebui să folosiți șablonul de proiectare Strategy. Veți defini câte o clasă pentru fiecare din următoarele strategii:

  • BestPartialScore – această strategie va selecta studentul care are cel mai mare punctaj în timpul semestrului;
  • BestExamScore – această strategie va selecta studentul care are cel mai mare punctaj în examen;
  • BestTotalScore – această strategie va selecta studentul care are punctajul total maxim.
interface Strategy {
    Student getBestStudent(Collection<Grade> grades);
}

Veți adăuga în clasa Course un atribut Strategy, și o metodă cu antetul: public Student getBestStudent(); Metoda va returna cel mai bun student, ținând cont de strategia setată de profesor pentru curs.

Problema 6 - Visitor

Folosind șablonul de proiectare Visitor, vom implementa funcționalitatea prin care fiecare asistent o să poată completa notele de pe parcurs ale studenților, iar fiecare profesor o să poată completa notele de la examen ale studenților săi.

public interface Element {
    void accept(Visitor visitor);
}
 
public interface Visitor {
    void visit(Assistant assistant);
    void visit(Teacher teacher);
}

Clasele Assistant și Teacher vor implementa interfața Element, iar clasa ScoreVisitor va implementa interfața Visitor. În clasa ScoreVisitor vom avea două dicționare în care sunt stocate notele studenților pentru examene și pentru parcurs.

  • Dicționarul examScores va avea cheia de tip Teacher și valoare de tip listă 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 similară, dar pentru notele de pe parcurs atribuite de asistenți.
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
    }
}
  • TODO1 – veți determina toate notele pe care le are de trecut asistentul primit ca parametru de metoda respectivă. Veți verifica dacă pentru o intrare din lista de note există sau nu un obiect de tip Grade pentru cursul indicat corespunzător studentului. Dacă există, atunci se va seta nota de pe parcurs pentru acel obiect, dacă nu există, se va crea un nou obiect Grade și se va adăuga cursului.
  • TODO2 – veți determina toate notele pe care le are de trecut profesorul primit ca parametru de metoda respectivă. Veți verifica dacă pentru o intrare din lista de note există sau nu un obiect de tip Grade pentru cursul indicat corespunzător studentului. Dacă există, atunci se va seta nota de la examen pentru acel obiect, dacă nu există, se va crea un nou obiect Grade și se va adăuga cursului.

Hint! Veți adăuga metodele de care aveți nevoie în clasele utilizate. Exemple: În Catalog veți adăuga o metodă public Course getCourse(String name), care întoarce obiectul Course corespunzător numelui trimis ca parametru. În Course o metodă addGrade(Grade g);. Etc.

Clasa Test (pentru testare)

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");
        User father = UserFactory.createUser("Parent", "T_AC", "Ionescu");
        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);
        catalog.addObserver((Parent) father);
        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);
    }
}
poo/laboratoare/11.txt · Last modified: 2025/12/14 17:54 by george.tudor1906
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