Algorithm Library Design 演算法庫設計in c++ IV(GenVoca 架構)

來源:互聯網
上載者:User
GenVoca 架構

GenVoca是一種軟體架構,與policy-based架構類似的是,它的最終成品也是由各個組件組裝而成的,但是組織的方式有所不同。

在Policy-based架構中,組件作為具體的policy實現被添加到host class以實現相應的功能,而在GenVoca中組件作為wrappers (layers) on top of a more basic components adding functionality to it.

個人感覺從原文給的list的一個實現來看,與基於policy的架構相比,GenVoca多了不同的層次,上層需要下層的不同實現。如B層需要下面的C來實現,而實現後的B又可作為實現提供給更上層的A。

R : A | B[R]S : C[R] | D[S] | E[R,S]
R可以由A實現,或者由B和R的一個實現合起來實現。
S可以由C以及R的某個實現,合起來實現。
GenVoca執行個體:List

是一個List的特徵圖。特徵是從使用者使用角度來看的,使用者裝配List要提供的參數。

必要的特徵

我需要List 操縱什麼樣的資料?

List如何持有資料?通過引用持有還是深拷貝的方法持有。

對於資料操作,我們採用多態性嗎?

可選的特徵

需要一個變數記錄長度嗎->如果需要長度的資料類型是什麼int short 還是long

需要Tracing嗎,這裡意思是說我們要追蹤過程列印過程資訊嗎?

設計一個GenVoca架構需要考慮下面幾個步驟:
  • 確定特種圖中提到的主要職責,要提供的主要功能。對於List:
    • 資料的儲存
    • 資料的拷貝
    • 資料的銷毀(注意這個對應到特徵圖,如果使用者選擇copy持有資料,或者owned reference那麼要自己負責delete,否則不需要,empty delete就好)
    • 動態類型檢查(為了monomorphism)
    • 長度計數器
    • tracing
  • 確定組件分組:
    • BasicList: PtrList     //:左邊代表策略組件,右邊是不同的實現策略categories : components
    • Copier: PolymorphicCopier, MonomorphicCopier, EmptyCopier
    • Desroyer: ElementDestroyer, EmptyDestroyer
    • TypeChecker: DynamicTypeChecker, EmptyTypeChecker
    • Counter: LengthList
    • Tracing: TracedList
  • 確定使用依賴`use'' dependencies between component categories.

  

  • Sort the categories into a layered architecture.得到具體架構。最底層的copier,destoryer,typechecker,作為config.

The component categories that do not depend on other categories are grouped into the bottom ConfigurationRepository (Config for short) layer category.

Tracing和Counter是可選的分組。

個人注,其實很清楚的標明了List的整體架構設計。

BasicList(其實就是用PtrList類實現)有3個策略copier,destoryer,typecheker,通過選擇不同的策略組合不同的list。其實就是基於policy的設計。

然後counter用basicList

那麼採用模版繼承的方法。

<typename Base>

class Derived: public Base

通過把basicList作為模版參數,並繼承,使得counter複用basiclist,同時它自己提供basicList沒有的長度計數器,修改相應操作維護長度計數。

Tracing 使用counter那它在最上層,同樣通過相同方式繼承Counter即可,然後修改相應操作添加過程列印的資訊。

  • 寫下GenVoca grammar
List            : TracedList[OptCounterList] | OptCounterListOptCounterList  : LengthList[BasicList] | BasicListBasicList       : PtrList[Config]Config          :   Copier       : PolymorphicCopier | MonomorphicCopier | EmptyCopier   Destroyer    : ElementDestroyer | EmptyDestroyer   TypeChecker  : DynamicTypeChecker | EmptyTypeChecker   ElementType  : [ElementType]   LengthType   : int | short | long | ...
實現細節

使用者可以自己定義一個符合自己需求的的config

struct TracedIntListConfig {  typedef int                             ElementType;  typedef const ElementType               ElementArgumentType;  typedef MonomorphicCopier<ElementType>  Copier;  typedef ElementDestroyer<ElementType>   Destroyer;  typedef DynamicTypeChecker<ElementType> TypeChecker;  typedef TracedList<PtrList<TracedIntlListConfig> >      FinalListType;};typedef TracedIntListConfig::FinalListType TracedIntList;
這裡要注意的是出現了模版參數循環相依性。這樣才能給出具體的最終List類型。
注,其實這個config不應該是最終提供給使用者,這些參數是最終決定List類型的,但不應由使用者設定這樣的參數,這個還是一個比較內部的config,例如具體採用什麼Destroyer對於使用者應該是透明的。
使用者可能會設定出使用MonomorphicCopier 和 EmptyDestroyer這樣會帶來記憶體流失的錯誤配置。
這裡面應該多一層抽象層,隔離開來。使用者只要聲明我用copy持有資料,或者說我用ownwed refernce,那麼庫的內部就會決定使用ElementDestroyer。
而使用者聲明要使用external refernce持有資料的話,庫的內部就會決定使用EmptyDestroyer,不做顯示的delete,即我不負責資料的釋放。
後面會給出如何加上這一層抽象,所謂的Generator方法,讓使用者更高層次的設定參數。
 
OK,我們先實現出一個基本的PtrList,這是一個最基本的list,它有很多策略參數,具體策略的實現使用者給出在Config中。
template <class Config_>class PtrList{public:  // export Config  typedef Config_ Config;  private:  // retrieve the needed types from the repository  typedef typename Config::ElementType          ElementType;  typedef typename Config::ElementArgumentType  ElementArgumentType;  typedef typename Config::Copier               Copier;  typedef typename Config::Destroyer            Destroyer;  typedef typename Config::TypeChecker          TypeChecker;  typedef typename Config::FinalListType        FinalListType;  // data members  ElementType*   head_;  FinalListType* tail_;   // note: not PtrList* but FinalListType*public:  PtrList (ElementArgumentType& h, FinalListType *t = 0)    : head_(0), tail_(t) { set_head(h); }  ~PtrList() { Destroyer::destroy(head_); }  void set_head(ElementArgumentType& h) {    TypeChecker::check(h);    head_ = Copier::copy(h);  }  ElementType& head() { return *head_; }  void set_tail(FinalListType *t) { tail_ = t; }  FinalListType* tail() const { return tail_; }};

 

//對這個最基本的list的使用

template <class List>void print_list(List* l) {  std::cout << "[ ";  for ( ; l; l = l->tail() ) std::cout << l->head() << " ";  std::cout << "]\n";}template <class List>void push_front(typename List::ElementArgumentType& e, List*& l) {  l = new List(e, l);}int main(){  typedef ListConfig::FinalListType List;  List* ls = 0;  push_front(1,ls);  push_front(2,ls);  push_front(3,ls);  print_list(ls);   // prints "3 2 1"}

注意list的實現中將一些操作轉交給別的類去做,也即某些策略參數,如Copier,Destoyer

template <class ElementType>struct MonomorphicCopier {  static ElementType* copy(const ElementType& e) {     return new ElementType(e);  }};template <class ElementType>struct PolymorphicCopier {  static ElementType* copy(const ElementType& e) {     return e.clone();    // polymorphic copy using   }                      // virtual member function clone()};template <class ElementType>struct EmptyCopier {  static ElementType* copy(ElementType& e) {   // note: not const    return &e;       // no copy  }};template <class ElementType>struct ElementDestroyer {  static void destroy(ElementType* e) { delete e; }};template <class ElementType>struct EmptyDestroyer {  static void destroy(ElementType* e) {}  // do nothing};template <class ElementType>struct DynamicTypeChecker {  static void check(const ElementType& e) {     assert(typeid(e)==typeid(ElementType));  }};template <class ElementType>struct EmptyTypeChecker {  static void check(const ElementType& e) {}};
 
最後更上層的laer採用inheritance-based wrappers實現。如LengthList
template <class BasicList>class LengthList : public BasicList{public:  // export config  typedef typename BasicList::Config Config;private:  // retrieve the needed types from the repository  typedef typename Config::ElementType          ElementType;  typedef typename Config::ElementArgumentType  ElementArgumentType;  typedef typename Config::LengthType           LengthType;  typedef typename Config::FinalListType        FinalListType;  LengthType length_;  LengthType compute_length() const {    return tail() ? tail()->length()+1 : 1;  }public:  LengthList (ElementArgumentType& h, FinalListType *t = 0)    : BasicList(h, t) {    length_ = compute_length();  }  void set_tail(FinalListType *t) {    BasicList::set_tail(t);    length_ = compute_length();  }  LengthType length() const { return length_; }};

Generators

下面給出為了給使用者更好的設定介面,進行抽象的方法。

enum Ownership {ext_ref, own_ref, cp};enum Morphology {mono, poly};enum CounterFlag {with_counter, no_counter};enum TracingFlag {with_tracing, no_tracing};
上面是使用者需要知道的,他們所應該關心的List配置參數。
template <bool condition, class Then, class Else>struct IF {  typedef Then RET;};template <class Then, class Else>struct IF<false, Then, Else> {  typedef Else RET;};

上面是利用模版偏特化,編譯期間選擇類型的一種技巧。

下面是具體的Generator的實現

template <  class       ElementType_,  Ownership   ownership    = cp,  Morphology  morphology   = mono,  CounterFlag counter_flag = no_counter,  TracingFlag tracing_flag = no_tracing,  class       LengthType_  = int>class LIST_GENERATOR{public:  // forward declaration of the configuration repository  struct Config;private:  // define the constants used for type selection  enum {    is_copy      = ownership==cp,    is_own_ref   = ownership==own_ref,    is_mono      = morphology==mono,    has_counter  = counter_flag==with_counter,    does_tracing = tracing_flag==with_tracing   };  // select the components  typedef typename  IF<is_copy || is_own_ref,     ElementDestroyer<ElementType_>,     EmptyDestroyer<ElementType_>  >::RET Destroyer_;  typedef typename  IF<is_mono,     DynamicTypeChecker<ElementType_>,     EmptyTypeChecker<ElementType_>  >::RET TypeChecker_;  typedef typename  IF<is_copy,     typename      IF<is_mono,MonomorphicCopier<ElementType_>,PolymorphicCopier<ElementType_> >::RET,     EmptyCopier<ElementType_>  >::RET Copier_;  typedef typename  IF<is_copy,     const ElementType_,     ElementType_  >::RET ElementArgumentType_;  // define the list type  typedef PtrList<Config> BasicList;  typedef typename  IF<has_counter,     LengthList<BasicList>,     BasicList  >::RET OptLengthList;  typedef typename  IF<does_tracing,     TracedList<OptLengthList>,     OptLengthList  >::RET List;public:  // return the final list type  typedef List RET;  // define the configuration repository  struct Config {    typedef ElementType_           ElementType;    typedef ElementArgumentType_   ElementArgumentType;    typedef Copier_                Copier;    typedef Destroyer_             Destroyer;    typedef TypeChecker_           TypeChecker;    typedef LengthType_            LengthType;    typedef RET                    FinalListType;  };};

 

使用者可以這樣使用來配置LIST
ypedef LIST_GENERATOR<int,cp,mono,no_counter,with_tracing>::RET    TracedIntList;

如果不需要traing

typedef LIST_GENERATOR<int>::RET IntList;

 

最後Shape,Square,Circle用到虛函數,因為我們操作一些列圖形幾何,需要動態多態。

而list沒有採用虛函數,只是繼承類對父類的覆蓋,因為對list沒有用到動態多態,直接用子類指標。

另外當前這個程式只是示範GenVoca構架的思想,其實還存在很多問題,比如當前list如果是拷貝構造而來或者owned reference,它的解構函式只能析構一個list的首元素,其它的

元素無法析構,需要寫類外面的一個destory函數,destory(list* l);
 
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.