C++ Proxy Pattern Example

1. Definition

The Proxy Design Pattern provides a surrogate or placeholder for another object to control access to it. Essentially, it acts as an intermediary between a client and the real object.

2. Problem Statement

You want to control access to an object, either to delay its creation, to represent it remotely, or to add some access control mechanism, without changing the object's code.

3. Solution

Introduce a new proxy class with the same interface as the original service object. When a proxy receives a request, it passes the request to the service object after either handling some tasks or checking whether the request should be processed.

4. Real-World Use Cases

1. Virtual proxies: Delay the creation and initialization of expensive objects until they're needed.

2. Remote proxies: Represent objects that are in a different address space.

3. Protection proxies: Control access to the original object based on permissions.

5. Implementation Steps

1. Define an interface that both the RealObject and Proxy will implement.

2. Create the RealObject that implements the aforementioned interface.

3. Create the Proxy class which also implements the interface and maintains a reference to the RealObject.

4. The Proxy will control the access to the RealObject, and when deemed necessary, forward the request to it.

6. Implementation in C++

// Step 1: Define the interface
class IObject {
public:
    virtual void request() const = 0;
    virtual ~IObject() {}
};
// Step 2: Implement the RealObject
class RealObject : public IObject {
public:
    void request() const override {
        std::cout << "RealObject: Handling request." << std::endl;
    }
};
// Step 3: Implement the Proxy
class Proxy : public IObject {
private:
    RealObject* realObject;
public:
    Proxy() : realObject(new RealObject()) {}
    ~Proxy() { delete realObject; }
    void request() const override {
        std::cout << "Proxy: Checking access prior to firing a request." << std::endl;
        realObject->request();
    }
};
int main() {
    IObject* proxy = new Proxy();
    proxy->request();
    delete proxy;
    return 0;
}

Output:

Proxy: Checking access prior to firing a request.
RealObject: Handling request.

Explanation:

1. The IObject interface defines a method called request.

2. RealObject is the actual object that performs the real operations.

3. Proxy maintains a reference to a RealObject. Before it forwards the request to the RealObject, it might check permissions or lazy initialize the RealObject.

4. In the main function, a Proxy object is created and the request is made through it. The proxy first checks access and then delegates the request to the RealObject.

7. When to use?

Use the Proxy pattern when:

1. You need a more versatile or sophisticated reference to an object than a simple pointer.

2. You want to lazy initialize an object.

3. You need to control access to the actual object for reasons like security, logging, or any other form of access control.

4. You want to work with an object that resides in a different address space, and you need to represent it locally (e.g., remote proxies).


Comments