The Proxy design pattern allows to define a “proxy” class which will act as a wrapper object which will be called by the client to access the product object without exposing the details. This proxy class can also be used to add extra functionality without changing the product behavior. This design pattern can be used in cases to provide additional security access to an existing product or providing an interface for remote resources. For Design patterns basic explanation see (Design Patterns Simplified Version).
Generic model class diagram of Proxy design pattern is as shown in image.
This design pattern is majorly used in cases where “Reference counting” mechanism is needed to add in the object code without modifying actual product code. This pattern can be modified to incorporate “Flyweight pattern” to reduce memory footprint of the product. This pattern can also be used in cases where deadlock feature needs to be added in any existing class without modifying the existing product’s code.
Proxy Design Pattern Code Example:
Let’s take an example of Election system where every person aged more than 25 years are allowed to cast their vote to choose the leader of their country. Since, each country has their own age limit for voting thus the same product code can be applied in all the countries by introducing a proxy or wrapper class in which we will have to handle this age-limit criteria. Rest all of functionality of the classes will remain same. Class diagram for the solution of above problem is as shown in below image.
Let’s have a look on the class definition of all product classes which will be as follows:
/* Real Object Class */ class Election { public: void vote() { cout<<"Voting power exercised "<<endl; } }; class Person { private: int m_age; public: Person(int age): m_age(age){} int getAge() { return m_age; } };
Now, Let’s have a look on the proxy class which will handle the security issue of checking a person’s age for casting vote.
/* Proxy Class */ class ProxyElection { private: Election m_election; Person* m_person; public: void castVote() { if (m_person->getAge() > 25 ) { m_election.vote(); } else { cout<<"Voter is too young to cast vote"<<endl; } } ProxyElection(Person* person): m_person(person) {} };
Let’s see now how to use the above described classes to build the final product. Below code is sample “main” function code.
int main() { Person p1(21); Person p2(35); Person p3(46); ProxyElection pe1(&p1); ProxyElection pe2(&p2); ProxyElection pe3(&p3); pe1.castVote(); pe2.castVote(); pe3.castVote(); }
Output of the above given example:
Voter is too young to cast vote Voting power exercised Voting power exercised