jRate
Policy-Oriented Design Principles and Techniques

Policy-oriented design is a very effective technique to achieve both reuse of behaviours and to obtain generative behaviour. Below I present the core concept behind this style of design and implementation along with a sample implementation.

Policies and Host Classes

In policy-oriented design, one of the core requirements is that of individuating the policies that make up a class. Usually a policy represents a well-defined behaviour, and it is typically one of those behaviours that are subject to frequent customization, or that are desirable in some cases and not needed in others. A common example of policy is the locking policy to be used in the implementation of a class. Policy can both enrich the behaviour of a class or change some of its semantics.

Host classes are typically created from a collection of policies. One of the problems that often arises on implementing policy oriented design is the necessity of being able to communicate between the host and the policy class.

For instance, you might need to access some property of the host class from a policy, but yet the policy is part of the class. How can this bootstrapping problem be solved?

Bootstrapping

As soon as you start designing policy-based code, in which there is the need for an explicit protocol between the policy and the host class, you'll soon realize that you end up trying to do the following:


 
template <typename T>
class Policy : public T {
public:
  void doPolicyCode() {
    // ...
    this->hostMethod()
    // ...
  }
};

template <template <typename> class T>
class Host : public T<Host> {
public:
  //...
  someType hostMethod() {
    //...
  }
};

int main(int argc, char** argv) {
  // ...
  Host<Policy> h; // This won't work!!!
  // ...
}


We can circumvent this problem and achieve the desired effect by combining the power of C++ polymorphism and templates. Below is a solution that shows how these techniques can be combined to achieve our goal.


 
template <typename T>
class PolicyOne {
public:
  virtual ~PolicyOne() { }
  void doPolicyOne() {
    T v = this->getValue();
    std::cout << "PolicyOne> Value = " 
              << v << std::endl;
  }
  // -- Contract Methods --
  virtual T getValue() = 0;
};

template <typename T>
class PolicyTwo {
public:
  void doPolicyTwo() {
    T v = this->getValue() * 5;
    std::cout << "PolicyTwo> Value = " 
              << v << std::endl;
  }

  // -- Contract Methods --
  virtual T getValue() = 0;
};

template <template <typename> class PolicyA, 
template <typename> class PolicyB>
class HostOne : public PolicyA<int>, public PolicyB<int> {
public:
  HostOne(int value) : value_(value) { }
  virtual ~HostOne() { }

  // -- Contract Methods --
  virtual int getValue() {
    return value_;
  }

private:
  int value_;
};

int main(int argc, char** argv) {
  HostOne<PolicyOne, PolicyTwo> h1(10);
  h1.doPolicyOne();
  h1.doPolicyTwo();
  return 0;
}

Last modified 15 Jul 2006 / xhtml1 / css2