基於原則設計

基於原則設計（Policy-Based Class Design）又名policy-based class design 或 policy-based programming, 是一種基於C++電腦程式設計規範，以原則（Policy）為基礎，並結合C++的模板超編程（template metaprogramming）。policy-based首見於 Andrei Alexandrescu 出版的 《Modern C++ Design》 一書以及他在C/C++ Users Journal雜誌專欄 Generic<Programming> 。

 概覽 
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於其中。

 外部連結 
 Andrei Alexandrescu's Web site

Jiyuyuanzesheji
Jiyuyuanzesheji