Patterns and Idioms

Home, 2007-08-27

Abstract Factory UNFINISHED
Adaptor aka Wrapper
Bridge aka Handle/Body
Command UNFINISHED
Composite
Decorator aka Wrapper UNFINISHED
Facade
Factory aka Factory Method aka Object Factory UNFINISHED
Flyweight UNFINISHED
Inversion of Control aka IOC aka The Dependency Inversion Principle UNFINISHED
Iterator aka Cursor
NVI aka The Non-Virtual Interface idiom
Observer aka Publish-Subscribe UNFINISHED
Pimpl aka the Compiler-Firewall Idiom
Proxy aka Surrogate
Singleton
State
Strategy
Template
Visitor
Litterature and Links

Abstract Factory UNFINISHEDContents

Goal:

Solution:

Question:

Adaptor aka WrapperContents

Goal: we need a class A with interface a and has a class B with interface b.

Solution: convert the interface by using a class adapter or a object adapter:

Bridge aka Handle/BodyContents

Goal: separate abstraction from implementation to make it possible to change have objects using the abstraction decoupled from the back-end implementations, i.e. the objects using the abstraction can be changed independently from the back-ends and vice versa.

Solution: The abstraction is a class that has an implementation object and implements the abstraction using the methods of the implementation.

The pattern makes it possible to change the implementation in the abstraction (like in State) and the implementation can be an Adaptor to a class with another interface. Furthermore, classes can be derived from the abstraction to use the abstraction.

Example: Say you have an abstraction, shapes. You want to have many types of shapes and each with its own properties but all of them should provide draw(). However, drawing graphics is dependent on the platform and you want your shapes to be able to be drawn on multiple platforms and it is not practical to reimplement the shapes for each platform. The bridge helps by allowing you to create new classes that provide the drawing implementation. The abstraction shape provides methods for getting the size or properties of a shape and has a drawing implementation that provides an interface for drawing graphics. Now if a new shape needs to be created or you want to draw your shapes on a new graphics API then it is easy to add a new class that implements the features you need.

This seems like a composite pattern to me, using classes derived from a State class, where this has an Adaptor.

Command UNFINISHEDContents

Goal:

Solution:

Question:

CompositeContents

Goal: to be able to handle objects and collections of objects in an uniform way.

Solution: There are a number of solutions to make a composite of a class T with an operation op(). One is to derive a class C, that additionally has a container with Cs in it together with an add() and remove(). When op() is called the functionality from T.op() is executed and op() is called on all the elements in the container. Another solution is to derive two classes from C, component and leaf, where only component will have a container and leaf represents a single object.

Decorator aka Wrapper UNFINISHEDContents

Goal:

Solution:

Question:

FacadeContents

Goal: hide a subsystem, for example a mess of classes, functions, or libraries.

Solution: make a nice wrapper class.

The facade is often a high-level interface to a lower-level system.

Factory aka Factory Method aka Object Factory UNFINISHEDContents

Problem:

Solution:

Question:

Flyweight UNFINISHEDContents

Goal: Use sharing to support large numbers of fine-grained objects efficiently or reduce memory footprint for small objects.

Solution: Each "flyweight" object is divided into two pieces: the state-dependent (extrinsic) part, and the state-independent (intrinsic) part. Intrinsic state is stored (shared) in the flyweight object. Extrinsic state is stored or computed by client objects, and passed to the Flyweight when its operations are invoked.

Instead of a large set of objects with a small amount of data we collect the data in one container object and use a method to get a specific object from the container (The container becomes a Factory).

Question:

Inversion of Control aka IOC aka The Dependency Inversion Principle UNFINISHEDContents

Goal: High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.

Solution: Design high level modules to use abstractions and implement the abstractions as low level modules.

Iterator aka CursorContents

The same as a c++ iterator.

NVI aka The Non-Virtual Interface idiomContents

Goal: separate interface and implementation (c++ does not directly support this).

Solution: Let the public functions represent the interface and the virtual private functions the implementation. The public functions will use the underlying virtual private functions and the implementation changed by sub-classes without touching the interface. Note that this also makes it possible to have pre and post conditions or other instrumentation in the base class that will also work for derived classes. Sutter2005.

Observer aka Publish-Subscribe UNFINISHEDContents

Goal: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

Note: It is the same idea the Qt signal-slot technology provides.

Solution:

Question:

Pimpl aka the Compiler-Firewall IdiomContents

Goal: hide implementation details to reduce compiletime dependencies.

Solution: use a pointer to a declared but undefined class and store private methods and members in this class. In this way it is possible to change the underlying implementation without recompiling the classes themselves. Sutter1999.

This is related to Bridge, but the intent here is only to hide the class own implementation.

Proxy aka SurrogateContents

Goal: controlling object access, for example defer construction of expensive objects.

Solution: A proxy class implements an interface but the methods are redelegated to an object owned by the proxy. In this way it is possible to create the object if it is needed and otherwise just have the proxy available.

A special case of State.

SingletonContents

Goal: ensure there is only one instance of an object.

Solution: a class with a static method, a static instance of itself and private constructors and operators:

class singleton{
public:
  static singleton& get_instance(){
    static singleton instance;
    return instance;
  }
  // methods etc.
  size_t get(){return counter++;} // example
  // ...
private:
  singleton(): counter(42){};
  singleton(const singleton&);
  ~singleton(){};
  singleton& operator=(const singleton&);
  // methods etc.
  size_t counter; // example
  // ...
};

By using a static allocated object we are ensured that it will be destructed correctly when the program ends (to free resources such as db-connections, corba-stuff etc.)

Question: how well does this work with threads?

StateContents

Goal: allow an object to change its behaviour when the state is changed, the object could appear to change its class.

Solution: let a class define an interface, but implement the methods by redelegating them to methods on an object owned by the class.

This can be used to build state machines easily: the SM will have a set of states and a pointer to the current state. It can also be used to change a toolkit at runtime.

State is related to Strategy. Proxy is a special case of State.

StrategyContents

Goal: make it possible to change algorithms at runtime.

Solution: use a base-class to represent an interface to a family of algorithms and implement the algorithms in the sub-classes.

Related to State and really just a special case of Template (?).

TemplateContents

Goal: implement an algorithm where it is easy to change the different steps used by the algorithm.

Solution: implement the algoritm in a base class and call methods to solve steps, a variant can then be constructed in a sub-class by overwriting the methods.

Also see NVI.

VisitorContents

Goal: Separating an algorithm from an object structure. A practical result of this separation is the ability to add new operations to existing object structures without modifying those structures.

Solution: We simulate double dispatch to let operations depend on both the method, shape, and a visitor object. Implementation: We have a set of classes C we wish to handle by a visitor class:

  1. Let every class C has a virtual method accept(visitor)
  2. For every concrete class C that has accept(), the visitor should have a method visit(C*).
  3. An object of class visitor is passed to the accept() method.
  4. accept(v) immediately calls v.visit(this)

    Extending the C interface amounts to defining one new visitor subclass rather than many new C subclasses. E.g. it is now easy to have multiple draws, as different draw_visitors can be implemented without changing shape-classes. In practice to draw a shape we will not call circle.draw(), but instead circle.accept(draw_visitor) (accept() will call draw_visitor.visit(this)).

Litterature and LinksContents