Monday, November 16, 2015

The Proxy design pattern

In the previous tutorial we presented the facade design pattern. The facade pattern, along with the adapter (which was presented earlier), the proxy (this post) the decorator and bridge patterns (coming soon), are all essentially wrapping certain functionality and provide a different interface. The difference between them is in their intent.

The proxy design pattern is a structural one where a class (proxy) is used to represent and allow access to the functionality of another class. The proxy is often used to add behavior in certain functionality, to protect the class that is being proxied so it is not accessed and in general to control the access to a class. Motivations for its use can be that the proxied class is costly, and for creating intelligent and distributed access to the proxied class. The proxy class can substitute the class that it proxies.

In order to provide a simple tutorial and showcase the proxy pattern we will use the case of a company that helps agoraphobic people with their chores. Below is depicted the UML class diagram of the tutorial:

First we will create the an interface with a single method 'doChores()' which we all have to implement.
package com.tasosmartidis.design_patterns_tutorial.proxy;

public interface ChoreDoer {

    public void doChores();
}


Next we have the AgoraphobicPerson class who does chores but does not like to go out of the house. Also there is a method skypeWithFamily which for the purposes of the tutorial is considered to be costly and we do not want our proxy to provide access to it, as shown in the source code below:
package com.tasosmartidis.design_patterns_tutorial.proxy;

import java.util.Arrays;
import java.util.List;

public class AgoraphobicPerson implements ChoreDoer {
    private List<String> chores = Arrays.asList(new String[]{"grocery shopping" ,"taxes", "dog walking"});
    
    @Override
    public void doChores() {
        System.out.println("Getting my chores done while home!");
        for(String chore : chores) {
            System.out.println("Chore: " + chore);
        }
    }

    // Fun but let's say costly operation
    public void skypeWithFamily() {
        System.out.println("Skyping with family from home!");
    }
}


But our agoraphobic person will use a proxy for doing its chores and the ProxyAgent class of the agency in our scenario does that and also provides additional functionality, such as premium services with detailed report of the chore expenses:
package com.tasosmartidis.design_patterns_tutorial.proxy;

public class ProxyAgent implements ChoreDoer {

    private AgoraphobicPerson client;
    
    public ProxyAgent(AgoraphobicPerson client) {
        this.client = client;
    }
    
    @Override
    public void doChores() {
        this.client.doChores();
    }
    
    // Adding some extra functionality to provide report of the expenses
    public void doChoresExtra() {
        this.client.doChores();
        System.out.println("Providing detailed report of the chores made by agent!");
    }

}


Let's now use the proxy class to do the chores for the agoraphobic person in our demo
package com.tasosmartidis.design_patterns_tutorial.proxy;

public class ProxyDemo {

    public static void main(String[] args) {
        AgoraphobicPerson client = new AgoraphobicPerson();     
        ProxyAgent agent = new ProxyAgent(client);
        
        // Let's do the chores for our agoraphobic client via the proxy
        System.out.println("Basic services:");
        agent.doChores();
        
        System.out.println();
        
        // And provide the premium chore services
        System.out.println("Premium services:");
        agent.doChoresExtra();
    }
}


And running the demo gives us the following results:
















And this concludes our brief tutorial on the proxy design pattern! The code is available on GitHub.

No comments:

Post a Comment