C++設計模式類庫 Loki介紹與用法

C++設計模式類庫 Loki介紹與用法

Loki是由Andrei編寫的一個與《Modern C++ Design》(C++設計新思惟)一書配套發行的C++代碼庫。
它不只把C++模板的功能發揮到了極致,並且把相似設計模式這樣思想層面的東西經過庫來提供。
本篇文章介紹如何利用Loki來輕鬆地實現一些設計模式。
因爲Loki使用了大量牛X到爆的模板技巧,對編譯器的要求是很苛刻的,官方兼容列表裏只列出了VC7.1以上版本及GCC3.4以上版本。若是你象我同樣喜歡用C++Builder6或VC6,能夠去下載《Modern C++ Design》配套源碼,那裏面的Loki提供了對其它不兼容編譯器的移植代碼,只是版本低了一點,有些接口有些差異。

最後,BTW,《Modern C++ Design》確實是一本好書,在這裏也順便推薦一下^_^算法

Loki的下載地址是http://sourceforge.net/projects/loki-lib/,目前最新版本是Loki 0.1.7,後面的代碼都使用這個版本做爲測試標準。編程

編譯

Loki庫提供了N多種編譯途經,你能夠直接打開項目文件(VC、Code::Block、Cpp-Dev等IDE)編譯,也能夠用傳統的makefile來make,還能夠直接用批處理文件編譯。象我這種被IDE慣壞的人,通常都是直接把src目錄裏的代碼加入到項目中了事。設計模式

Singleton模式(單件模式)

Singleton模式確保一個類在系統中只有一個實例。好比一個窗口系統中只能有一個鼠標對象,只有一個屏幕對象,一個剪切板對象...。咱們能夠用一個全局變量來作這些工做,但它不能防止實例化多個對象。一個更好的辦法是讓類自身保存它的惟一實例,而且不容許建立其它實例,這就是Singleton模式。ide

Loki庫的SingletonHolder類提供了對Singleton模式的支持函數

頭文件

  1. #include <loki/Singleton.h>

類型定義

  1. template<
  2.     typename T,
  3.     templateclass > class CreationPolicy = CreateUsingNew,
  4.     templateclass > class LifetimePolicy = DefaultLifetime,
  5.     templateclassclass > class ThreadingModel = ::Loki::SingleThreaded,
  6.     class MutexPolicy = ::Loki::Mutex>
  7. class Loki::SingletonHolder;

Loki的類大部分都是基於策略編程的,其中最主要的是CreationPolicy,它決定了怎樣生成一個類實例,可選的有:測試

  • template<template<class> class Alloc> struct CreateUsing; 在分配器分配的內存中生成實例,如
  • template <class T> struct CreateStatic 生成靜態實例
  • template <class T> struct CreateUsingMalloc 使用malloc申請內存並在其中生成實例
  • template <class T> struct CreateUsingNew 使用new生成實例(默認)

示例代碼

  1. class MyClass{
  2. public:
  3.     // 有默認構造
  4.     MyClass(){;}
  5.     // 顯示本身所在的內存地址,用以區分是不是同一個對象
  6.     void ShowPtr()
  7.     {
  8.         std::cout << this << std::endl;
  9.     }
  10. };
  11. // 定義Singleton的MyClass
  12. typedef Loki::SingletonHolder<MyClass> MyClassSingleton;
  13.  
  14. int _tmain(int argc, _TCHAR* argv[])
  15. {
  16.     // 經過Instance()靜態方法取得MyClass實例
  17.     MyClass& v = MyClassSingleton::Instance();
  18.     v.ShowPtr();
  19.     // MyClassSingleton::Instance()老是返回同一個MyClass實例
  20.     MyClassSingleton::Instance().ShowPtr();
  21.     return 0;
  22. }

Loki::SingletonHolder默認的CreationPolicy策略要求類必須有默認構造,如MyClass這樣。若是須要包裝沒有默認構造的類的話,咱們就得自定義一個CreationPolicy策略,好在CreationPolicy策略比較簡單,先看看Loki中默認的CreateUsingNew吧:ui

  1. template <class T> struct CreateUsingNew
  2. {
  3.     static T* Create()
  4.     { return new T; }
  5.  
  6.     static void Destroy(T* p)
  7.     { delete p; }
  8. };

呵呵,簡單吧,只是簡單的Create和Destroy而已。this

咱們只要修改Create()靜態方法,new一個本身的對象就能夠了,固然隨便多少構造參數均可以在這裏寫上去啦。另外,若有必要,也能夠作一些其它初始工做哦。spa

  1. class MyClass2{
  2. public:
  3.     // 構造裏要求兩個整數
  4.     MyClass2(int,int){;}
  5.     void ShowPtr()
  6.     {
  7.         std::cout << this << std::endl;
  8.     }
  9. };
  10. // 咱們本身的CreationPolicy策略
  11. template<class T>
  12. class CreateMyClass2UsingNew:
  13.     public Loki::CreateUsingNew<T>
  14. {
  15. public:
  16.     static T* Create()
  17.     { return new T(0,0); }
  18. };
  19. // 定義使用CreateMyClass2UsingNew策略的Singleton類
  20. typedef Loki::SingletonHolder<MyClass2,
  21.     CreateMyClass2UsingNew> MyClass2Singleton;
  22. // 使用之
  23. int _tmain(int argc, _TCHAR* argv[])
  24. {
  25.     MyClass2Singleton::Instance().ShowPtr();
  26.     MyClass2Singleton::Instance().ShowPtr();
  27.     return 0;
  28. }

usidc5 2011-01-18 16:48

對象工廠 Object Factory

又名簡單工廠模式,貌似不屬於設計模式範疇。它的做用是把對象的建立工做集中起來,並使建立工做與其它部分解耦。好比下面這個函數也可看成簡單工廠:.net

  1. CWinBase* Create(string s)
  2. {
  3.     if(s == "Edit")
  4.         return new CEdit;
  5.     else if(s == "Button")
  6.         return new CButton;
  7.     ...
  8. }

Loki庫的Factory類提供了對簡單工廠模式的支持。

頭文件

  1. #include 

類型

  1. template<
  2.     class AbstractProduct, // 「產品」基類型
  3.     typename IdentifierType, // 用什麼區分各產品
  4.     typename CreatorParmTList = NullType, // 生成器參數
  5.     templatetypenameclass > class FactoryErrorPolicy = DefaultFactoryError>
  6. class Loki::Factory;

成員方法

bool Register(const IdentifierType& id, ProductCreator creator); 以id做爲識別碼註冊生成器。函數、對象方法或仿函數均可以做爲生成器。
bool Unregister(const IdentifierType& id); 取消註冊
std::vector RegisteredIds(); 取得已註冊的全部識別碼
AbstractProduct* CreateObject(const IdentifierType& id);
AbstractProduct* CreateObject(const IdentifierType& id, Parm1 p1);
AbstractProduct* CreateObject(const IdentifierType& id, Parm1 p1, Parm2 p2);
...
按識別碼id生成對象(調用對應的生成器)

示例代碼

  1. #include 
  2. #include 
  3. #include 
  4. #include 
  5.  
  6. // 窗體基類
  7. struct IWidget{
  8.     virtual void printName() = 0;
  9.     virtual ~IWidget(){;}
  10. };
  11. // 定義窗體工廠,使用string區分各對象類型
  12. typedef Loki::Factory widget_factory_t;</iwidget, std::string>
  13. // 按鈕窗體
  14. struct CButton : IWidget{
  15.     void printName()
  16.     {
  17.         std::cout << "CButton" << std::endl;
  18.     }
  19. };
  20. // 編輯框窗體
  21. struct CEdit : IWidget{
  22.     void printName()
  23.     {
  24.         std::cout << "CEdit" << std::endl;
  25.     }
  26. };
  27. // 列表框窗體
  28. struct CListBox : IWidget{
  29.     void printName()
  30.     {
  31.         std::cout << "CListBox" << std::endl;
  32.     }
  33. };
  34.  
  35. int _tmain(int argc, _TCHAR* argv[])
  36. {
  37.     // 工廠實例
  38.     widget_factory_t wf;
  39.     // 註冊各類窗體的生成器,這裏偷懶用了CreateUsingNew做爲生成器
  40.     wf.Register("Edit", Loki::CreateUsingNew::Create );
  41.     wf.Register("Button", Loki::CreateUsingNew::Create );
  42.     wf.Register("ListBox", Loki::CreateUsingNew::Create );
  43.     // 測試,使用工廠生成窗體
  44.     {
  45.         IWidget* pWid = wf.CreateObject("Edit");
  46.         pWid->printName();
  47.         delete pWid;
  48.     }
  49.     {
  50.         IWidget* pWid = wf.CreateObject("ListBox");
  51.         pWid->printName();
  52.         delete pWid;
  53.     }
  54.     return 0;
  55. }

不少時候,工廠每每只須要一個實例,咱們可使用前面說過的SingletonHolder把widget_factory_t弄成Singleton模式。

上面生成CButton之類的窗體時使用的是默認構造,因此我偷懶沒寫各個類的生成器,直接用了Loki::CreateUsingNew。

若是你的類有構造參數的話,那麼就得在Loki::Factory模板參數中指出參數類型,而且自定義生成器,就象這樣:

  1. #include 
  2. #include 
  3. #include 
  4.  
  5. // 窗體基類
  6. struct IWidget{
  7.     virtual void printName() = 0;
  8.     virtual ~IWidget(){;}
  9. };
  10. // 定義窗體工廠,這裏用Loki::Seq指定參數類型
  11. typedef Loki::Factory<
  12.     IWidget,
  13.     std::string,
  14.     Loki::Seq<intchar>
  15. > widget_factory_t;
  16. // 單件模式,注意Lifetime策略要選擇Loki::LongevityLifetime::DieAsSmallObjectChild,不然...
  17. typedef Loki::SingletonHolder<widget_factory_t, loki::createusingnew,< span=""></widget_factory_t, loki::createusingnew,<>
  18.     Loki::LongevityLifetime::DieAsSmallObjectChild> Singleton_Fac;
  19. // 按鈕窗體
  20. struct CButton : IWidget{
  21.     void printName()
  22.     {
  23.         std::cout << "CButton:" << m_txt << std::endl;
  24.     }
  25.     CButton(std::string txt, intchar//多個構造參數
  26.         :m_txt(txt){}
  27.     std::string m_txt;
  28. };
  29. // 編輯框窗體
  30. struct CEdit : IWidget{
  31.     void printName()
  32.     {
  33.         std::cout << "CEdit:" << m_txt << std::endl;
  34.     }
  35.     CEdit(std::string txt, intchar//多個構造參數
  36.         :m_txt(txt){}
  37.     std::string m_txt;
  38. };
  39. // 列表框窗體
  40. struct CListBox : IWidget{
  41.     void printName()
  42.     {
  43.         std::cout << "CListBox:" << m_txt << std::endl;
  44.     }
  45.     CListBox(std::string txt, intchar//多個構造參數
  46.         :m_txt(txt){}
  47.     std::string m_txt;
  48. };
  49. // 自定義的窗體構造器,用模板只是爲了方便點^_^
  50. template<class T> struct CreateT
  51. {
  52.     T * operator()(std::string txt, int p1, char p2) const
  53.     {
  54.         return new T(txt, p1, p2);
  55.     }
  56. };
  57.  
  58. int _tmain(int argc, _TCHAR* argv[])
  59. {
  60.     // 工廠實例
  61.     widget_factory_t& wf = Singleton_Fac::Instance();
  62.     // 註冊各類窗體的生成器,用咱們的生成器
  63.  
  64.     wf.Register("Edit", CreateT() );
  65.     wf.Register("Button", CreateT() );
  66.     wf.Register("ListBox", CreateT() );
  67.  
  68.     // 測試,使用工廠生成窗體
  69.     {
  70.         IWidget* pWid = wf.CreateObject("Edit""Hello", 0, ' ');
  71.         pWid->printName();
  72.         delete pWid;
  73.     }
  74.     {
  75.         IWidget* pWid = wf.CreateObject("ListBox""World", 0, ' ');
  76.         pWid->printName();
  77.         delete pWid;
  78.     }
  79.  
  80.     return 0;
  81. }

Loki::Seq是一個相似於TypeList的東東,能夠存放一系列的類型。另外用SingletonHolder包裝Factory時,必定要用Loki::LongevityLifetime::DieAsSmallObjectChild做爲SingletonHolder的lifttime策略(Loki使用說明上說的,因爲Factory使用了Loki內部的內存管理器SmallObject)。


usidc5 2011-01-18 16:49

Abstract Factory模式(抽象工廠)

抽象工廠提供了一個建立一系列相關或相互依賴對象的接口,而無需指定具體的類。

好比要編寫一個可換膚的用戶界面,那麼咱們生成的每一個窗體都應該遵循統一的風格,不該該在一個界面裏同時出現Mac風格和Win風格的按鈕。爲了便於控制,咱們能夠這樣寫代碼:

  1. struct IWidgetFactory{
  2.     virtual IButton* CreateButton() = 0;
  3.     virtual IEdit* CreateEdit() = 0;
  4.     virtual IListBox* CreateListBox() = 0;
  5. };
  6. struct CWindowsFactory : IWidgetFactory{
  7.     virtual IButton* CreateButton(){生成Win風格按鈕;}
  8.     virtual IEdit* CreateEdit(){生成Win風格編輯框;}
  9.     virtual IListBox* CreateListBox(){生成Win風格列表框;}
  10. };
  11. struct CMacFactory : IWidgetFactory{
  12.     virtual IButton* CreateButton(){生成Mac風格按鈕;}
  13.     virtual IEdit* CreateEdit(){生成Mac風格編輯框;}
  14.     virtual IListBox* CreateListBox(){生成Mac風格列表框;}
  15. };

這樣,在程序中咱們要用執有IWidgetFactory指針,在必要時實例化某個具體風格的工廠類,最後全部的窗體都由這個IWidgetFactory指針來生成便可。這就是Abstract Factory模式。Loki庫的AbstractFactory和ConcreteFactory提供了對Abstract Factory模式的支持。

頭文件

  1. #include 

類型

template
<
    class TList,
    template <class>
        class Unit = AbstractFactoryUnit
>
class AbstractFactory;

AbstractFactory模板類是一個虛類,它根據TList中的類型提供一組Create<>()方法。

  • 模板參數TList是一個Typelist,輸入全部工廠可生產的產品基類,如前面的IButton,IEdit,IListBox。
  • 模板參數Unit依據TList中的全部類型產生對應的Create<>()虛函數,通常直接用默認的AbstractFactoryUnit就能夠了。
template
<
    class AbstractFact,
    template <class, class>
        class Creator = OpNewFactoryUnit,
    class TList = typename AbstractFact::ProductList
>
class ConcreteFactory;

ConcreteFactory實現了AbstractFactory中的Create<>()方法

  • 模板參數AbstractFact就是對應的AbstractFactory類
  • 模板參數Creator是產品實例的生成策略,可選的有OpNewFactoryUnit和PrototypeFactoryUnit。
    • OpNewFactoryUnit使用new生成新的產品實例;
    • PrototypeFactoryUnit使用已有產品(原型)的Clone()方法生成新的實例,這也意味着要使用PrototypeFactoryUnit咱們的產品基類必需要有T *Clone()成員方法。
  • TList提供一組具體的產品類型,若是Creator策略是PrototypeFactoryUnit,能夠不提供。

演示代碼

  1. #include 
  2. #include 
  3. #include 
  4. // 產品基類
  5. struct IButton{
  6.     virtual void click() = 0;
  7. };
  8. struct IEdit{
  9.     virtual void edit() = 0;
  10. };
  11. struct IListBox{
  12.     virtual void scroll() = 0;
  13. };
  14. // 抽象工廠
  15. typedef Loki::AbstractFactory<
  16.     LOKI_TYPELIST_3(IButton, IEdit, IListBox) //也能夠用Loki::Seq< IButton, IEdit, IListBox >::Type
  17. > IWidgetFactory;
  18.  
  19. // 具體產品-Win
  20. struct CWinBtn : IButton{
  21.     virtual void click(){
  22.         std::cout<< "CWinBtn Clicked" << std::endl;
  23.     }
  24. };
  25. struct CWinEdit : IEdit{
  26.     virtual void edit(){
  27.         std::cout<< "CWinEdit Editing" << std::endl;
  28.     }
  29. };
  30. struct CWinLB : IListBox{
  31.     virtual void scroll(){
  32.         std::cout<< "CWinLB Scrolling" << std::endl;
  33.     }
  34. };
  35. // 具體產品-Mac
  36. struct CMacBtn : IButton{
  37.     virtual void click(){
  38.         std::cout<< "CMacBtn Clicked" << std::endl;
  39.     }
  40. };
  41. struct CMacEdit : IEdit{
  42.     virtual void edit(){
  43.         std::cout<< "CMacEdit Editing" << std::endl;
  44.     }
  45. };
  46. struct CMacLB : IListBox{
  47.     virtual void scroll(){
  48.         std::cout<< "CMacLB Scrolling" << std::endl;
  49.     }
  50. };
  51. // 具體工廠
  52. typedef Loki::ConcreteFactory<
  53.     IWidgetFactory,
  54.     Loki::OpNewFactoryUnit,
  55.     LOKI_TYPELIST_3(CWinBtn, CWinEdit, CWinLB)
  56. > CWindowsFactory;
  57.  
  58. typedef Loki::ConcreteFactory<
  59.     IWidgetFactory,
  60.     Loki::OpNewFactoryUnit,
  61.     LOKI_TYPELIST_3(CMacBtn, CMacEdit, CMacLB)
  62. > CMacFactory;
  63.  
  64. // 使用工廠生成的產品
  65. void UsingWidget(IWidgetFactory *pFac)
  66. {
  67.     IEdit* pEdt = pFac->Create();
  68.     IButton* pBtn = pFac->Create();
  69.     IListBox* pLB = pFac->Create();
  70.     pEdt->edit();
  71.     pBtn->click();
  72.     pLB->scroll();
  73.     delete pEdt;
  74.     delete pBtn;
  75.     delete pLB;
  76. }
  77.  
  78. int _tmain(int argc, _TCHAR* argv[])
  79. {
  80.     // 使用Win風格
  81.     {
  82.         CWindowsFactory winfac;
  83.         UsingWidget(&winfac);
  84.     }
  85.  
  86.     // 使用Mac風格
  87.     {
  88.         CMacFactory macfac;
  89.         UsingWidget(&macfac);
  90.     }
  91.     return 0;
  92. }

usidc5 2011-01-18 16:49

Visitor 模式(訪問者模式)

訪問者模式把對某對象結構中的各元素的相關操做集中到一塊兒,能夠方便地在不改變無素類的前提下添加新的操做。

假設一個XML類,咱們可能要打印、保存、轉換這個XML數據。實際上這些操做都須要遍歷節點,不一樣的只是操做的方式,咱們能夠這樣寫代碼:

  1. struct IVisitor;
  2. struct TTextNode{
  3.     virtual void accept(IVisitor *visitor){ visitor->visit(this); }
  4. };
  5. struct TCDataNode{
  6.     virtual void accept(IVisitor *visitor){ visitor->visit(this); }
  7. };
  8. struct TElementNode{
  9.     virtual void accept(IVisitor *visitor){ visitor->visit(this); }
  10. };
  11. struct IVisitor{
  12.     virtual void visit(TTextNode*) = 0;
  13.     virtual void visit(TCDataNode*) = 0;
  14.     virtual void visit(TElementNode*) = 0;
  15. };
  16.  
  17. struct CSaveVisitor{
  18.     virtual void visit(TTextNode*){ 保存文本內容 }
  19.     virtual void visit(TCDataNode*){ 保存[[CData內容]] }
  20.     virtual void visit(TElementNode*){ 保存<標籤> 全部子節點.accept(this)  }
  21. };
  22.  
  23. struct CPrintVisitor{
  24.     ...
  25. };

固然,這種模式的問題是可能會破壞一些封裝性。咱們這裏不討論Visitor模式的優劣,先看看Loki是怎麼實現這個模式的吧

頭文件

  1. #include 

類型

template
<
    typename R = void,
    template <typename, class> class CatchAll = DefaultCatchAll,
    bool ConstVisitable = false
>
class BaseVisitable;
可訪問類型的基類,若是要讓元素能被訪問,要必須繼承自BaseVisitable。
  • 模板參數R是Accept()方法的返回值。
  • 模板參數CatchAll表示某元素沒有對應的訪問方法時的反應,默認的DefaultCatchAll是什麼也不作。
  • 模板參數ConstVisitable表示Accept()方法是不是const方法。
class BaseVisitor;
全部訪問者的基類
template <
  class T,
  typename R = void,
  bool ConstVisit = false>
class Visitor;
訪問者實現模板
  • 模板參數T是一個Typelist,表示訪問者能接受的全部元素類型
  • 模板參數R是Visit()方法的返回值
  • 模板參數ConstVisit表示Visit()方法是不是const方法。

示例代碼

  1. #include 
  2. #include 
  3. #include 
  4. #include 
  5. #include 
  6. // XML元素
  7. struct TTextNode : Loki::BaseVisitable<>{
  8.     LOKI_DEFINE_VISITABLE();
  9.     TTextNode(std::string text)
  10.         :m_text(text){}
  11.     std::string m_text;
  12. };
  13. struct TCDataNode : Loki::BaseVisitable<>{
  14.     LOKI_DEFINE_VISITABLE();
  15.     TCDataNode(std::string text)
  16.         :m_cdata(text){}
  17.     std::string m_cdata;
  18. };
  19. struct TElementNode : Loki::BaseVisitable<>{
  20.     LOKI_DEFINE_VISITABLE();
  21.  
  22.     std::string m_name;
  23.     TElementNode(std::string text)
  24.         :m_name(text){}
  25.     typedef Loki::BaseVisitable<> visitable_t;
  26.     //這裏用了Loki::SmartPtr,這是一個智能指針類型
  27.     typedef Loki::SmartPtr<
  28.         Loki::BaseVisitable<>
  29.     > ptr_t;
  30.     std::vector< ptr_t > m_childs;
  31. };
  32. // 訪問者,必須繼承自BaseVisitor
  33. class CPrintVisitor :
  34.     public Loki::BaseVisitor,
  35.     public Loki::Visitor
  36. {
  37. public:
  38.     void Visit(TTextNode& n){std::cout << n.m_text;}
  39.     void Visit(TCDataNode& n){std::cout << " << n.m_cdata << "]]>";}
  40.     void Visit(TElementNode& n){
  41.         std::cout<<std::endl;< span="">
  42.         std::cout<< '<' << n.m_name << '>' << std::endl;
  43.         for(size_t idx=0, len=n.m_childs.size(); idx<len; idx++ )< span=""></len; idx++ )<>
  44.         {
  45.             n.m_childs[idx]->Accept(*this);
  46.         }
  47.         std::cout<< std::endl << " << n.m_name << '>' << std::endl;
  48.     }
  49. };
  50.  
  51. int main()
  52. {
  53.     // 構建XML結構
  54.     TElementNode root("root");
  55.     TElementNode *child1 = new TElementNode("child1");
  56.     child1->m_childs.push_back(new TTextNode("hello"));
  57.     TElementNode *child2 = new TElementNode("child2");
  58.     child2->m_childs.push_back(new TCDataNode("world >_<"));
  59.     root.m_childs.push_back( child1 );
  60.     root.m_childs.push_back( child2 );
  61.  
  62.     // 用CPrintVisitor訪問XML全部元素
  63.     CPrintVisitor visitor;
  64.     root.Accept(visitor);
  65. }

輸出結果




hello



_<]]>




usidc5 2011-01-18 16:51

大牛Andrei Alexandrescu的《Modern C++ Design》討論的是C++語言的最前沿研究:generative programming。本書中譯版估計得要半年之後才能出來,因此只能靠其所附源碼來窺測generative programming了。
  目前,我剛將源碼讀解了約一半,等所有讀完,我會將個人讀解註釋放出來的。如今,現談一下個人感想。
   先扯得遠一點。C++有兩個巨大優勢:和C兼容,自由;有兩個巨大缺點:和C兼容,複雜。C++極其複雜,很難掌握,而這正是「自由」的代價。C++語言是個多編程風格的語言,它同時支持過程化、基於對象、面向對象、泛型、生成性這5種編程思想,具備極其強大的表達能力,能夠方便地將各類設計轉化爲實現。
  generic Programming的思想精髓是基於接口編程(相對於OOP,連多態所需的基類都不要了),它的技術出發點是選擇子,核心技術是:類型推導、類型萃取、特化/偏特化,其成果是STL庫:一組通用容器和一組操做於通用容器上的通用算法。
  generative programming的思想精髓是基於策略編程(編譯器根據策略自動生成所需代碼,因爲具備更高的抽象性,因此代碼複用度也更高),在Loki庫的實現中,目前只使用了遞歸策略,它的技術出發點是Typelist,核心技術是:類型推導、類型萃取、特化/偏特化、多重繼承、類型間去耦合,其成果是Loki庫:對設計模式的封裝。
  Typelist是一種對類型自己進行存儲和管理的技巧,它的源碼已經貼過了,我也做了註解,此處再也不談論。
  這是多重繼承在COM以後的又一大型運用。多重繼承極易發生菱型缺陷,因此Loki庫使用了類型間去耦合技術來避免:
   template <typename T>
   struct Type2Type
   {
   typedef T OriginalType;
   };
  通過這樣一層轉換後,原類型T間的各類轉換關係(尤爲是繼承/派生關係)已不復存在,菱型缺陷不會再發生了。
  Loki庫的具體實現至關講究技巧,設計它很是困難(難度遠大於STL庫,和Boost庫有得一拼啊)。但使用它卻很是容易,並且便利顯著。因爲Loki庫提供了對設計模式的封裝,因此極大量地豐富了C++語言的表達能力,使的你的設計更容易地轉化爲實現。
  目前,Loki庫只提供了對廠模式和visitor模式的封裝,它還處於發展初期。



相關文章
相關標籤/搜索