C++: Delegates

Bjarne-stroustrup
 

A delegate is a helper object used by another object. The delegator may send the delegate certain messages, and provide a default implementation when there is no delegate or the delegate does not respond to a message. This pattern is heavily used in Cocoa framework on Mac OS X. See also wp:Delegation pattern.

Objects responsibilities:

Delegator:

  • Keep an optional delegate instance.
  • Implement “operation” method, returning the delegate “thing” if the delegate respond to “thing”, or the string “default implementation”.

Delegate:

  • Implement “thing” and return the string “delegate implementation”

Show how objects are created and used. First, without a delegate, then with a delegate that does not implement “thing”, and last with a delegate that implements “thing”.

Delegates in the C# or D style are available in C++ through std::tr1::function class template. These delegates don’t exactly match this problem statement though, as they only support a single method call (which is operator()), and so don’t support querying for support of particular methods.

#include <tr1/memory>
#include <string>
#include <iostream>
#include <tr1/functional>

using namespace std;
using namespace std::tr1;
using std::tr1::function;

// interface for all delegates
class IDelegate
{
public:
	virtual ~IDelegate() {}
};

//interface for delegates supporting thing 
class IThing
{
public:
	virtual ~IThing() {}
	virtual std::string Thing() = 0;
};

// Does not handle Thing
class DelegateA : virtual public IDelegate
{
};

// Handles Thing
class DelegateB : public IThing, public IDelegate
{
	std::string Thing()
	{
		return "delegate implementation";
	}
};

class Delegator
{
public:
	std::string Operation()
	{
		if(Delegate) //have delegate
		if (IThing * pThing = dynamic_cast<IThing*>(Delegate.get()))
		//delegate provides IThing interface
		return pThing->Thing();

		return "default implementation";
	}

	shared_ptr<IDelegate> Delegate;
};

int main()
{
	shared_ptr<DelegateA> delegateA(new DelegateA());
	shared_ptr<DelegateB> delegateB(new DelegateB());
	Delegator delegator;

	// No delegate
	std::cout << delegator.Operation() << std::endl;

	// Delegate doesn't handle "Thing"
	delegator.Delegate = delegateA;
	std::cout << delegator.Operation() << std::endl;

	// Delegate handles "Thing"
	delegator.Delegate = delegateB;
	std::cout << delegator.Operation() << std::endl;

	/*
Prints:

default implementation
default implementation
delegate implementation
*/
}

SOURCE

Content is available under GNU Free Documentation License 1.2.