6 August 2004

The policy (trait) pattern

Policies allow you to affect the internal workings of an otherwise opaque class by providing that class with secondary classes. The secondary classes are used by the primary class to define how it should implement its algorithms, or to provide those algorithms themselves.

[ updated 28 Mar 2006 ] with list of terminology used

The canonical example is the smart pointer. A smart pointer has several, overarching choices, the most relevant: how are the raw pointers shared and how is the memory managed. With, say, three sharing options and three memory options, you have nine possible class implementations. Using policies, you can define the three versions of each trait and allow the client to choose their implementation. This way, one class plus its policies accommodates all options.

Andrei Alexandrescu details the ins and outs of policy programming in his book Modern C++ Design: Generic Programming and Design Patterns Applied. Design Patterns defines this as a strategy pattern, and I've always used the name trait.

Alexandrescu focuses on policies as templates. This makes sense with smart pointers, which need to be templates anyway, but templates can get in the way of hiding header file dependencies. Because the template exists in one file, all of the headers required for implementation must be specified there. Any client will get those headers (and be forced to rebuild when they change) even if it doesn't need them.

Another solution, offered in Design Patterns, is to simply use a property of the primary class to hold the policy class. This way, the dependencies can be encapsulated in the primary class's source file. A small feature, but sometimes very helpful. Both the template and the property solution allow you to provide defaults so that the client can use the most common policies without overcomplicating their code.

[ posted by sstrader on 6 August 2004 at 12:28:53 PM in Programming ]