基於原則設計

基於原則設計（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彼此獨立運作，不相互影響。 在 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