Documente Academic
Documente Profesional
Documente Cultură
OBIECT
Limbajul şi platforma Java
Programare II. C2
Motto
“Simple can be harder than complex: You have to work
hard to get your thinking clean to make it simple. But it’s
worth it in the end because once you get there, you can
move mountains.”
Steve Jobs [BusinessWeek, May 25, 1998,]
2
Capitolul 2.
Principii ale ORIENTĂRII OBIECTUALE
4
1. Principiul ascunderii informației și abstractizării
● Ascunderea informației: separarea implementării
interne față de reprezentarea externă.
● Ascunderea informației sau încapsularea (prin
specificatorii de vizibilitate):
○ încapsularea atributelor;
○ încapsularea comportamentală;
○ împachetarea claselor.
● Abstractizarea: separarea reprezentării externe față
de implementarea internă.
● Abstractizarea prin interfețe: separarea definiției
abstracte față de implementare.
5
1.1 Principiul ascunderii informaţiei
❏ Ascunderea informației reprezintă un mecanism de
încapsulare (delimitare sau separare)
❏ a detaliilor interne (private)
❏ față de caracteristicile accesibile extern (publice) ale
obiectelor.
6
Specificatorii de vizibilitate în Java
❏ Specificatori pentru îngrădirea (protejarea) accesului din
contextul (client) în care va fi invocat obiectul:
❏ private - încapsulare completa;
❏ “package” sau “friendly” - fără specificator explicit:
restricționează accesul din clase din pachete externe;
❏ protected restricționează accesul din pachete externe din
afara ierarhiei de moștenire.
❏ Specificatori pentru pemiterea accesului (la membrii
structurii de atribute și operații) din contextul (client) în
care va fi invocat obiectul:
❏ public - deschidere completă;
❏ “friendly” sau “package” - fără specificator explicit: permite
accessul din clase din același pachet.
❏ protected - extinde vizibilitatea package la subclase din
pachete externe.
7
Specificatorii de vizibilitate Java
Creștere încapsularea
Creștere vizibilitatea
8
Încapsularea ATRIBUTELOR
Încapsulare structurală
❏ Se referă la protejarea detaliilor informaţionale interne
reprezentate prin atribute și controlul accesibilității
acestora prin intermediul proprietăţilor (convenţia
JavaBeans):
❏ declararea private a atributelor sau variabilelor de
instanță;
❏ restricționarea citirii atributelor prin metode accesor
sau get-teri: getNumeProprietate;
❏ restricționarea modificării atributelor prin metode
modificator sau set-teri: setNumeProprietate.
11
Tipul de clase Record (Java 14>)
● Declară câmpurile încapsulate într-o clasă JavaBean
prin declarația Record - constructor canonic.
● Generează metode de accesare pentru fiecare câmp
din constructorul canonic - cu numele câmpului() -
fără particula get.
● Generează metodele standard equals(), hashCode(),
toString() pe baza câmpurilor din constructorul canonic,
dar care pot fi suprascrise.
● Obiectele instanțiate dintr-o clasă Record sunt
imutabile: câmpurile sunt înregistrate ca final-e,
metodele de access sunt doar pentru citire.
12
Exemplu simplu Record
public record CerintaRecord (
Integer idCerinta,
String denumire,
String descriere,
Long durataEstimata,
Date dataEstimata)
{
public CerintaRecord(Integer idCerinta, String
denumire, String descriere) {
this(idCerinta, denumire, descriere,
0l, new Date()); }
}
13
Cadrul de lucru Lombok
● Funcție de tipul adnotărilor adăugă (la momentul
compilării) :
○ metode accessor (getteri și setteri);
○ metodele standard: equals(), hashCode(), toString();
○ metode constructor.
● Adnotările standard pentru controlul procesului de
generare:
○ @Data - cea mai cuprinzătoare - și @Value;
○ @Getter, @Setter;
○ @EqualsAndHashCode și @ToString;
○ @NoArgsConstructor, @RequiredArgsConstructor,
@AllArgsConstructor
14
Exemplu simplu Lombok
(import lombok.*)
@Data @EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class CerintaData {
@EqualsAndHashCode.Include
private Integer idCerinta;
private String denumire;
protected String descriere;
private Long durataEstimata = 0l;
private Date dataEstimata = new Date();
// restrict setDataFinalizare to be generated
@Setter(AccessLevel.NONE)
private Date dataFinalizare;
}
15
Încapsularea METODELOR -
Încapsulare comportamentală
❏ “Ascunderea” metodelor, facându-le inaccesibile din
exterior, constituie esenţa principiului încapsulării
comportamentale care afirmă că numai operaţiile
necesare (relevante) a fi invocate din exterior să fie
accesibile.
❏ Algoritmul de implementare a metodelor accesibile
(publice) poate fi modularizat cu ajutorul metodelor
interne (declarate private) inaccesibile din exterior.
16
Exemplu încapsulare atribute și metode::
org.encapsulation.members
17
Încapsularea sau împachetarea CLASELOR
● Clasele pot fi declarate:
○ (direct) în interiorul pachetelor:
■ pot fi publice, accesibile din exteriorul pachetelor;
■ pot fi neînsoţite de specificatorul de vizibilitate public:
accesibilitatea fiind limitată doar membrilor pachetului (doar
la clasele declarate în interiorul pachetului).
○ în interiorul altor clase: în acest fel se creează clase
interne (nested/inner classes), care pot fi:
■ de tip:
● clase interne statice;
● clase interne non-statice.
■ accesibile prin specificatori:
● public;
● privat;
● protected.
18
Clase abstracte, interne, anonime
19
Exemplu încapsulare clase ::
[org.encapsulation.classes.*]
● Domain Model
○ Cerinta - Task - DetaliuTask
● Pachete
○ org.encapsulation.classes ::
■ clasa Cerinta
■ import org.encapsulation.classes.domain.Task
○ org.encapsulation.classes.domain ::
■ clasa Task, enums StatusTask, CategorieTask
■ Clasa internă: Task.DetaliuTask
● Clasa Test org.encapsulation.classes.TestIncapsulareClase
○ Invocare clase încapsulate
20
Încapsularea pachetelor și serviciilor
prin intermediul modulelor (Java 9)
● Un modul -> un fișier-arhivă .jar
○ Dependent de alte module din alte fișiere .jar din
classpath
● root-module-dir\module-info.java
○ module <module-name>{
■ requires transitive <other-module>
■ opens <package> to <other-module>
■ exports <package> to <other-module>
○
■ uses <service-definition-class-or-definition>
■ provides <service-definition-class-or-definition>
● with <service-implementation-class-or-definition>
○ }
Java Modularity, JIGSAW, Examples
21
1.2 Principiul abstractizării prin interfeţe
● Interfaţa reprezintă un mecanism de extragere,
separare sau abstractizare a definiţiei tipului faţă de
implementare.
○ Interfeţele (ca și clasele abstracte) nu permit instanţierea
directă.
○ Interfețele sunt implementate concret prin clase cu
implementări conforme specificațiilor abstracte.
● Tipizarea reprezintă (re)cunoașterea obiectelor prin
tipurile-interfețelor implementate.
* 22
Sub-tipizare şi interfeţe
● Definiţia interfețelor se limitează doar la
membri-operaţii, nu permit declarare de variabile de
instanţă (evitarea detaliilor de implementare):
○ pot fi adăugate constante-statice pentru declararea
valorilor “legale” ce formează domeniul discret al
unor eventuali parametri sau atribute și proprietăți;
○ pot fi adăugate operații cu metode de implementare
default.
○ pot fi adăugate operații static-e cu metode de
implementare.
Ex. domeniu STARE:
static final Integer NOUA = 1;
static final Integer IN_PROGRES = 2;
static final Integer COMPLETA = 3;
static final Integer INCHISA = 4;
void setStare(Integer stareModificata);
* 23
Implementarea interfeţelor
* 24
Interfețe și polimorfism
25
Tipuri abstracte de date TAD în Java
26
Tipuri abstracte de date TAD în Java
27
Exemplu: TAD-UML cu proprietăţi JavaBean
ex. 2.4
28
Exemplu interfață-TAD :: org.abstracting.interfaces
29
2. Principiul reutilizabilității obiectelor
● Principiul reutilizabilității obiectelor se referă la faptul
că scopul creării obiectelor constă în invocarea
funcţionalităţii asociate acestora: de fiecare dată
când un obiect este instanţiat, funcţionalitatea
declarată/definită a acestuia urmează a fi
(re)utilizată.
● Reutilizarea claselor este ingredientul fundamental în
construirea unor noi structuri:
○ prin compunere (reutilizare prin referenţiere structurală),
○ prin derivare (reutilizare prin moştenire).
30
2.1 Reutilizabilitate prin Compunere
● Plasarea de referinţe ale unor obiecte în structura noilor
clase are drept consecințe:
○ (d.p.d.v) semantic: obiectele compuse vor include
structural obiectele componente;
○ (d.p.d.v) al implementării: obiectele compuse conţin
câmpuri ce stochează referinţe către obiectele
componente.
● Diferența (semantică) compunere vs. agregare:
○ compunere: dependenţă puternică => componente
“captive”;
○ agregare: dependenţă slabă => componente partajabile.
31
Exemplu: Modelare UML Compunere
32
Exemplu compunere ::
[org.reusability.classes]
public class Sprint {
private List<Cerinta> cerinte = new ArrayList<>();
}
33
2.2 Reutilizabilitate prin moștenire
Specializarea și Generalizarea claselor
● Extinderea setului de caracteristici ale unei clase de
bază prin includerea unor caracteristici specifice =
adăugarea diferenţelor =>
○ Clase diferenţiate pornind de la o bază comună
– SPECIALIZARE.
34
Exemplu: Modelare UML Specializare
35
Reutilizabilitate prin clase abstracte
● Clasele declarate abstracte nu pot fi instanţiate în
mod direct.
● Instanţe ale acestor clase se obţin prin intermediul
claselor concrete care le moştenesc.
● Metodele abstracte sunt specificate în clasele
abstracte şi sunt implementate în clasele concrete.
● Clasele abstracte pot apare:
○ ca efect al specializării: toate instanțele clasei generice
pot fi obținute prin instanțierea claselor concrete
○ ca efect al generalizării: cumularea caracteristicilor
comune, reutilizabile în clase abstracte pentru
simplificarea structurii claselor concrete.
36
Exemplu specializare ::
[org.reusability.classes]
public abstract class Cerinta {
37
Exemplu clasa abstracta: Specializare
[org.reusability.classes]
38
Moștenire în structura obiectelor
● Prin specializare în subclase, obiectele subclaselor
moştenesc atributele (variabilele de instanţă) care
formează scheletul structural al claselor părinte.
● Accesul din contextul sub-claselor la variabilele de
instanţă care provin din super-clase este dependent
de specificatorii de vizibilitate:
○ (package), protected, public.
40
Exemplu moștenire atribute:
[org.reusability.inheritance.attributes]
● Clase: Cerinta, CerintaFunctionala
○ atribute: categorie, descriere, descriereUseCase
● Exemplu supraîncărcare nume atribute si invocare
constructori: this vs.super:
TestOverloadingAttributes
41
Moştenire comportamentală
● Prin specializare în subclase, obiectele subclasate
moştenesc operaţiile şi metodele de implementare
care formează comportamentul claselor părinte.
● Accesul din contextul sub-claselor la operaţiile care
provin din super-clase este dependent de specificatorii
de vizibilitate:
○ private, (package), protected, public.
43
Constructori în ierarhii de moștenire
❏ Constructorul reprezintă o metodă asociată oricărei
clase şi care este apelată în momentul creării
instanţelor. Numele constructorului desemnează o
metodă-membru cu numele clasei, şi nu prezintă un tip
returnat (nici măcar void).
❏ Constructorii sunt metode care nu se moștenesc: nu
sunt metode specifice instanțelor, nu pot fi apelate la
nivelul obiectelor instanțiate.
❏ Fiecare subclasă va invoca implicit sau explicit, din
cadrul propriilor constructori, un constructor al clasei
părinte prin sintaxa super() cu sau fără argumente.
44
Tipuri de constructori
❏ Tipuri:
❏ Constructorul default (adăugat de compilator în lipsa unui
constructor explicit).
❏ Constructorul fără parametri, this().
❏ Constructorul parametrizat, this(args).
❏ Regula supraîncărcării constructorilor: toţi constructorii
au acelaşi “nume” care corespunde cu numele clasei.
❏ Prima instrucțiune din cadrul unui constructor
❏ va invoca constructorul clasei părinte super(args)
❏ sau va invoca un alt constructor local this(args) care va
apela constructorul clasei părinte.
❏ Dacă această instrucțiune nu este explicită, compilatorul
va adăuga/genera implicit super().
45
Diferenţierea metodelor supraîncărcate
● Numele metodelor pot fi supraîncărcate prin
impunerea restricţiei ca fiecare să aibă o listă de
argumente unică prin:
○ numărul argumentelor;
○ tipul argumentelor;
○ ordinea argumentelor.
● Nu se iau în considerare numele argumentelor şi
nici tipul returnat.
46
Moştenire multiplă şi interfeţe
● O deosebirea esenţială dintre interfeţe şi ierarhiile de
clase rezidă în faptul că, în cazul primelor, acestea pot
extinde mai mult decât un singur părinte.
● O clasă în sine poate implementa în mod direct mai
multe interfeţe. Adică ar putea avea mai mulţi
“părinţi”-interfeţe, în afară, eventual, de unul singur care
ar putea fi o clasă obişnuită.
○ Regulile de subtipizare care se aplică claselor se aplică
în aceeași măsură şi interfeţelor.
47
Restricționarea ierarhiei de moștenire
48
Exemplu ierarhie de moștenire
interface Angajat
class ProductManager
extends ManagerProiect
49
Exemplu moștenire operații :
[org.reusability.inheritance.operations]
● Ierarhie Membru (refactoring … Persoana)
○ prop. rol;
○ prop. ManagerProiect :: competente;
■ overloading: getCompetente()
○ constructori subclase ManagerProiect, LiderEchipa;
○ ierarhie sealed - clasa Membru;
○ overriding în subclasa ManagerProiect:setRole()
● Ierarhie Cerinta:
○ proprietate categorie, protected;
■ overriding: setCategorie()
○ constructori în subclase;
○ ierarhie deschisă: clasa Cerinta declarată abstractă;
● TestOverridingOverloadingOperations
50
2.3 Object Oriented Design Patterns
51
Design Patterns
52
Design Pattern Types
54
Implementare Factory
● Abordarea directă
○ implementare completă a clasei Factory
■ org.design.patterns.factory.CerintaFactory
● Exemple Java Standard Library
○ java.time.LocalDate.now()
○ java.time.LocalDate.of()
○ Double.valueOf()
○ java.util.Calendar.getInstance()
○ java.util.List.of()
55
Builder Pattern
● Abordarea directă:
○ implementare completă a clasei Builder
■ org.design.patterns.builder.Cerinta.CerintaBuilder
● Abordarea declarativă lombok @Builder, @With
● Exemple Builder în Java Standard Library:
○ java.util.Calendar.Builder.set…().build();
○ java.time.LocalDate.now().with…();
○ new StringBuilder().append().append().toString().
57
Singleton Pattern
58
Implementare Singleton
● Abordarea directă
○ implementare completă a clasei Singleton
■ org.design.patterns.singleton.ComputeCerintaService
■ org.design.patterns.singleton.ComputeCerintaStaticService
● Abordare declarativă
○ Adnotarea @Singleton în aplicații Java/Jakarta Enterprise
(SessionBean components).
○ Adnotarea @Bean@Scope(“singleton”) în aplicații cu
Spring Framework (Spring DI components).
● Exemple Java Library
○ java.util.Calendar.getInstance()
59
Exemple design patterns :
[org.design.patterns]
● org.design.patterns.factory.CerintaFactory
○ Metode factory:
■ getCerinta() pentru ierarhia ICerinta
■ getInstace() doar pentru clasa Cerinta
● org.design.patterns.builder
○ Clasa Bean: Cerinta
○ Clasa Builder: Cerinta.CerintaBuilder
● org.design.patterns.singleton
○ Clasa cu instanță Singleton: ComputeCerintaService
○ Clasa statică: ComputeCerintaStaticService
● org.design.patterns.factory.TestFactory
● org.design.patterns.builder.TestBuilder
● org.design.patterns.singleton.TestSingleton
60
References. Tutorials. Links
● Encapsulation
○ TutorialsPoints: Encapsulation
○ JavaCodeGeeks: Encapsulation
○ Learneroo:
● Composition
○ JavaCodeGeeks: Inheritance&Composition
● Subclasses and inheritance
○ TutorialsPoints: Inheritance
○ Oracle JavaSE Tutorials: Inheritance concept
○ JavaCodeGeeks: Inheritance
○ Learneroo: Inheritance
● Design patterns
○ https://www.digitalocean.com/community/tutorials/builde
r-design-pattern-in-java
61
Java Books References
Ivor Horton, Beginning Java®, Java 7 Edition, John Wiley &
Sons, Inc, 2011, ISBN: 978-0-470-40414-0
Kishori Sharan, Beginning Java Language Features: With
Modules, Streams, Threads, I/O, and Lambda Expressions,
2nd Ed., Apress, 2018
Kishori Sharan, Beginning Java 9 Fundamentals: Language
Syntax, Arrays, Objects, Modules, JShell and Regular
Expressions, 2nd Edition, Apress, 2017
62
Java Books References
● Erich Gamma, Richard Helm, Ralph Johnson, John
Vlissides, Design Patterns: element of reusable
object-oriented software, Addison-Wesley, 1995
● [Burns, 2018] Brendan Burns, Designing Distributed
Systems. Patterns and Paradigms for Scalable, Reliable
Services, O’Reilly Media, Inc., 2018
● [Fowler et a., 2002] Martin Fowler, David Rice,
Matthew Foemmel, Edward Hieatt, Robert Mee, Randy
Stafford, Patterns of Enterprise Application
Architecture, Addison Wesley, 2002
63