Object Factories 物件工廠

2021-06-28 17:53:07 字數 2436 閱讀 9047

1,為什麼需要物件工廠?

我們建立乙個物件時,必須給出具體型別,new a也好,new b也罷。a,b都是物件的型別。我們向來反對寫hardcode,但卻在建立物件時必須hardcode。

如果需要根據使用者的輸入資訊,或是網路反饋資訊,或是文字檔案資訊來建立物件時,應該怎麼辦呢?

最初我們想法可能是這樣的,偽**

switch(info)

利用物件工廠,我們建立物件時得到了解脫,無需寫hardcode,不必給出型別,我們可以提供數字,字串,以及特定格式資訊來建立乙個物件。

好的,這就是物件工廠存在的意義!

2.簡單工廠不夠完美嗎?

是的,不夠完美。理由有三:

它使用了switch語句,因而帶有switch語句相應缺點,這是物件導向極力消除的東西(switch本身就是一種hardcode,所以物件導向:多型)

工廠類需要收集其生產的所有型別資訊,編譯依存性很強哦

想要新增乙個新型別,需要修改工廠**,而且通常不只一處。(引入標頭檔案,新增常量,修改switch等)

3.我們的目標是什麼?

工廠不使用switch語句

工廠可伸縮,可以動態新增或刪除所生產的產品

可以對工廠提供構造物件的原料,且數量可變

泛化工廠,可以無需編碼支援不同型別抽象產品

減少記憶體管理複雜度

盡量做到型別安全

struct package; 

template class typelist {};

template class factoryimpl

)).second;

}template bool unregister(const identifiertype& id)

return associations_.erase(id)==1;

}template unique_ptrcreateobject(const identifiertype& id,arg&&... args)

assert(false);

} private:

typedef std::unordered_mapassocmap;

assocmap associations_;

};

**釋疑:

17行,在幹什麼?是這樣的,客戶傳過來的function物件很可能在呼叫時已經釋放了,如果我們不儲存乙個function物件,僅僅將其function物件指標轉變為void*,而之後我們在把void*轉換為function物件指標,呼叫時如果function物件已經釋放了,那麼必然出現記憶體錯誤。

恰恰因為17行原因,一切變得非常棘手。最難實現的是unregister函式,這也是這段**最大的敗筆。unregister強迫客戶顯式提供正確的型別,否則不能工作。為什麼一定要提供型別?因為型別擦除後,編譯器已無法知道它真的型別,需要明確進行強制轉換後,才能在vector中刪除function物件。不然,記憶體洩露直至程序退出。

所有函式都加入assert,防止客戶出錯,提供不正確引數將導致程序終止。

**中使用std::function和unique_ptr, std::function為不同形式的可呼叫體包裝為相同型別,並保持統一的呼叫。unique_ptr則是為了方便記憶體管理。

1-7package結構體中 func指向使用者提供function物件,funcset指向register函式中static vector,index為其在func指標在funcset中位置,sig可以理解為函式簽名

因為沒有在類模板使用可變引數,所以實現起來很是費勁,我現在倒覺得可以使用類模板帶可變引數實現。這樣類模板例項化的類,雖然只支援註冊和呼叫引數固定呼叫體,但具有編譯期型別檢查的好處,register和unregister均很容易實現。使用者需要時,根據需要例項化模板即可。

template class factory

bool unregister(const identifiertype& id)

unique_ptrcreateobject(const identifiertype& id,arg&&... args)

assert(false);

}private:

typedef std::unordered_map(arg...)> > assocmap;

assocmap associations_;

};

需要注意一下,這**因為使用變長模板引數,所以無法使用預設模板引數。

使用第一種實現方式,你只需要乙個物件,即可搞定所有需求(unregister比較鬧心)。具有執行期型別檢查。

使用第二種實現方式,你要在不同場合下,例項化出類,並且建立出物件只支援註冊某種呼叫格式呼叫體。而且具有編譯期型別檢查。

雖然在第一種方式上,下了很多功夫,但是我還是不推薦這種做法,除非真的有萬不得已需要,非要把**設計成這樣。

初學軟工 物件導向的技術

物件導向 物件 類 繼承 通訊 類與物件還有之間通訊的關係如圖 大概的關係圖就是這樣,其實類和物件的關係我們在以前的學習中就已經知道不少了,在現在的學習中有有了訊息的概念,物件之間的訊息如何更好傳遞是我們在軟體工程中要掌握的。物件向物件傳送的服務請求 1 服務物件的標識 2 服務標識 3 輸入資訊 ...

飯工和碗工

飯工和碗工 飯工和碗工 一看這兩個名詞,你一定費解。聽過鉗工電工清潔工搬運工,或是張工王工,那聽過這個稱謂呀。甭急,這是我的發明,你聽我慢慢道來。我兒子兒媳都在天津工作,住的地方到工作單位較遠。早晨六點半出發,晚上七點後回家。若遇見堵車,回到家就八點多了。他們倆既辛苦又繁忙。我和老伴住在陝西老家,身...

飯工和碗工

飯工和碗工 飯工和碗工 一看這兩個名詞,你一定費解。聽過鉗工電工清潔工搬運工,或是張工王工,那聽過這個稱謂呀。甭急,這是我的發明,你聽我慢慢道來。我兒子兒媳都在天津工作,住的地方到工作單位較遠。早晨六點半出發,晚上七點後回家。若遇見堵車,回到家就八點多了。他們倆既辛苦又繁忙。我和老伴住在陝西老家,身...