Proxy Pattern

  • Structural Design Patterns

Definition of Proxy: The authority to represent someone else, especially in voting.

What is the Proxy Pattern?

The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. The Surrogate or placeholder would be our Proxy Object that controls the access to another object. Each implement the same interface.

UML

"Insert Images"

The Client has no knowledge that it is iteracting with a Proxy vs. the Real Subject.

Different Types of Proxies:

  1. Remote Proxy
  2. Virtual Proxy
  3. Protection Proxy
  4. Smart Reference

Example of the Proxy Pattern

In my Example I have Stadium that allows two different type of fans/members, members and regular guests. Memebers receive a few perks like such as early access and access to the floor over normal guests.

UML

"Insert Images"

NBAFan Header File (NBAfan.h)

Here is a close up of the UML of an NBAfan

"Insert Images"

!"Insert Images"

#ifndef NBA_Fan_H_
#define NBA_Fan_H_

#include <string>

class NBAfan {

	private:
		std::string name_;

	public:
		NBAfan(std::string name) : name_(name) {}

		virtual ~NBAfan() {} // Deconstructor

		std::string GetName() { return name_; }

		virtual bool HasFloorSeatAccess() = 0;
		virtual bool HasEarlyAccess() = 0;
	
};

#endif /* NBA_Fan_H_ */

NBAGuest Header File (NBAGuest.h)

#ifndef NBAGUEST_H_
#define NBAGUEST_H_

#include "NBAfan.h"

class NBAGuest : public NBAfan {

	public:
		NBAGuest(std::string name);
		virtual ~NBAGuest();
		
		virtual bool HasFloorSeatAccess()
		{
			return false;
		}
		virtual bool HasEarlyAccess()
		{
			return false;
		}
};

NBAGuest::NBAGuest(std::string name) : NBAfan(name){}

NBAGuest::~NBAGuest() {}

#endif /* NBAGUEST_H_ */

NBAMember Header File (NBAMember.h)

#ifndef NBA_MEMBER_H_
#define NBA_MEMBER_H_

#include "NBAfan.h"

class NBAMember : public NBAfan {
	public:
		NBAMember(std::string name);
		virtual ~NBAMember();

		virtual bool HasFloorSeatAccess()
		{
			return true;
		}
		virtual bool HasEarlyAccess()
		{
			return true;
		}
};

NBAMember::NBAMember(std::string name) : NBAfan(name) {}

NBAMember::~NBAMember() {}

#endif /* NBA_MEMBER_H_ */

Stadium Header File (Stadium.h)

"Insert Images"

!"Insert Images"

#ifndef STADIUM_H_
#define STADIUM_H_

#include "NBAfan.h"

#include <iostream>


class NBAfan;

class Stadium {
	public:
		Stadium();
		virtual ~Stadium();

		virtual void EnterStadiumEarly(NBAfan * patron);
		virtual void AttendFloor(NBAfan * patron);
};

Stadium::Stadium() {} // constructor

Stadium::~Stadium() {}   // deconstructor

// members normally
void Stadium::EnterStadiumEarly(NBAfan * patron)
{
	std::cout << "Welcome, " << patron->GetName() << ", to our early access stadium hours\n";
}

void Stadium::AttendFloor(NBAfan * patron)
{
	std::cout << "Welcome, " << patron->GetName() << ", to the floor seats\n";
}

#endif /* STADIUM_H_ */

Stadium Interface Header File (StadiumIF.h)

!"Insert Images"

#ifndef STADIUMIF_H_
#define STADIUMIF_H_

class NBAfan;

class StadiumIF {
	public:
		virtual void EnterStadiumEarly(NBAfan * patron) = 0;
		virtual void Attendfloor(NBAfan * patron) = 0;
};

#endif /* STADIUMIF_H_ */

Stadium Proxy Header File (StadiumProxy.h)

#ifndef STADIUMPROXY_H_
#define STADIUMPROXY_H_

#include "StadiumProxy.h"
#include "Stadium.h"
#include "NBAfan.h"
#include <iostream>

class Stadium;
class NBAfan;

class StadiumProxy {
	public:
		StadiumProxy(Stadium * stadium);
		virtual ~StadiumProxy();

		virtual void EnterStadiumEarly(NBAfan * patron);
		virtual void AttendFloor(NBAfan * patron);

	private:
		Stadium * m_pstadium;
};

StadiumProxy::StadiumProxy(Stadium * stadium) : m_pstadium(stadium) {}

StadiumProxy::~StadiumProxy() {}

void StadiumProxy::EnterStadiumEarly(NBAfan * patron)
{
	if(patron->HasEarlyAccess())
	{
		m_pstadium->EnterStadiumEarly(patron);
	}
	else
	{
		std::cout << "Sorry, " << patron->GetName() << ", you don't have early stadium access privileges\n";
	}
}

void StadiumProxy::AttendFloor(NBAfan * patron)
{
	if(patron->HasFloorSeatAccess())
	{
		m_pstadium->AttendFloor(patron);
	}
	else
	{
		std::cout << "Sorry, " << patron->GetName() << ", you don't have access to the Floor Seats \n";
	}
}

#endif /* STADIUMPROXY_H_ */

Main File to Run (StadiumProxyTest.cpp)

!"Insert Images"

#include "Stadium.h"
#include "StadiumProxy.h"
#include "NBAMember.h"
#include "NBAGuest.h"

int main()
{
	NBAMember member(std::string("Devin"));
	NBAGuest guest(std::string("Noah"));
	NBAGuest guest2(std::string("Sarah"));
	NBAMember member2(std::string("Aaron"));


	Stadium stadium;			
	StadiumProxy stadiumProxy(&stadium);

	stadiumProxy.EnterStadiumEarly(&member);
	stadiumProxy.EnterStadiumEarly(&member2);

	stadiumProxy.EnterStadiumEarly(&guest);
	stadiumProxy.EnterStadiumEarly(&guest2);

	stadiumProxy.AttendFloor(&member);
	stadiumProxy.AttendFloor(&member2);

	stadiumProxy.AttendFloor(&guest);
	stadiumProxy.AttendFloor(&guest2);
}

Output

Welcome, Devin, to our early access stadium hours
Welcome, Aaron, to our early access stadium hours
Sorry, Noah, you don't have early stadium access privileges
Sorry, Sarah, you don't have early stadium access privileges
Welcome, Devin, to the floor seats
Welcome, Aaron, to the floor seats
Sorry, Noah, you don't have access to the Floor Seats 
Sorry, Sarah, you don't have access to the Floor Seats

Extra

  • Let’s just use the Regualr Stadium Interface to see how it interacts/works
#include "Stadium.h"
#include "StadiumProxy.h"
#include "NBAMember.h"
#include "NBAGuest.h"

int main()
{
	NBAMember member(std::string("Devin"));
	NBAGuest guest(std::string("Noah"));
	NBAGuest guest2(std::string("Sarah"));
	NBAMember member2(std::string("Aaron"));


	Stadium stadium;			
	StadiumProxy stadiumProxy(&stadium);

	// Lets just use the stadium Interface to interact
	stadium.AttendFloor(&member);
	stadium.AttendFloor(&guest);
    stadium.EnterStadiumEarly(&guest);
}

Output

Welcome, Devin, to the floor seats
Welcome, Noah, to the floor seats
Welcome, Noah, to our early access stadium hours