條款38:通過複合塑膜出has-a或"根據某物實現"

條款38:通過複合塑膜出has-a或"根據某物實現"

內容:
      所謂的複合就是類型之間的一種關係,它的基本的表現形式在我們平時的編寫代碼過程當中常常出現,比如你準備設計一個類的時候,你寫出來的類的對象不是保護了其它的對象?呵呵,對了,這就叫複合.舉個例子:
      class Address{...};
      class PhoneNumber{...};
      class Person{
          ...
      private:
          std::string name_;
          Address address_;
          PhoneNumber voiceNumber_;
          PhoneNumber faxNumber_;
      };
      本例中Person就包含了string,Address,PhoneNum合成成分物,它們之間就構成了複合的關係,是不是很簡單?呵呵!在前面的條款32中我們提到public繼承體系下的子類與父類之間帶有"is-a"的意義,而在這裏,複合也有自己的意義,它有兩個實際的意義,複合意味着"has-a"(有一個)或者is-implemented-in-term-of(根據某物實現),前者的對象屬於應用域部分,相當於你塑造的世界中的某些事物,例如人,汽車等.後者的對象則是實現細節人工產品(這產品現實世界中是沒有的),像什麼mutex,list,container等等,這些對象是你的軟件的實現領域.這兩個意義理解起來並不是很困難,但在實際的編寫代碼中如何區分這兩種對象關係卻並不是你想的那麼容易.
      現在的你希望有一個template class去表現一組不重複的對象組成的set(集合),當然你首先想到的就是STL中的set容器,我們都知道STL中set容器是通過balanced search trees實現而成的,它在查找、安插、移除元素時保證較好的速度效率,但卻佔用了足夠客觀的空間,如果你的程序的空間比速度要重要,那麼標準庫的set就不是我們想要的東西了,那怎麼辦?很簡單嘛,你自己寫一個不就得了嘛,呵呵.
      考慮到代碼的複用,我就想盡量能用現成的代碼來模擬它,要是自己親自每一步都來寫,得花我不少時間呢?呵呵,沒辦法,我這人就是比較懶,想來想去,我決定底層用linked list來實現,因爲標準庫中有list容器!可以把set對象看成list對象,於是我就這樣聲明瞭set template:
      template<typename T>
      class Set:public std::list<T>{...}
      看起來似乎不錯,不過稍微細想了一下,覺得有些地方不得勁:如果Set是list子類的話,那麼list裏面的每一件事情對Set來說應該都適用,但list可以含重複元素Set卻不可以,暈死!所以說將這兩個類強扭成父子關係並不是很合適,其實在這裏你的Set對象可以由一個list塑膜出來,你可以這樣做:
      template <class T>
      class Set{
      public:
             bool member(const T& item)const{
                     return std::find( list_.begin(), list_.end(), item ) != list_.end() );
             }
             void insert(const T& item){
                    if( !member(item) )
                        list_.push_back(item);
             }
             void remove(const T& item){
                    typename std::list<T>::iterator iter = std::find( list_.begin(),
                                                                                               list_.end(),
                                                                                               item );
                    if( iter != list_.end() )
                        list_.erase(iter);
             }
             size_t size()const{
                    return list_.size();
             }
      private:
             std::list<T> list_;
      };
      今天的內容比較少,也比較簡單,但是在平時的編寫代碼的時候我們卻經常遇到,所以大家要注意.
      請記住:
      ■ 複合的意義和public繼承完全不同.
      ■ 在應用域,複合意味着has-a(有一個).在實現域,複合意味着is-implemented-in-terms-of(根據某物實現出).

發佈了62 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章