Proxy (padrón de deseño)
O padrón de deseño Proxy é un padrón estrutural que ten como propósito proporcionar un subrogado ou intermediario dun obxecto para controlar o seu acceso.
Motivación
Para explicar a motivación do uso deste padrón vexamos un exemplo onde a súa aplicación sería a solución máis axeitada ao problema requirido.
- Editor que pode engadir obxectos dentro dun documento. A apertura do documento deberá ser rápida, e a creación dos obxectos (imaxes de gran tamaño) é cara
- Non é necesario crear todos os obxectos con imaxes ao abrir o documento porque non todos os obxectos son visibles.
- Solución : cargar as imaxes baixo demanda.
- Problema: Como cargar as imaxes baixo demanda sen complicar o resto do editor?
- Solución: Utilizar un obxecto proxy que se comporte como unha imaxe normal e que sexa o responsable de cargalas baixo demanda.
Aplicabilidade
O padrón proxy necesita dunha forma de referencia a un obxecto máis flexible que un punteiro. Dependendo da función que se desexe realizar con dita referencia pódense distinguir diferentes tipos de proxies:
- proxy remoto: representante local dun obxecto remoto.
- proxy virtual: crea obxectos custosos baixo demanda (como a clase ImageProxy do exemplo de motivación).
- proxy de protección: controla o acceso ao obxecto orixinal.
Estrutura
Participantes
- Proxy (ImageProxy)
Mantén unha referencia ao obxecto real (RealSubject).
Proporciona unha interface idéntica ao suxeito (Subject).
Controla o acceso ao obxecto real e pode ser o responsable da súa creación e borrado.
- Subject (Graphic)
Define a interface común de Proxy e RealSubject.
- RealSubject (Image)
Define o obxecto real.
Colaboracións
- Dependendo da clase de proxy, o obxecto proxy redirixe as peticións ao obxecto real que representa.
Consecuencias
O uso do proxy introduce un nivel de indirección adicional con diferentes usos:
- Un proxy remoto oculta o lugar onde reside un obxecto.
- Un proxy virtual realiza optimizacións como creación baixo demanda.
- Os proxies de protección permite realizar diversas tarefas de mantemento adicional ao acceder a un obxecto.
Implementación
public abstract class Suxeito {
public Suxeito(String nome) {
_nome = nome;
}
public String toString() {
return _nome;
}
public abstract void metodo1();
public abstract void metodo2();
private String _nome;
}
public class SuxeitoReal extends Suxeito {
public SuxeitoReal(String nome) {
super(nome);
}
public void metodo1() {
System.out.println("Executando metodo1 en " + this);
}
public void metodo2() {
System.out.println("Executando metodo2 en " + this);
}
}
public class Proxy extends Suxeito {
public Proxy(String nome) {
super(nome);
_accesos_metodo1 = 0;
_accesos_metodo2 = 0;
_suxeito_real = null;
}
private SuxeitoReal obterSuxeitoReal() {
if (_suxeito_real == null) {
_suxeito_real = new SuxeitoReal(this + " (Real)");
}
return _Suxeito_real;
}
public void metodo1() {
_accesos_metodo1++;
obterSuxeitoReal().metodo1();
}
public void metodo2() {
_accesos_metodo2++;
obterSuxeitoReal().metodo2();
}
public void status() {
if (_suxeito_real != null) {
System.out.println("Accesos a " + _suxeito_real +
": metodo1=" + _accesos_metodo1 +
", metodo2=" + _accesos_metodo2);
} else {
System.out.println("Suxeito Real (" + this + ") no creado.");
}
}
private SuxeitoReal _suxeito_real;
private int _accesos_metodo1, _accesos_metodo2;
}
public class Cliente {
public Cliente(Suxeito suxeito) {
_suxeito = suxeito;
}
public void executar() {
_suxeito.metodo1();
_suxeito.metodo1();
_suxeito.metodo2();
_suxeito.metodo1();
}
private Suxeito _suxeito;
}
public class Main {
public static void main(String[] argv) {
Proxy obxecto_a = new Proxy("obxecto_a");
Cliente c = new Cliente(obxecto_a);
obxecto_a.status();
c.executar();
obxecto_a.status();
SuxeitReal obxecto_b = new SuxeitoReal("obxecto_b");
Cliente d = new Cliente(obxecto_b);
d.executar();
}
}
Véxase tamén
Bibliografía
- E. Gamma, R. Helm, R. Johnson and J. Vlissides (1994). Design Patterns: elements of reusable object-oriented software. Addison-Wesley.