Virtual Proxy Pattern

It controls the access to a resource that is expensive to create, for instance data for object creation have to be retrieved from a network.

Bates and SierraHead First Design Patterns

Scenario. The client has to interact with an object which is very expensive to create.

Virtual proxy. The proxy hides the complexity of creating an managing the real subject. Moreover the proxy could handle the request by itself or creates the expensive object and directly delegate to it the request.

Proxy in action. The proxy acts as a surrogate for the real object before and while it is created.

##Example Each contact of an address book has some details such as the name, surname, address and a picture. The picture should always be up to date, for this reason must be retrieved from the network or from a database. The creation of the picture is expensive involving a connection.

The proxy will control how the picture is retrieved without blocking the main application.

/images/posts/design-patterns/virtual_proxy_example.png

Implementing the same interface, Picture, ProxyPicture can be used in place of ContactPicture so the client will use an instance reference of type Picture without knowing that it is a proxy.

Start

When the system starts will create a proxy which will be passed to the client, the Contact class. Calling toString() method the first time will start the retrieval process.

public class AddressBook {
	public static void main(String[] args) {
		new AddressBook().run();
	}

	public void run() {
		NetworkService ns = new NetworkServiceImpl();
		Contact contact = new Contact(new PictureProxy(ns));
		System.out.println(contact.toString());
	}
}

###The Client It gets a reference of type Picture thinking to be the real object, but it is the proxy.

public class Contact {

	private Picture picture;

	public Contact(Picture p) {
		picture = p;
	}

	@Override
	public String toString() {
		if (picture.getName() == null) {
			return "picture is going to be retrieved...";
		} else {
			return picture.getFormat() + " " + picture.getName() + " " + new String(picture.getImage());
		}
	}
}

###The Proxy It wraps the real object. At the first method call, the proxy will start a thread to retrieve the data and return a null value until data are not available then it builds the real object it wraps. Once the proxy will have the data it will directly answer to the client.

import java.net.MalformedURLException;
import java.net.URL;

public class PictureProxy implements Picture {

	private ContactPicture contactPicture;
	private boolean isRetrieving;
	private NetworkService networkService;

	public PictureProxy(NetworkService ns) {
		networkService = ns;
	}

	@Override
	public String getName() {
		if (contactPicture == null) {
			retrieveImage();
		} else {
			contactPicture.getName();
		}
		return null;
	}

	@Override
	public String getFormat() {
		// some code
	}

	@Override
	public byte[] getImage() {
		// some code
	}

	private void retrieveImage() {
		if (!isRetrieving) {
			isRetrieving = true;
			Thread thread = new Thread(new Runnable() {
				@Override
				public void run() {
					try {
						contactPicture = new ContactPicture("john picture", 
							"png", networkService.getImage(new URL("http://imagerepo.com")));
						System.out.println("picture retrieved");
					} catch (MalformedURLException e) {
						e.printStackTrace();
					}
				}
			});
			thread.start();
		}
	}
}