Real World Example
Have you ever used an access card to go through a door? There are multiple options to open that door i.e. it can be opened either using access card or by pressing a button that bypasses the security. The door’s main functionality is to open but there is a proxy added on top of it to add some functionality. Let me better explain it using the code example below.
In Plain Words
Using the proxy pattern, a class represents the functionality of another class.Wikipedia Definition
A proxy, in its most general form, is a class functioning as an interface to something else. A proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked.
Programmatic Example
Taking our security door example from above. Firstly we have the door interface and an implementation of door:Additional Example: Data Mapper
Yet another example would be some sort of data-mapper implementation. For example, I recently made an ODM (Object Data Mapper) for MongoDB using this pattern where I wrote a proxy around mongo classes while utilizing the magic method__call(). All the method calls were proxied to the original mongo class and result retrieved was returned as it is but in case of find or findOne data was mapped to the required class objects and the object was returned instead of Cursor.
Key Participants
Subject
Subject
Defines the common interface for RealSubject and Proxy (in our example:
Door interface)Real Subject
Real Subject
The real object that the proxy represents (in our example:
LabDoor)Proxy
Proxy
Maintains a reference to the Real Subject and controls access to it (in our example:
SecuredDoor)Client
Client
Works with objects through the Subject interface
Types of Proxies
- Protection Proxy
- Virtual Proxy
- Remote Proxy
- Caching Proxy
Controls access to the original object. Useful when you need different access rights.
When to Use?
Use the Proxy pattern when:
- You need lazy initialization (virtual proxy)
- You need access control (protection proxy)
- You need a local representative for a remote object (remote proxy)
- You need to add additional logic before/after method calls
- You want to cache expensive operations (caching proxy)
- You need logging, monitoring, or instrumentation
Benefits
- Control: Controls access to the real object
- Lazy Initialization: Can delay expensive object creation
- Access Control: Can enforce security and access rights
- Additional Logic: Can add logging, caching, etc. without modifying the real object
- Open/Closed Principle: Can introduce new proxies without changing the service or clients
Proxy vs Similar Patterns
- Proxy vs Adapter
- Proxy vs Decorator
- Proxy vs Facade
Proxy: Provides the same interface as the real objectAdapter: Provides a different interface
Real-World Applications
ORM Frameworks
Lazy loading of database relations
API Clients
Remote proxies for web services
Image Loading
Virtual proxies for large images
Access Control
Protection proxies for secure resources
Implementation Example: Lazy Loading
Considerations
Related Patterns
- Adapter: Proxy provides the same interface; Adapter provides a different interface
- Decorator: Decorator adds responsibilities; Proxy controls access
- Facade: Facade provides simplified interface to subsystem; Proxy provides same interface as real object