Proxy - shoonie/StudyingDesignPattern GitHub Wiki

Intent

Provide a surrogate or placeholder for another object to control access to it.

Diagram

disgram

Consequences

The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy.

  1. A remote proxy can hide the fact that an object resides in a different address space.
  2. A virtual proxy can perform optimizations such as creating an object on demand.
  3. Both protection proxies and smart references allow additional housekeeping tasks when an object is accessed.

Implementation

  1. Overloading the member access operator in C++ (operator -> and * operator)
class Image;
extern Image* LoadAndImageFile(const char*);
//external function
class ImagePtr
{
public:
	ImagePtr(const char* imageFile);
	virtual ~ImagePtr();

	virtual Image* operator->();
	virtual Image& operator*();
private:
	Image * LoadImage();
private:
	Image * _image;
	const char* _imageFile;
};

ImagePtr::ImagePtr(const char* imageFile)
{
	_imageFile = imageFile;
	_image = nullptr;
}
ImagePtr::~ImagePtr()
{
	if (_image != nullptr)
		delete _image;
}
Image*  ImagePtr::LoadImage()
{
	if (_image == nullptr)
	{
		_image = LoadAndImageFile(_imageFile);
	}
	return _image;
}
// overload -> and * operator use LoadImage to return _image to caller(loading if necessary)
Image* ImagePtr::operator->()
{
	return LoadImage();
}

Image& ImagePtr::operator*()
{
	return *LoadImage();
}
// This approach lets you call Image operations through ImagePtr objects without 
// going to the trouble of making the opertation part of the ImagePtr interface:
ImagePtr image = ImagePtr("anImageFilename");
image->Draw(Point(50,100));
 //(image.operator->())->Draw(Point(50,100));
// Notice how the image proxy acts like a pointer, but it's not declared to be a pointer to an Image.
// That means you can't use it exactly like a real pointer to an Image. Hence clients must treat Image and 
// ImagePtr objects differently in this approach.
  1. Proxy doesn't always have to know the type of real subject. If a Proxy class can deal with its subject solely through an abstract interface, then there's no need to make a Proxy class for each RealSubject class; the proxy can deal with all Realsubject classes uniformly.

Sample Code

#include<iostream>
#include<string>

using namespace std;

class IBank
{
public:
	virtual string WithDrawCash(void) = 0;
	virtual ~IBank() {}
};

class ActualBank : IBank
{
public:
	string WithDrawCash(void)
	{
		return "Here, have a million Zimbabwean dollars.\n\n";
	}
};

class Bank : public IBank
{
	ActualBank* _bank;
	string _password;
public:
	Bank() :_bank(nullptr), _password("WhoWhatWhere") {}

	string WithDrawCash(void)
	{
		if (_bank == nullptr)
			return "\nDid you authenticate?\n";
		return _bank->WithDrawCash();
	}

	void Authenticate(string passwd)
	{
		if (_password == passwd)
		{
			cout << "\nYou have been authenticated.\n\n";
			_bank = new ActualBank();
		}
		else
		{
			cout << "\nSorry but wrong.\n";
		}
	}

	~Bank()
	{
		if(_bank!=nullptr)
			delete _bank;
	}
};

int main()
{
	Bank* daddysBank = new Bank();
	cout << daddysBank->WithDrawCash();
	daddysBank->Authenticate("Hello");
	daddysBank->Authenticate("WhoWhatWhere");
	cout << daddysBank->WithDrawCash();
	return 1;
}
⚠️ **GitHub.com Fallback** ⚠️