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
RealSubject
iProxy
. - RealSubject: Implementa la interfície
Subject
i conté la lògica real que es vol controlar. - Proxy: També implementa la interfície
Subject
i conté una referència aRealSubject
. Controla l'accés aRealSubject
i pot afegir funcionalitats addicionals. - Client: Utilitza l'objecte
Proxy
per 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
BankAccount
i conté la lògica real per gestionar el compte bancari. - BankAccountProxy: Implementa la interfície
BankAccount
i controla l'accés aRealBankAccount
basat en el rol de l'usuari. - Client: Utilitza l'objecte
BankAccountProxy
per 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