Introducció al Patró Proxy
El patró Proxy és un patró estructural que proporciona un substitut o un representant d'un altre objecte per controlar l'accés a aquest. Aquest patró és útil quan necessitem controlar l'accés a un objecte, afegir funcionalitats addicionals abans o després de l'accés a l'objecte, o retardar la creació d'un objecte costós fins que sigui necessari.
Objectius del Patró Proxy
- Controlar l'accés: Permet controlar l'accés a l'objecte original.
- Reduir el cost: Retarda la creació de l'objecte fins que sigui necessari.
- Afegir funcionalitats: Permet afegir funcionalitats addicionals abans o després de l'accés a l'objecte.
Tipus de Proxies
- Remote Proxy: Controla l'accés a un objecte que resideix en un espai d'adreces diferent.
- Virtual Proxy: Retarda la creació d'un objecte costós fins que sigui necessari.
- Protection Proxy: Controla l'accés a un objecte basat en permisos.
- Smart Proxy: Proporciona funcionalitats addicionals com la referència comptada o la verificació de bloqueig.
Diagrama UML del Patró Proxy
+-----------------+ +-----------------+
| Client | | RealSubject |
+-----------------+ +-----------------+
| - subject: Proxy|<>------->| + request() |
+-----------------+ +-----------------+
| ^
| |
v |
+-----------------+ |
| Proxy |--------------+
+-----------------+
| - realSubject: |
| RealSubject |
+-----------------+
| + request() |
+-----------------+Implementació del Patró Proxy
Exemples de Codi
Interface Subject
Classe RealSubject
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject: Handling request.");
}
}Classe Proxy
public class Proxy implements Subject {
private RealSubject realSubject;
@Override
public void request() {
if (realSubject == null) {
realSubject = new RealSubject();
}
System.out.println("Proxy: Logging the request.");
realSubject.request();
}
}Classe Client
public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}Explicació del Codi
- Subject Interface: Defineix la interfície comuna per a
RealSubjectiProxy. - RealSubject: Implementa la interfície
Subjecti conté la lògica real que es vol controlar. - Proxy: També implementa la interfície
Subjecti conté una referència aRealSubject. Controla l'accés aRealSubjecti pot afegir funcionalitats addicionals. - Client: Utilitza l'objecte
Proxyper accedir aRealSubject.
Exercici Pràctic
Enunciat
Implementa un patró Proxy que controli l'accés a un objecte BankAccount. El proxy ha de verificar si l'usuari té permisos per accedir al compte bancari abans de permetre qualsevol operació.
Solució
Interface BankAccount
public interface BankAccount {
void deposit(double amount);
void withdraw(double amount);
double getBalance();
}Classe RealBankAccount
public class RealBankAccount implements BankAccount {
private double balance;
@Override
public void deposit(double amount) {
balance += amount;
System.out.println("Deposited " + amount + ". New balance: " + balance);
}
@Override
public void withdraw(double amount) {
if (amount <= balance) {
balance -= amount;
System.out.println("Withdrew " + amount + ". New balance: " + balance);
} else {
System.out.println("Insufficient funds.");
}
}
@Override
public double getBalance() {
return balance;
}
}Classe BankAccountProxy
public class BankAccountProxy implements BankAccount {
private RealBankAccount realBankAccount;
private String userRole;
public BankAccountProxy(String userRole) {
this.userRole = userRole;
this.realBankAccount = new RealBankAccount();
}
private boolean hasAccess() {
return "ADMIN".equals(userRole);
}
@Override
public void deposit(double amount) {
if (hasAccess()) {
realBankAccount.deposit(amount);
} else {
System.out.println("Access denied. Only ADMIN can deposit.");
}
}
@Override
public void withdraw(double amount) {
if (hasAccess()) {
realBankAccount.withdraw(amount);
} else {
System.out.println("Access denied. Only ADMIN can withdraw.");
}
}
@Override
public double getBalance() {
if (hasAccess()) {
return realBankAccount.getBalance();
} else {
System.out.println("Access denied. Only ADMIN can view the balance.");
return 0;
}
}
}Classe Client
public class Client {
public static void main(String[] args) {
BankAccount adminAccount = new BankAccountProxy("ADMIN");
adminAccount.deposit(100);
adminAccount.withdraw(50);
System.out.println("Balance: " + adminAccount.getBalance());
BankAccount userAccount = new BankAccountProxy("USER");
userAccount.deposit(100);
userAccount.withdraw(50);
System.out.println("Balance: " + userAccount.getBalance());
}
}Explicació del Codi
- BankAccount Interface: Defineix les operacions que es poden realitzar en un compte bancari.
- RealBankAccount: Implementa la interfície
BankAccounti conté la lògica real per gestionar el compte bancari. - BankAccountProxy: Implementa la interfície
BankAccounti controla l'accés aRealBankAccountbasat en el rol de l'usuari. - Client: Utilitza l'objecte
BankAccountProxyper accedir aRealBankAccount.
Resum
El patró Proxy és una eina poderosa per controlar l'accés a un objecte, afegir funcionalitats addicionals i retardar la creació d'objectes costosos. Hem vist com implementar aquest patró amb un exemple pràctic de control d'accés a un compte bancari. Aquest patró és especialment útil en situacions on es necessita un control estricte sobre l'accés a certs recursos o funcionalitats.
Curs de Patrons de Disseny de Programari
Mòdul 1: Introducció als Patrons de Disseny
- Què són els Patrons de Disseny?
- Història i Origen dels Patrons de Disseny
- Classificació dels Patrons de Disseny
- Avantatges i Desavantatges d'Usar Patrons de Disseny
Mòdul 2: Patrons Creacionals
Mòdul 3: Patrons Estructurals
Mòdul 4: Patrons de Comportament
- Introducció als Patrons de Comportament
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Mòdul 5: Aplicació de Patrons de Disseny
- Com Seleccionar el Patró Adequat
- Exemples Pràctics d'Ús de Patrons
- Patrons de Disseny en Projectes Reals
- Refactorització Usant Patrons de Disseny
Mòdul 6: Patrons de Disseny Avançats
- Patrons de Disseny en Arquitectures Modernes
- Patrons de Disseny en Microserveis
- Patrons de Disseny en Sistemes Distribuïts
- Patrons de Disseny en Desenvolupament Àgil
