Strukturalny wzorzec projektowy Proxy, jego zadaniem jest zbudowanie klasy, która zastępuje/emuluje zachowanie innego klasy/obiektu Jest to jeden z najprostszych wzorców projektowych, bardzo często niepozornie siedzący w kodzie.

Zastosowanie takiej kombinacji gdzie jeden obiekt zastępuje inny obiekt jest:

  • Kontrola dostępu do ochranianego obiektu – np. dostęp do danych po autoryzacji użytkownika
  • Opóźnienie tworzenia kosztownego obiektu, obiekt jest tworzony kiedy to jest niezbędne – tworzenie na żądanie
  • Emulacja zdalnego obiektu, np.: dane obiektu przesyłane są przez internet
  • Cachowanie pewnych danych obiektu – niektóre dane klasy długo się generują, albo są przeliczane wcześniej
  • Dodatkowe operacje wykonywane przy dostępie do obiektu np.: zliczanie ilości referencji, czy tzw. Sprytne wskaźniki

Proxy jest w założeniu bardzo prostym wzorcem, ale umożliwia realizowanie dodatkowych zadań, które nie były przewidziane w interfejsie emulowanego obiektu.

Przykładowa implementacja, klasa dostarcza wygenerowane obrazy, przy pierwszym wywołaniu dostarczone są tylko grafiki poglądowe – generowanie właściwych wymaga bardzo dużo mocy obliczeniowej.

package pl.shad.net.blog;
 
/**
 * Interfejs dostępu do danych
 */
interface ImageInterface{
	String getImage();
}
 
/**
 * Główna klasa generująca dane
 */
class Image implements ImageInterface{
 
	@Override
	public String getImage(){
		return "HiRes image data ...";
	}
}
 
/**
 * Klasa proxy, przy pierwszym wywołaniu
 * daje dane poglądowe
 */
class ProxyImage implements ImageInterface{
 
	private Image image;
	private int counter = 0;
 
	@Override
	public String getImage(){
 
		counter++;
		if (counter > 1){
			if (image == null){
				image = new Image();
			}
			return image.getImage();
		}
		return "LoRes proxy thumbnail ...";
	}
}
 
/**
 * Testowa klasa uruchomieniowa
 */
public class DesignPatternsProxy{
 
	public static void main(String[] args){
 
		//
		// Odwołania do głównego obiektu bez użycia proxy
		//
		ImageInterface image = new Image();
		System.out.println("Object without proxy:");
		System.out.println("First access: " + image.getImage());
		System.out.println("Second access: " + image.getImage());
 
		//
		// Odwołania do głównego obiektu z użyciem obiektu proxy
		//
		image = new ProxyImage();
		System.out.println("Object with proxy:");
		System.out.println("First access: " + image.getImage());
		System.out.println("Second access: " + image.getImage());
	}
}