Skip to content

Proxy

Proxy is one of the structural patterns that, in terms of authoring, has a similar structure to Decorator. This pattern adds a layer between the interface and the specific implementation. This layer, depending on the type of proxy we implement, may fulfill a different function.

proxy

We can distinguish several types of proxies. Some of them are:

  • remote, the purpose of which is to represent an object located in another space (e.g. a remote machine)
  • virtual, which can be used as a cache for an object reference
  • security, which adds a layer of security to the object

A proxy object should implement the same interface as the object it wraps. Very often the end user of an interface does not know that he uses a proxy, which also means that a proxy can hide some implementation details.

The following example shows a simple implementation of the Proxy pattern of type remote. The user uses the Image interface to display images, and the proxy hides their source (disk or Internet), additionally ensuring lazy loading (only when the client wants to display them).

The example consists of the following classes:

  • Image - represents the image interface that the client uses
  • RemoteImage - interface representing remote image - proxy uses it to lazy loading
  • DiskImage, InternetImage - specific implementations of images
  • ImageProxy - The 'proxy' used by the client, hides the image source and ensures lazy loading
class Image:
    def show(self):
        pass
class RemoteImage(Image):
    def load_from_source(self):
        pass

    def is_loaded(self):
        pass
class DiskImage(RemoteImage):
    def load_from_source(self):
        pass

    def is_loaded(self):
        pass

    def show(self):
        pass
class InternetImage(RemoteImage):
    def load_from_source(self):
        pass

    def is_loaded(self):
        pass

    def show(self):
        pass
class ImageProxy(Image):
    def __init__(self, remote_image):
        self._remote_image = remote_image

    def show(self):
        if not self._remote_image.is_loaded():
            self._remote_image.load_from_source()
        return self._remote_image.show()
def main():
    disk_image_proxy = ImageProxy(DiskImage())
    internet_image_proxy = ImageProxy(InternetImage())
                                # the user only uses the Image interface
    disk_image_proxy.show()     # the proxy only loads the image when it is needed
                                # the picture from the Internet is never loaded


if __name__ == '__main__':
    main()