Interesting patterns: Proxy

Imagine a class which wraps an external API or read large files or parses huge XML files, fetches data from the Internet or something else. There are thousands of situations like that.

In many cases, you can want to not parse/download/load some resources every time, right?. A good option is to use a cache but, to be honest, it’s difficult. In this article, I’ll show you a simple and flexible solution.

The proxy – this is an answer. The best way to explain is to show an example. You can see a simple class below which fetches some information from external API.

package guru.iamcode.patterns.api;
import guru.iamcode.patterns.ApiRequests;
import guru.iamcode.patterns.Client;
import guru.iamcode.patterns.Order;
import java.util.ArrayList;

public class SomeExternalAPI extends ApiRequests {
    public ArrayList<Order> getLastOrders(int limit)
    {
        return (ArrayList<Order>)get("/v1/orders/latest?limit=" + limit);
    }
    public Client getClientInformation(int clientId)
    {
        return (Client)get("/v1/client/" + clientId);
    }
}

The information doesn’t change very often so it would be handy to cache it somewhere to decrease network consumption. We can achieve it in a few ways. The particulars steps you can find below.

Extend the base class

Extending the base class has one key advantage: you can easily replace the base class because both have identical interfaces. Moreover, you don’t have to implement all of the methods – just the one you need to. Great, right?

package guru.iamcode.patterns.api;
import guru.iamcode.patterns.Cache;
import guru.iamcode.patterns.Order;
import java.util.ArrayList;

public class APIOverrideProxy extends SomeExternalAPI {
    Cache cache;
    public APIOverrideProxy(Cache cache) {
        this.cache = cache;
    }
    @Override
    public ArrayList getLastOrders(int limit)
    {
        if (cache.has("last_order_" + limit)) {
            return (ArrayList)cache.get("last_order_" + limit);
        }
        ArrayList Orders = super.getLastOrders(limit);
        cache.put("last_order_" + limit, Orders);
        return Orders;
    }
}

 

Create an instance of the class in the proxy class

The biggest difference between APIDependencyProxy and APIOverrideProxy classes you get an instance of the object in a constructor or setter. It’s required to implement the same interface as SomeExternalAPI does but it gives you another advantage. Because you are not fixed to a specific interface. Thanks to that you can add more dependencies and rebuild it completely.

package guru.iamcode.patterns.api;
import guru.iamcode.patterns.Cache;
import guru.iamcode.patterns.Order;
import java.util.ArrayList;

public class APIDependencyProxy {
    private Cache cache;
    private SomeExternalAPI api;
    public APIDependencyProxy(Cache cache, SomeExternalAPI api) {
        this.cache = cache;
        this.api = api;
    }
    public ArrayList getLastOrders(int limit)
    {
        if (cache.has("last_order_" + limit)) {
            return (ArrayList)cache.get("last_order_" + limit);
        }
        ArrayList Orders = api.getLastOrders(limit);
        cache.put("last_order_" + limit, Orders);
        return Orders;
    }
}

Create an instance of the base class if needed

Sometimes creating an object can be expensive and not necessarily required. Proxy is a great place to decide which implementation should be used or if the instance is created at all.

Summary

As you can see, ways of solving the problem can be many. I hope that I’ve given you a lot of inspiration and “A” for your “Q”.What do you think about the above I prepared? Do you have interesting examples of the Proxy Pattern and want to share them with us? I’m waiting for your comments.

Hi, I'm Bartek, founder of this blog. I am a developer since 2011. I love learning by teaching other people and this is my motivation for creating this website.
Posts created 16

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top