基於原則設計

概覽

Policy的意思是方針，或策略，也就是將原本複雜的系統，拆解成多個獨立運作的「策略類別」（policy class），每一組policy class都只負責單純如行為（behavior, method）或結構（structure）的某一方面。Templetes與多重繼承（Multiple Inheritance）兩項技術互補。多重繼承由於繼承自多組 Base Class，故缺乏型別訊息（type information），而Templetes基於型別，擁有豐富的型別訊息。多重繼承容易擴張，而Templetes的特化（Specialization）不容易擴張。Policy-Based Class Design 同時使用了 Template 以及 Multiple Inheritance 兩項技術，結合兩者的優點。

template
<
         class Policy1,
         class Policy2,
         class Policy3
>
class PolicyBasedClass:public Policy1, public Policy2
{
public:
   PolicyBasedClass(){};
};
PolicyBasedClass則稱為宿主類別（host class），只需要切換不同 Policy Class，就可以得到不同的需求。Policy不一定要被宿主（host）繼承，只需要用委託（delegation）完成這一工作。但policies必須遵守一個隱含的constraint，介面（interface）必須一樣，故參數不能有巨大改變。
Policy class有點類似回呼函式（callbacks），但不同的是，callback只是一個函式，至於 policy class 則盡可能包含許多的 functions (methods), 有時還會結合狀態變數（state variables）與其他各式各樣的型別，如巢狀型別（nested types）。
policy 的一個重要的特徵是，宿主類別（host class）經常（並不一定要）使用多重繼承的機制去使用多個 policy classes. 因此在進行 policy 拆解時，必須要盡可能達成正交分解（Orthogonal Decomposition），policy彼此獨立運作，不相互影響。

Template Template Parameter

在 C++ 的Policy-Based Design 中，用來建構 Template 的類別參數（也就是policy class），本身亦可以是一個 Tempate 化的類別，形成所謂的 Template Template Parameter。
如果 Read()、Write() 有各種不同名目的參數時，可以利用 template 的不完全具現化 (Incomplement Instantiation) 特徵檢實現各個參數不同的成員函式（member function）。在host class中，可以撰寫不同參數版本的 Read(...) 函式，這有賴於c++ compiler的協助。

template
<
        class T,
        template< class > class ReadPolicy,
        template< class > class WritePolicy
>
class ResourceManager
        :
        public ReadingPolicy< T >,
        public WritingPolicy< T >
{
public:
   void Read();
   void Write(XmlElement*);
   void Write(DataSource*);
};
上述的class T即是一個Template Template Parameter，這使得 Policy Class 更具擴充性與彈性，能夠處理各種類型的實體（instance）。

void main()
{
  ResourceManager< AnimationEntity, BinaryReader, BinaryWriter > ResMgr1;
  ResourceManager< ScriptEntity, TextReader, TextWriter > ResMgr2;
}

範例

下例是 C++ hello world的範例，可以使用各種原則（policies）列印文字。
template<
    typename output_policy,
    typename language_policy>class HelloWorld
  : public output_policy,
    public language_policy{
    using output_policy::Print;
    using language_policy::Message;public:

    //behaviour method
    void Run()
    {
        //two policy methods
        Print( Message() );
    }};#include <iostream>class HelloWorld_OutputPolicy_WriteToCout{protected:

    template< typename message_type >
    void Print( message_type message )
    {
        std::cout << message << std::endl;
    }};#include <string>class HelloWorld_LanguagePolicy_English{protected:

    std::string Message()
    {
        return "Hello, World!";
    }};class HelloWorld_LanguagePolicy_German{protected:

    std::string Message()
    {
        return "Hallo Welt!";
    }};int main(){/* example 1 */

    typedef
        HelloWorld<
            HelloWorld_OutputPolicy_WriteToCout,
            HelloWorld_LanguagePolicy_English
        >
            my_hello_world_type;

    my_hello_world_type hello_world;
    hello_world.Run(); //returns Hello World!/* example 2  * does the same but uses another policy, the language has changed */

    typedef
        HelloWorld<
            HelloWorld_OutputPolicy_WriteToCout,
            HelloWorld_LanguagePolicy_German
        >
            my_other_hello_world_type;

    my_other_hello_world_type hello_world2;
    hello_world2.Run(); //returns Hallo Welt!}
你可以更容易的撰寫其他的 Output policy, 單靠你創造更新的Policy class並實作print於其中。