Intent
Proxy pattern provides a surrogate or placeholder for another object to control access to it. This help control the access to the real object. You can think of proxy to real object as puppet to the person who is in real power.
Motivation
Suppose you have a small file to read, ~100 lines, the naive approach to read the file and process may look similar to the following Pseudocode:
for line in readFile("filename.ext"):
process(line)
Since the file is not large, this solution may work fine.
However, if the requirements changed:
- The file is pretty large. ~ 1M lines
- The processing may last for the entire file or a few lines and then stops
Will the above solution still on the table? I personally doubt.
There is a better concept for this, which is called iterator
. Behind the scenes, it introduces another concept which is similar to the meaning, lazy loading, where this may be more popular in Front-end development.
Lazy loading is the practice of delaying load or initialization of resources or objects until they’re actually needed to improve performance and save system resources.
Similarly, we can apply this “idea” when we do for object creation, and only forward the request to the real object when client’s code wanna retrieve or alter something.
Another good example is in the Gang of Four - Design Patterns book:
When you are developing a text editor, like Microsoft Word or Markdown editor. You can upload and change the image during the editor. But you dont wanna create all the objects that refer to the image creation, updates, etc.
What you can do is that use an ImageProxy
which pretends to be a real image, but not, and forward a display
request or crop
request to the real image when these methods are invoked.
For a pretty expensive object, during creation, we can do the creation on demand - lazy initialization.
This “expensive object”could also be a third-party library or tools, like a local DynamoDB container. (?)
Applicability
There are four different types of Proxy pattern:
- Remote proxy
- provides a local representative of an object in a different address space.
- one example which gives the feeling similar to this proxy pattern is the local version of AWS DynamoDB. though this may not the perfect example
- provides a local representative of an object in a different address space.
- Virtual Proxy
- creates expensive objects on demand
- delays the time creating the object, only create when you need communicate with the real object
- creates expensive objects on demand
- Protection Proxy
- controls access to the real object
- no detailed example on code level. However, I think AWS Bastion Host has some similarity to this type of Proxy pattern. => to communicate with the production server, you need to pass the Bastion Host “proxy”. though this may not the perfect example
- controls access to the real object
- Smart reference
- checking the reference to the real object so that it could be freed automatically when no references to it =? smart pointers
- loading a persistent object into memory when it is first referenced => Caching Proxy