The idea behind the proxy design pattern is to have a class, which in some way facilitates or optimises access to an underlying object. At the same time, the proxy class has the same interface as the underlying object, so it can be substituted for it.
Proxy pattern can be used for accessing remote resources, authentication or using performance heavy objects. The underlying implementation can be different, but the result should be the same.
Nothing illustrates it better than a good sample of proxy pattern code:
interface TrainScheduleProviderInterface { public List getTrains(String origin, String destination); } pubic class TrainScheduleProvider extends TrainScheduleProviderInterface{ private final RailProvider railProvider; public TrainScheduleProvider(RailProvider railProvider) { this.railProvider = railProvider; this.railProvider.connect(); // early connection initialization } public List getTrains(String origin, String destination) { return railProvider.getTrains(origin, destination) //heavy network call } } public class NationalLazyTrainScheduleProvider extends TrainScheduleProviderInterface { private TrainScheduleProvider trainScheduleProvider; private final Map<String,List> trainSchedule = new HashMap<>(); public List getTrains(String origin, String destination) { if (trainSchedule.contains(origin+destination)) { return trainSchedule(origin+destination); } else { if (trainScheduleProvider == null) { trainScheduleProvider = new TrainScheduleProvider(new NationalScheduleProvider())} return trainScheduleProvider.getTrains(origin, destination) } } }
In the sample code for proxy pattern, we create a proxy wrapper around the TrainScheduleProvider. TrainScheduleProvider allows to lookup trains connection, but the API requires constant internet connection and make a call every time the train schedule is requested.
Luckly, the TrainScheduleProvider uses an interface. Our NationalLazyTrainScheduleProvider caches the schedules in memory, so there is no need to make a new call to distant schedule provider, if somebody has made the same call just a minute ago.
What’s more, the proxy does not start the connection to schedule provider until, somebody makes the first request (one could imagine that the connection is closed after certain time of inactivity).
All these benefits come with the same API as the resource expensive basic TrainScheduleProvider class.