Sunteți pe pagina 1din 15

MINISTERUL EDUCAŢIEI AL REPUBLICII MOLDOVA

UNIVERSITATEA TEHNICĂ A MOLDOVEI


FACULTATEA CALCULATOARE, INFORMATICǍ ȘI MICROELECTRONICǍ
DEPARTAMENTUL INGINERIA SOFTWARE ȘI AUTOMATICĂ

RAPORT
Lucrarea de laborator nr. 2
Disciplina : Tehnici și mecanisme de proiectare software
Tema : Șabloane de proiectare structurale

A efectuat: st.gr. TI–171 F/r


Roșca Doinița

A verificat: asist.univ.
Poștaru Andrei

Chișinău 2021
Sarcina lucrării
De implementat 3 șabloane structurale la alegere .

Mersul lucrării
Fiecare şablon descrie o problemă care apare mereu în domeniul nostru de activitate şi indică esenţa
soluţiei acelei probleme într-un mod care permite utilizarea soluţiei de nenumărate ori în contexte diferite .
Un sablon reprezintă o soluţie comună a unei probleme într-un anumit context .
Șabloanele ne usurează viața . Cu ajutorul lor putem să înțelegem “mai bine” POO . Uneori pot reduce
ordinul de complexitate al problemei sau fac definițiile obiectelor mai ușor de înțeles .
După scop avem trei șabloane :
 Şabloanele creaţionale (creational patterns) privesc modul de creare al obiectelor .
 Şabloanele structurale (structural patterns) se referă la compoziţia claselor sau al obiectelor .
 Şabloanele comportamentale (behavioral patterns) caracterizează modul în care obiectele şi clasele
interacţionează şi îşi distribuie responsabilităţile .
După domeniu de aplicare se clasifică în :
 Şabloanele claselor se referă la relaţii dintre clase , relaţii stabilite prin moştenire şi care sunt statice
(fixate la compilare) .
 Şabloanele obiectelor se referă la relaţiile dintre obiecte , relaţii care au un caracter dinamic .

 
În ingineria software , şabloanele structurale sunt şabloane ce facilitează proiectarea prin identificarea
unui mod simplu de a realiza relațiile între entități . Ele arată cum pot fi lipite împreună diferite bucăţi ale
unui system , într-un mod flexibil și extensibil .
Șablonul Bridge
Este un șablon care realizează decuplarea unei abstracțiuni de implementarea ei , astfel încât cele 2 pot
varia independent .
Când o anumită abstracțiune poate avea mai multe variante de implementare , de obicei se utilizează
moștenirea : o clasă abstractă definește interfața abstracțiunii , iar subclasele concrete o implementează în
diverse moduri .
Această abordare nu este întotdeauna suficient de flexibilă . Prin moștenire o implementare este legată
permanent de abstracțiune și acest lucru face foarte dificilă modificarea independentă a abstracțiunii și a
implementării .
Sablonul Bridge se aplică în general în situațiile în care :
 se dorește evitarea legării unei abstracțiuni de implementarea sa . Acest lucru se întâmplă de exemplu
când implementarea trebuie aleasă sau modificată pe durata execuției ;
 atât abstracțiunea cât și implementarea trebuie să poată fi extinse prin adăugarea de subclase . În
acest caz sablonul bridge permite combinarea după dorința a diferitelor abstracțiuni și implementări .
 schimbările aduse implementării nu trebuie să afecteze clienții , adică nu trebuie să necesite
recompilarea codului acestora ;
 se dorește ascunderea completă a implementării față de clienți ;
 se constată că extensiile care trebuie aduse unei abstracțiuni duc la o creștere prea mare a numărului
de subclase . În acest caz se indică " spargerea " obiectelor în 2 părți , creindu-se 2 ierarhii separate .
Asemenea ierarhii se mai numesc " generalizări încuibate " ;
 se dorește partajarea unei implementări între mai multe obiecte și acest fapt trebuie ascuns față de
client .
În figura de mai jos este dată structura de clase care constituie șablonul Bridge :

Abstraction :
 definește interfața abstracțiunii ;
 deține o referință spre un obiect de tip Implementor .
RefinedAbstraction :
 extinde interfața Abstraction .
Implementor :
 definește interfața pentru clasele ce conțin implementări . Această interfață nu trebuie neaparat să
corespundă exact cu interfața Abstraction . De fapt , cele 2 pot fi total diferite . De obicei
Implementor oferă doar operații primitive , iar Abstraction definește operații de nivel mai înalt ,
bazându-se pe acele primitive .
ConcreteImplem:
 implementează interfața Implementor .
Obiectele de tip Abstraction redirectează cererile clientului spre obiectele de tip Implementor de care sunt
asociate .
Codul sursă Intrebari
package Sablon;

public interface Intrebari {


public void IntrebareaUrmatoare();
public void IntrebareaPrecedenta();
public void IntrebareNoua(String intreb);
public void StergeIntrebare(String intreb);
public void AfisareIntrebare();
public void AfisareToate();
}

Codul sursă IntrebariJob


package Sablon;

import java.util.ArrayList;
import java.util.List;

public class IntrebariJob implements Intrebari{


private List<String>intrebari=new ArrayList<String>();
private int curent=0;
public IntrebariJob() {
questions.add("Ce este un job?");
questions.add("Ce este un CV?");
questions.add("Cum indeplinesc un CV?");
questions.add("Cum stiu ca am fost acceptat la interviu de companie?");
questions.add("La cite companii pot trimite CV simultan?");
questions.add("Unde gasesc contactele companiei?");
questions.add("Sunt in siguranta datele persoanele pe aceasta platforma?");
questions.add("Cum obtin postul dorit cit mai rapid?");
}
public void IntrebareaUrmatoare() {
if(curent<=intrebari.size()-1)
curent++;
System.out.print(curent);
}
public void IntrebareaPrecedenta() {
if(curent>0)
curent--;
}
public void IntrebareNoua(String intreb) {
intrebari.add(intreb);
}
public void StergeIntrebare(String intreb) {
intrebari.remove(intreb);
}
public void AfisareIntrebari() {
System.out.println(intrebari.get(curent));
}
public void AfisareToate() {
for(String intreb:intrebari) {
System.out.println(intreb);
}
}
@Override
public void AfisareIntrebare() {
// TODO Auto-generated method stub
}
}

Codul sursă ManagerIntrebari


package Sablon;

public class ManagerIntrebari {


protected Intrebari i;
public String catalog;
public ManagerIntrebari(String catalog) {
this.catalog=catalog;
}
public void urmatoarea() {
i.IntrebareaUrmatoare();
}
public void precedenta() {
i.IntrebareaPrecedenta();
}

public void intrebnoua(String intreb) {


i.IntrebareNoua(intreb);
}
public void sterge(String intreb) {
i.StergeIntrebare(intreb);
}
public void afisare() {
i.AfisareIntrebare();
}
public void afisaretoate() {
System.out.println("Numarul de intrebari:"+catalog);
i.AfisareToate();
}
}

Codul sursă FormatIntrebare


package Sablon;

public class FormatIntrebare extends ManagerIntrebari {


public FormatIntrebare(String catalog) {
super(catalog);
}
public void afisaretoate() {
System.out.println("\n............................");
super.afisaretoate();
System.out.println("...............................");
}
}
Codul sursă BridgePatten
package Sablon;

public class BridgePatten {


public static void main(String[] args) {
FormatIntrebare intrebari=new FormatIntrebare(" Platforma de cautare a joburilor.");
intrebari.i=new IntrebariJob();
intrebari.sterge("Ce este un job?");
intrebari.afisare();
intrebari.intrebnoua("Unde pot gasi un job?");
intrebari.afisaretoate();
}
}

Codul sursă questions


package Sablon;

public class questions {

public static void add(String string) {


// TODO Auto-generated method stub
}
}

Rezultatul
Șablonul Adapter
Adaptorul (cunoscut şi sub numele de wrapper) este o clasă ce permite traducerea unor interfeţe în alte
interfeţe . Adaptorul permite unor clase cu interfeţe incompatibile să interacţioneze . Acest şablon este
folositor atunci când o clasă deja implementată (clasa de adaptat sau clasa furnizor) asigură funcţionalităţile
dorite , dar nu şi interfaţa dorită . Adaptorul ştie să răspundă cel puţin la interfaţa dorită de client , din acest
motiv clasa adaptor este utilizată în mod direct de către clasa client . În acelaşi timp adaptorul ştie să
utilizeze funcţionalităţile clasei de adaptat .
Şablonul Adapter acționează ca un intermediar între două clase , transformând interfața unei clase astfel
încât să poată fi utilizată cu cealaltă . Acest lucru permite claselor cu interfețe incompatibile să lucreze
împreună . Şablonul Adapter implementează o interfață cunoscută clienților săi și asigură accesul la o
instanță a unei clase ce nu este cunoscut clienţilor săi . Un obiect adaptor oferă funcționalitatea unei interfețe
fără să știe clasa folosită pentru a implementa acea interfaţă .
În acest fel , clasa client este independentă de structura interfeţei de adaptat .
Cu un astfel de şablon clasa client poate modifica furnizorii de funcţionalităţi fără să îşi modifice propria
structură , doar utilizând alţi adaptor .
Există două tipuri de adaptoare , în funcţie de modul în care adaptorul reuşeşte să utilizeze
funcţionalităţile clasei de adaptat :
1. adaptoare ce implementează interfaţa dorită de client şi care conţin în plus o instanţă a clasei de
adaptat = object adapter ;

În metoda request a adaptorului se scrie în acest caz :


public void request () {
furnizor.specificRequest();
}
2. adaptoare care implementează ambele interfeţe şi care în metodele ce implementează operaţiile
interfeţei dorite se face trimitere la operaţiile interfeţei de adaptat = class adapter . În acest caz se
poate vorbi de o adaptare bidirecţională a claselor .

Şablonul class adapter presupune folosirea moştenirii multiple . Un exemplu de utilizare a şablonului
object adaptor este cel în care aplicaţiile client de messenger pot utiliza diferite servere de messenger . Iniţial
un client de messenger poate fi dezvoltat pentru un singur server , ulterior dorindu-se utilizarea şi a altor
servere.
Pentru utilizarea unui alt server de messenger , clasa ServerMessenger se poate specializa într-un adaptor
ce conţine ca şi membru un obiect de tipul unui alt server . Metoda sendText a adaptorului suprascrie
metoda sendText a serverului iniţial făcând delegând activitatea de realizat membrului obiect de tipul
celuilalt server, mai exact folosind metoda sendMessage a acestuia .

Codul sursă CV
package Adaptor;

public interface CV {
public void giveCVDetails();
public String getCV();
}

Codul sursă CVDetails


package Adaptor;

public class CVDetails {


private String CompanyName;
private String PersonName;
private long PhoneNumber;
public String getCompanyName() {
return CompanyName;
}
public void setCompanyName(String CompanyName) {
this.CompanyName=CompanyName;
}
public String getPersonName() {
return PersonName;
}
public void setPersonName(String PersonName) {
this.PersonName=PersonName;
}
public long getPhoneNumber() {
return PhoneNumber;
}
public void setPhoneNumber(long PhoneNumber) {
this.PhoneNumber=PhoneNumber;
}
}

Codul sursă Utilizator


package Adaptor;

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Utilizator extends CVDetails implements CV {


public void giveCVDetails() {
try {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

System.out.print("Introduceti numele persoanei:");


String numeutilizator=br.readLine();
System.out.print("\n");

System.out.print("Introduceti numar telefon:");


long phonenumber=Long.parseLong(br.readLine());
System.out.print("\n");

System.out.print("Introduceti numele companiei:");


String companyname=br.readLine();

setPersonName(numeutilizator);
setPhoneNumber(phonenumber);
setCompanyName(companyname);
}
catch(Exception e) {
e.printStackTrace();
}
}
@Override
public String getCV() {
long phonenumber=getPhoneNumber();
String numeutilizator=getPersonName();
String companyname=getCompanyName();

return(" Persoana cu numele "+numeutilizator+" si cu numarul de telefon "+phonenumber+"


doreste sa se angajeze in compania "+companyname+" . ");
}
}

Codul sursă AdapterPattern


package Adaptor;

public class AdapterPattern {


public static void main(String args[]) {
CV targetInterface=new Utilizator();
targetInterface.giveCVDetails();
System.out.print(targetInterface.getCV());
}
}

Rezulatul
Șablonul Decorator
Șablonul Decorator reprezintă o alternativă mai flexibilă faţă de derivarea claselor în scopul extinderii
funcţionalităţii . Acest șablon permite ataşarea în mod dinamic a funcţionalităţilor aditionale , unui obiect .
Șablonul Decorator se aplică în următoarele situații :
 pentru a adăuga funcțiuni în mod dinamic și transparent unor obiecte individuale ;
 pentru a putea elimina anumite functionalități ;
 când extinderea functionalității prin moștenire nu este posibilă . Uneori avem de a face cu un număr
mare de extensii independente între ele , ceea ce ar duce la necesitatea creării unui număr imens de
subclase , ca să se acopere toate combinațiile posibile .
În figura de mai jos este dată structura de clase care constituie șablonul Decorator :

 Component : definește interfața pentru obiectele cărora li se pot adăuga funcțiuni în mod dinamic ;
 ConcreteComponent : definește un obiect concret căruia i se pot adăuga funcșiuni ;
 Decorator : conține o referință la Component ( compref ) și definește o interfață conformă cu cea a
lui Component ;
 ConcreteDecorator : adaugă funcțiuni noi unei componente .
Decoratorii permit adăugarea / eliminarea de funcțiuni în timpul execuției , pur și simplu prin asocierea /
disocierea obiectelor cu rol de decoratori la / de obiectele cu rol de componente înfășurate . Dacă s-ar aplica
moștenirea , ar trebui să se definească subclase pentru fiecare funcție nouă ( de
exemplu BorderedScrollableTextView , BorderedTextView etc ) .
Spre deosebire de moștenire , decoratorii permit , printre altele , și adăugarea aceleiași funcțiuni de mai
multe ori . De exemplu , pentru a prevedea un TextView cu chenar dublu , vom atașa 2
obiecte BorderDecorator .
În lucrul cu decoratorii se aplică principiul " plătești în măsura în care consume " . Aceasta înseamnă că ,
în loc să se includă toate funcțiile previzibile într-o singură clasă complex , care apoi să fie adaptată
necesităților , se definește o clasă simplă , căreia i se adaugă proprietăți suplimentare folosind
obiectele Decorator . Funcțiunile pot fi asamblate din piese simple . Ca urmare , o clasă nu trebuie să
suporte ( deci să " plătească " ) pentru facilități pe care nu le folosește . Pe de altă parte , se pot defini noi
tipuri de decorator , independent de clasele obiectelor înfășurate
.
Un decorator nu este identic cu componentele pe care le înfășoară . Deși el acționează ca o " manta "
transparentă pentru o component , din punct de vedere al identității obiectelor , componenta decorată nu este
identică cu componenta simpla
.
Un proiect care utilizează șablonul Decorator se materializează adesea în sisteme compuse dintr-un
număr foarte mare de obiecte mici , care seamănă între ele . Diferențele se manifestă doar în modul de
interconectare a obiectelor . Deși aceste sisteme sunt ușor de adaptat de către cei care le înțeleg , ele pot fi
dificil de învățat și depanat .

Codul sursă Program


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Decorator
{
class Program
{
static void Main(string[] args)
{
Beverage beverage = new Espresso();
Console.WriteLine(beverage.getDescription() + " $ " + beverage.cost());

Beverage beverage2 = new DarkRoast();


beverage2 = new Mocha(beverage2);
beverage2 = new Mocha(beverage2);
beverage2 = new Whip(beverage2);
Console.WriteLine(beverage2.getDescription() + " $ " + beverage2.cost());

Beverage beverage3 = new HouseBlend();


beverage3 = new Soy(beverage3);
beverage3 = new Mocha(beverage3);
beverage3 = new Whip(beverage3);
Console.WriteLine(beverage3.getDescription() + " $ " + beverage3.cost());

Console.Read();
}
public abstract class Beverage
{
protected String description = "Suc";
public virtual String getDescription()
{
return description;
}
public abstract double cost();
}
public class Espresso : Beverage
{
public Espresso()
{
description = "Espresso";
}
public override double cost()
{
return 1.99;
}
}
public class DarkRoast : Beverage
{
public DarkRoast()
{
description = "Suc";
}
public override double cost()
{
return .99;
}
}
public class Decaf : Beverage
{
public Decaf()
{
description = "Coffee";
}
public override double cost()
{
return 1.05;
}
}
public class HouseBlend : Beverage
{
public HouseBlend()
{
description = "Coffee with milk";
}
public override double cost()
{
return .89;
}
}
public abstract class CondimentDecorator : Beverage
{
//public abstract String getDescription();
}
public class Mocha : CondimentDecorator
{
Beverage beverage;
public Mocha(Beverage beverage)
{
this.beverage = beverage;
}
public override String getDescription()
{
return beverage.getDescription() + " Mochacinno";
}
public override double cost()
{
return .20 + beverage.cost();
}
}
public class Milk : CondimentDecorator
{
Beverage beverage;
public Milk(Beverage beverage)
{
this.beverage = beverage;
}
public override String getDescription()
{
return beverage.getDescription() + " Milk";
}
public override double cost()
{
return .10 + beverage.cost();
}
}
public class Soy : CondimentDecorator
{
Beverage beverage;
public Soy(Beverage beverage)
{
this.beverage = beverage;
}
public override String getDescription()
{
return beverage.getDescription() + " Soy";
}
public override double cost()
{
return .15 + beverage.cost();
}
}
public class Whip : CondimentDecorator
{
Beverage beverage;
public Whip(Beverage beverage)
{
this.beverage = beverage;
}
public override String getDescription()
{
return beverage.getDescription() + " Wine";
}
public override double cost()
{
return .10 + beverage.cost();
}
}
}
}
Rezultatul

Concluzie
În Ingineria Software şabloanele structurale oferă numeroase beneficii . Eficienţa poate creşte
considerabil ca urmare a utilizării şabloanelor ( Decorator , Flyweight , Proxy ) , iar ( Adapter , Bridge ,
Composite , Façade , Proxy ) pot reduce complexitatea prin oferirea unei interfețe simple , la un sistem care
este mai ușor pentru programatorii client să o înțeleagă .
În această lucrare am ales doar trei șabloane structurale , pe care le-am reazilat și le-am arătat în câte un
program fiecare . Aceste șabloane au fost :
- Șablonul Bridge ,
- Șablonul Adapter ,
- Șablonul Decorator .

S-ar putea să vă placă și