Clasele au fost create si grupate in package-uri. Aceasta grupare a fost bazata pe criterii precum:
- design pattern-uri
- asemanarea logicii codului
- acelasi tip de clase
Mentiuni importante privind implementarea:
- Clasa
Maincontine doar instructiunile necesare doar pentru a da mai departe claseiControllerargumentele din linia de comanda, adica path-ul fisierelor de input - Clasa
Controllercontine logica centrala a proiectului. - Folosirea conceptelor de POO:
- Encapsulare: toate proprietatile sunt declarate
private, cu metode getter/setter unde este necesar - Mostenire: clasele de comenzi extind clasa de baza
Command - Polimorfism: tratarea diferitelor tipuri de comenzi
- Genericitate: de exemplu in
ResourceGroupList members
- Encapsulare: toate proprietatile sunt declarate
- Folosirea a 5 design pattern-uri diferite:
- Singleton
- Factory Method
- Builder
- Command
- Observer
In aceasta clasa este punctul de intrare in aplicatie. Este o clasa simpla care primeste ca parametri tipul path-ului si path-ul/path-urile respective si apeleaza metoda executeCommands() din clasa Controller.
Clasa Controller contine logica centrala a proiectului, gestionand toate comenzile primite din fisierul de input.
Aici am folosit design pattern-ul Command:
- implementarea clasei abstracte
Commandcare contine metoda execute() si care trebuie implementata de toate clasele care extind aceasta clasa. - am creat cate o clasa pentru fiecare comanda din enuntul proiectului. Acestea implementeaza metoda execute() si sunt apelate in clasa
Controllerprin crearea unei instante pentru fiecare comanda.
Fiecare comanda genereaza un output. Acest output este scris la finalul functiei executeCommands() folosind Files.writeString.
Am creat functii de "check" care arunca exceptiile implementate din enunt in caz ca parametrii lipsesc. Aceasta verificare este facuta inainte de procesarea comenzii respective.
Inainte ca obiectele de tip Server/ResourceGroup/User sa fie date ca si parametrii comenzilor, acestea au fost create folosind clasa InfrastructureFactory.
Clasa Database gestioneaza toate colectiile care retin serverele, grupurile de monitorizare si alertele.
Pe langa metodele din enunt, am creat functii de get care returneaza server/group in functie de ipAddress si functii de contains care au ca parametru tot ipAddress.
In aceasta clasa a fost folosit design pattern-ul Singleton prin crearea unei instante unice care a fost instantiata prin metoda getInstntce(). Aceasta asigura ca exista doar o instanta de database.
Aceste clase au atribute obligatorii si atribute optionale.
Astfel aceste clase folosesc design pattern-ul Builder prin crearea unui constructor Builder() ce are ca parametri atributele obligatorii. In continuare sunt create metodele ce seteaza fiecare atribut optional. In final este metoda build() care creeaza obiectul cu atributele setate.
Crearea serverelor, grupurilor si a membrilor se face in clasa InfrastructureFactory pe baza variabilei properties[] dat ca parametru metodelor pentru crearea fiecarei clase.
Astfel am folosit design pattern-ul Factory Method in doua moduri distincte:
- prin clasa
InfrastructureFactory - prin clasa
MemberFactory
Clasa InfrastructureFactory nu implementeaza o singura metoda create() spre deosebire de MemberFactory care respecta design-ul din laborator.
MemberFactory foloseste un switch(role) prin care verifica ce fel de Membru trebuie creat.
Pe langa atributele si metodele mentionate in enunt, aceasta clasa contine si metoda update() specifica design pattern-ului Observer.
Am implementat acest pattern folosind clasele Server si ResourceGroup. Server fiind subiectul, iar ResourceGroup observatorul.
Clasa Server contine metodele attachGroup si notifyObserver care sunt apelate prin database. Cand este adaugata o alerta, database-ul notifica grupul atasat la server, care returneaza un mesaj in schimb.
Am folosit acest design pattern pentru a reprezenta fiecare operatiune ca un obiect independent (cu metoda execute()), astfel încât să fie clar care comenzi pot fi apelate, in ce ordine si in ce context, iar clasele ce le invoca sa fie decuplate de implementarile efective ale actiunilor.
Am folosit acest design pattern pentru a fi sigur ca exista doar un database. Acesta asigura si faptul ca toate metodele din toate clasele care au o referinta la database actioneaza asupra aceleasi instante.
Am folosit acest design pattern pentru a lasa subclasele sa decida ce clasa sa instantieze. Astfel am putut sa creez mai usor membri in functie de rolul lor sau obiecte in functie de clasa lor.
Am folosit acest design pattern pentru a putea crea anumite obiecte de tip Server sau Location care au unele atribute optionale, astfel nu trebuie sa creez cate un constructor pentru fiecare posibilitate de atribute care nu sunt specificate.
Am folosit acest design pattern pentru a arata relatia dintre clasele server si resourcegroup. Acesta permite grupurilor sa afle cand apare o alerta pe server si sa o gestioneze cu usurinta. Serverul notifica observatorii chiar daca nu stie cine sunt acestia.