All notes
DesignPatter

FAQ

How to learn patterns

Reference: "pattern.pdf" by Martin Fowler.

Patterns are summarization of recurring methodologies to specific problems. So you should learn patterns by problems. Usually the pattern books talk about "how" to apply the patterns, but no "when" to apply them, while knowing "when" to apply "what" pattern, and what disadvantages it may bring is more important.

An expert in a field may learn little from patterns since the patterns are implicit in his/her experience. But patterns are still helpful for them in:

Catogories

Observer

A common side-effect of partitioning a system into a collection of cooperating classes is the need to maintain consistency between related objects. You don't want to achieve consistency by making the classes tightly coupled, because that reduces their reusability.

Sample codes

Observer

class Subject;
class Observer{
public:
	virtual ~ Observer();
	// The subject passed to the Update operation lets the observer determine which subject changed when it observes more than one.
	virtual void Update(Subject* theChangedSubject) = 0;
protected:
Observer();
};
Subject

class Observer;
class Subject {
public:
	virtual ~Subject();
	virtual void Attach(Observer*);
	virtual void Detach(Observer*);
	virtual void Notify();
protected:
	Subject();
private:
List<Observer*> *_observers;
};

//////////
// CPP
void Subject::Attach (Observer* o) { _observers->Append(o); }
void Subject::Detach (Observer* o) { _observers->Remove(o); }
void Subject::Notify () {
	ListIterator<Observer*> i(_observers);
	for (i.First(); !i.IsDone(); i.Next()) {
		i.CurrentItem()->Update(this);
	}
}
Subject: ClockTimer

class ClockTimer : public Subject {
public:
	ClockTimer();
	virtual int GetHour();
	virtual int GetMinute();
	virtual int GetSecond();
	void Tick();
};

/////////
//CPP.
void ClockTimer::Tick () {
	// update internal time-keeping state
	// ...
	Notify();
}
Observer: DigitalClock

class DigitalClock: public Widget, public Observer {
public:
	DigitalClock(ClockTimer*);
	virtual ~DigitalClock();
	virtual void Update(Subject*);
    // overrides Observer operation
private:
	virtual void Draw();
    // overrides Widget operation; defines how to draw the digital clock
	ClockTimer* _subject;
};

DigitalClock::DigitalClock (ClockTimer* s) {
	_subject = s;
	_subject->Attach(this);
}
DigitalClock:: DigitalClock () {
	_subject->Detach(this);
}

void DigitalClock::Update (Subject* theChangedSubject) {
	if (theChangedSubject == _subject) {
		Draw();
	}
}
void DigitalClock::Draw () {
	// get the new values from the subject
	int hour = _subject->GetHour();
	int minute = _subject->GetMinute();
	// etc.
	// draw the digital clock
}

Delegation

Wikipedia: delegation pattern.

In delegation, an object handles a request by delegating to a second object, the delegate (a helper object), but with the original context.

With language-level support for delegation, this is done implicitly by having self in the delegate refer to the original (sending) object, not the delegate (receiving object). In the delegate pattern, this is instead accomplished by explicitly passing the original object to the delegate, as an argument to a method.

In Gamma et al. 1994, delegation is defined as:

Delegation is a way to make composition as powerful for reuse as inheritance [Lie86, JZ91]. In delegation, two objects are involved in handling a request: a receiving object delegates operations to its delegate. This is analogous to subclasses deferring requests to parent classes. But with inheritance, an inherited operation can always refer to the receiving object through the this member variable in C++ and self in Smalltalk. To achieve the same effect with delegation, the receiver passes itself to the delegate to let the delegated operation refer to the receiver.

SO: what is the purpose of a delegation pattern. It is useful in a number of scenarios, and is a base for other patterns:

As per effective Java (by Joshua Blosch), composition is favorable over inheritance. Composition has several advantages over inheritance. One of the intuitions for this is as follows: Consider a sub-class which inherits from a base class. So any change in the base class will make the sub-class fragile as the sub-class depends on the base class. so by using inheritance, we are making a binding on the sub-class to depend on the base class, which makes our code fragile. By using composition, we can remove this limitation. Composition is done by establishing a 'has-a relationship' between classes instead of 'is-a' relationship as in inheritance. 'Delegate pattern' and 'Decorator pattern' both are examples of how composition can be achieved.

Reactor, Proactor

"In particular, his (ACE) Reactor is an OO way of doing nonblocking I/O, and Proactor is an OO way of doing asynchronous I/O."

Pimpl, opaque pointer

This technique is described in Design Patterns as the Bridge pattern. Other names include: "handle classes", the "Pimpl idiom" (for "pointer to implementation idiom"), "Compiler firewall idiom" or "Cheshire Cat", especially among the C++ community. Ref.

An example from Ref:

//header file:
class Handle {
public:
	Handle();						  // Constructor
	Handle(const Handle&);			  // Copy constructor
	Handle(Handle&&);				  // Move constructor
	Handle& operator=(const Handle&); // Copy assignment operator
	~Handle();						  // Destructor
	// Other operations...
 
private:
	struct CheshireCat;				  // Not defined here
	CheshireCat* smile;				  // Handle
};
//CPP file:
#include "handle.h"
 
struct Handle::CheshireCat {
	int a;
	int b;
};
 
Handle::Handle()
	: smile(new CheshireCat()) {
	// do nothing
}
 
Handle::Handle(const Handle& other)
	: smile(new CheshireCat(*other.smile)) {
	// do nothing
}
 
Handle::Handle(Handle&& other) 
	: smile(0)
{
	std::swap(smile, other.smile);
}
 
Handle& Handle::operator=(const Handle &other) {
	if(this != &other) {
		*smile = *(other.smile);
	}
	return *this;
}
 
Handle::~Handle() {
	delete smile;
}
The design has the following advantages:
  1. more of the class implementation is hidden from view
  2. adding new data members to the private struct does not affect binary compatibility;
  3. the header file containing the class declaration only needs to include those other files needed for the class interface, rather than for its implementation.
  4. One side benefit is that compilations are faster because the header file changes less often.
The design is heavily used in the Qt and KDE libraries.

CORBA

Short for Common Object Request Broker Architecture.

Introduction

CORBA uses an interface definition language (IDL) to specify the interfaces that objects present to the outer world.
Standard mappings (from IDL to a specific implementation lang) exist for Ada, C, C++, C++11, COBOL, Java, Lisp, PL/I, Python, Ruby and Smalltalk. Non-standard mappings exist for C#, Erlang, Perl, Tcl and Visual Basic implemented by object request brokers (ORBs) written for those languages.
A specialization of GIOP is the Internet Inter-ORB Protocol or IIOP. IIOP uses raw TCP/IP connections in order to transmit data. Most modern firewalls support GIOP & IIOP and are thus CORBA-friendly firewalls.
D-Bus open source IPC program provides similar function to CORBA.