400-888-5228

侯捷再次受邀C++設(shè)計模式企業(yè)培訓(xùn)

發(fā)布時間:2014.05.11

4月22-24日,艾威培訓(xùn)再次為杭州某企業(yè)提供了C++設(shè)計模式培訓(xùn)課程,此次培訓(xùn)課程原定40人的培訓(xùn)規(guī)模,猛增至120余人旁聽,大家均表示能夠聽到侯老師的精湛的技術(shù)講解實(shí)屬不宜,都不想放棄此次學(xué)習(xí)的機(jī)會。侯捷老師C++培訓(xùn)課程列表
該課程結(jié)合實(shí)際代碼和應(yīng)用,對實(shí)際項目開發(fā)非常有益。引用部分學(xué)員參加侯捷老師的培訓(xùn)內(nèi)容及心得如下:
???? 面向?qū)ο笾械暮铣珊屠^承關(guān)系
通常擴(kuò)展一個類的功能主要有兩種方式,一種是大家很熟悉的繼承(inheritance),另一種就是合成(composition),很多初學(xué) OO(面向?qū)ο螅┎⒂幸恍┙?jīng)驗(yàn)都很容易搞混這個的區(qū)別,其實(shí)很簡單,繼承是解決Is-a的問題,而合成是解決Has-a的問題。比如說小鳥有兩個翅膀,就 是合成,而鳥是一種飛禽,就是繼承了,設(shè)計一個“小鳥”的類,它繼承自”飛禽”,就具有“飛”的特性,但要用合成的方法“包含”一個“翅膀”的類才具有真 正“飛”的功能。
別看這兩個定義很簡單,其實(shí)很多人都犯過錯誤,包括Java類庫的設(shè)計者,他們就把Properties直接“繼承”自Hashtable了,這里其實(shí)應(yīng)該用“合成”。
講到合成,就應(yīng)該說說聚合(Aggregation),它是描述整體和局部的關(guān)系,合成其實(shí)是一種“強(qiáng)烈”的聚合,它與局部具有相同的生命周期, “容納”局部的“對象”,而聚合只是“容納”局部的一個“指針”。比如說,人和腦袋就是合成,而汽車與發(fā)動機(jī)就是聚合,改裝汽車可以任意替換更好的發(fā)動 機(jī),而人的腦袋就不行(目前是這樣:)
聚合在UML中是以空心棱形的箭頭表示,合成是以實(shí)心棱形的箭頭表示。
還有一種關(guān)系叫委托(Delegation),委托是一種讓合成(composition)變得像繼承(inheritance)的復(fù)用能力一樣強(qiáng) 大的方式。(a way of making composition as powerful for reuse as inheritance [Lie86, JZ91] )在委托中,兩個對象在處理一個請求的時候發(fā)生關(guān)聯(lián):一個接收的對象委派操作給它的委托對象。這跟子類(subclass)延遲請求(deferring requests)給它的父類(parent class)來實(shí)現(xiàn)類似。但是在繼承里,一個被繼承的操作(inherited operation)通過this成員變量能夠經(jīng)常引用到那個接收的對象。為了在委托里達(dá)到同樣的效果,接受者傳遞它自己給它的委托者,以便被委托的操作 能夠引用到這個接收者。
再說一下繼承(Inheritance),它是將基類(base-class)所有一切(包括 private )都繼承下來,所以假如你想實(shí)現(xiàn)一個新的類,只想繼承一部分,就用合成(Composition)別用繼承?;蛘吒M(jìn)一步來講,如果你想改造一個類,想改 造一些接口(interface),也建議用合成,通過轉(zhuǎn)調(diào)內(nèi)部對象的方法實(shí)現(xiàn),別用虛函數(shù)(virtual function)。這是非常符合_基本的OCP設(shè)計原則(Open-Closed Principle ,開閉原則)的方式了。
???? 類的構(gòu)造和析構(gòu)
類的構(gòu)造和析構(gòu)是_基礎(chǔ)的知識了,任何一個類的對象產(chǎn)生和銷毀都必須有這兩個步驟,但是它們是如何工作的,編譯器是如何制造缺省的ctor和dtor的,估計少有人關(guān)注了。
一個類的對象的產(chǎn)生,會依次從它_里面的類開始構(gòu)造,同一個類會跟據(jù)內(nèi)部類成員定義的順序依次構(gòu)造。類對象的銷毀的過程則相反?;惖臉?gòu)造器會在用 戶定義的ctor之前調(diào)用,基類的析構(gòu)則是在用戶定義的dtor之后進(jìn)行。熟悉這些過程,非常有利于設(shè)計出_的類庫,也不容易出現(xiàn)內(nèi)存泄露和資源耗盡等 問題。下面舉個例子更容易理解:
更復(fù)雜的繼承關(guān)系以及多重繼承的構(gòu)造和析構(gòu)過程類似,有興趣的人可以寫程序測試:)
還有一個問題,編譯器會在什么時候自動產(chǎn)生ctor和dtor的呢,又是如何產(chǎn)生的呢
其實(shí)很簡單,當(dāng)你沒有寫缺省構(gòu)造函數(shù)(default constructor)和缺省析構(gòu)函數(shù)(default destructor)的時候,編譯器就會給你自動生成一個,換句話說,任何類都有構(gòu)造函數(shù)和析構(gòu)函數(shù),雖然有時候什么都不做,還有復(fù)制構(gòu)造函數(shù) (copy ctor)也會自動生成。但是如何產(chǎn)生會跟你的類的成員有關(guān)。如果成員都是原生類型,還有如果類成員也全部為原生類型,ctor將只會跟普通變量定義的初 始化一樣,給一個初值,dtor則什么都不做,copy ctor則會使用內(nèi)存復(fù)制(memcpy)的方式復(fù)制對象。如果成員包含一個或多個類成員,而且至少有一個類成員定義有缺省構(gòu)造方法,則產(chǎn)生的ctor會 依次調(diào)用每個成員的ctor。dtor和copy-ctor產(chǎn)生方法類似。(詳見《Inside the C++ Object Model》)
???? 多態(tài)(Polymorphism)和虛函數(shù)(Virtual function)
多態(tài)是面向?qū)ο蟮幕咎匦?,C++里是通過virtual關(guān)鍵詞來提供的,它是通過在類對象里加入vtbl虛函數(shù)表來實(shí)現(xiàn)的,這一點(diǎn)相信大部分程序 員都很清楚,不過怎么做到多態(tài)功能估計了解的不多了。要詳細(xì)了解,還請閱讀《 Inside the C++ Object Model》一書,下面簡單介紹一下原理。
一般編譯都會給包含有virtual function的類頭部(有的編譯也會放到底部,比如 VC )增加一個成員vptr指針,指向一個 vtbl 虛函數(shù)表,為定長數(shù)組,大小是所有帶virtual的函數(shù)數(shù)目再加 1 。虛函數(shù)指針從 vtbl[1] 開始,按照定義順序,指向特定的函數(shù)實(shí)現(xiàn)。如果子類定義了父類中帶virtual的函數(shù),則vtbl相應(yīng)的指針指向子類的函數(shù)實(shí)現(xiàn),否則就指向父類的實(shí) 現(xiàn)。另外再說明一點(diǎn),其中vtbl[0]是有別的用途,用來存放類型信息,做dynamic_cast 用途。
仍以上面的例子為例,如下的代碼編譯器是如何處理:
A *p = new D(); // up-cast
p->vfunc1(); // 編譯器會轉(zhuǎn)化為如下代碼
(*(p->vptr))[n](p); // n 為編譯期確定的固定數(shù),即相應(yīng) virtual function
// 所在位置
需要牢記一點(diǎn),總是讓 base class 擁有 virtual destructor 。因?yàn)楫?dāng)如下操作時
delete p;
如果A和B的析構(gòu)函數(shù)不是虛函數(shù),則不會調(diào)用子類D的dtor,就有可能造成內(nèi)存泄露或者資源沒有釋放等嚴(yán)重問題。如果給base class加了virtual dtor,由于有多態(tài)的特性,就會自動調(diào)用subclass的dtor,接下來就會上面的介紹,依次調(diào)用各個base class的 dtor,因而就沒有問題了。
C++ template即模板技術(shù)是實(shí)現(xiàn)泛型編程技術(shù)的,能夠使得寫一份代碼可以應(yīng)用到類似用途的不同地方。模板技術(shù)其實(shí)原理比較簡單,但是使用還是比較復(fù)雜 的,看看 STL 源碼就知道了,如果還不相信,再看看Boost代碼好了,會把你搞得暈頭轉(zhuǎn)向。候捷老師把這個技術(shù)講解得非常清楚易懂,還具體分析了 STL 里各個大組件的運(yùn)作原理,我這里就不講述了,基本都是源碼的剖析,請閱讀候捷老師的《STL源碼剖析》一書。
???? C++template和STLcontainers
在講解STL中用模板如何實(shí)現(xiàn)function class(實(shí)現(xiàn)函數(shù)功能的類,在stl_functions.h)中。有這樣一段代碼

template <class _Operation>

class binder1st

?: public unary_function<typename _Operation::second_argument_type,

????????????????????????? typename _Operation::result_type> {

protected:

?_Operation op;

?typename _Operation::first_argument_type value;

public:

?binder1st(const _Operation& __x,

??????????? const typename _Operation::first_argument_type& __y)

????? : op(__x), value(__y) {}

?typename _Operation::result_type

?operator()(const typename _Operation::second_argument_type& __x) const {

??? return op(value, __x);

?}

};

有人提出上面_Operation op;為什么不定義為引用,如_Operation &op;呢。我的想法如下,因?yàn)闃?gòu)造方法為
binder1st(const _Operation& __x, // 這里為const類型
const typename _Operation::first_argument_type& __y)
傳入的參數(shù)為const類型,這時不應(yīng)在本調(diào)用方法(這里是構(gòu)造方法)之外使用引用或指針指向它,因?yàn)閹onst T &t的參數(shù)一般情況都視為臨時對象,很有可能是在方法調(diào)用的時候臨時產(chǎn)生的,比如說自動轉(zhuǎn)型產(chǎn)生的臨時對象都是const T &類型,它的生命周期都在此方法調(diào)用期間內(nèi),方法調(diào)用結(jié)束即被銷毀,所以就不能在方法外部用引用或指針之類指向它了。舉例來說,可能比較容易理 解,比如大家常用的string類,假如有一個方法和調(diào)用如下:
void func(const string &s);
func("abcdfd");
這個時候就會出現(xiàn)自動轉(zhuǎn)型行為,編譯器會做如下處理
func(string("abcdfd"));
即產(chǎn)生一個臨時的string對象,這個對象是以const類型傳入的。假如你的方法定義改成如下
void func(string &s);
現(xiàn)在大部分編譯器嚴(yán)格的處理都會報錯,以前的VC6就不會,但是好像_新的VC2005 也報錯了。
這是其中一個原因,還有一個原因我認(rèn)為是_Operation類只是一個 function class,沒有成員,所以做復(fù)制構(gòu)造也不會有多大的開銷,基本不會影響效率。再加模板和inline方法的處理,編譯器經(jīng)過優(yōu)化,應(yīng)該都不會產(chǎn)生臨時對 象了,所以也不必用引用了。不過我覺得_重要是上面_個原因。
???? 內(nèi)存池和小對象分配器(memory pool,small object allocator)
候捷老師在內(nèi)存池方面也有很豐富的研究經(jīng)驗(yàn),他基本將目前主流的內(nèi)存池實(shí)作都剖析了一遍,介紹了它們各自的特點(diǎn),以及如何與上層框架的配合。內(nèi)存池 是一個非常基礎(chǔ)也非常關(guān)鍵的底層庫,一般大型的框架自己都帶有一個內(nèi)存池庫,比如STL、MFC等。即使在目前內(nèi)存比較便宜的今天,內(nèi)存資源也是_寶貴的 系統(tǒng)資源之一,設(shè)計一個_的內(nèi)存池對提高系統(tǒng)的效率和穩(wěn)定性都非常有幫助,尤其是設(shè)計專門針對小內(nèi)存對象(一般低于128字節(jié))的分配器非常重要,因?yàn)?這樣對象分配和釋放非常頻繁,只用簡單的malloc()和free()來處理非常影響效率,不是一個_的設(shè)計。下面我簡要介紹一下目前主流內(nèi)存池設(shè)計 的特點(diǎn),以及我自己的想法,另外再加一個候捷老師沒提到ACE中的內(nèi)存池管理器的設(shè)計特點(diǎn)。
???? SGI STL中的內(nèi)存分配器(allocator)
SGI STL 的 allocator 應(yīng)該是目前設(shè)計__的 C++ 內(nèi)存分配器之一了,它的運(yùn)作原理候捷老師在《STL源碼剖析》里講解得非常清楚。基本思路是設(shè)計一個free_list[16]數(shù)組,負(fù)責(zé)管理從8 bytes到128 bytes 不同大小的內(nèi)存塊(chunk),每一個內(nèi)存塊都由連續(xù)的固定大?。╢ixed size block)的很多chunk組成,并用指針鏈表串接起來。比如說
free_list[3]->start_notuse->next_notuse->next_notuse->...->end_notuse;
當(dāng)用戶要獲取此大小的內(nèi)存時,就在free_list的鏈表找一個_近的free chunk回傳給用戶,同時將此chunk從free_list里刪除,即把此chunk前后chunk指針鏈結(jié)起來。用戶使用完釋放的時候,則把此 chunk放回到free_list中,應(yīng)該是放到_前面的start_free的位置。這樣經(jīng)過若干次allocator和deallocator 后,free_list中的鏈表可能并不像初始的時候那么是chunk按內(nèi)存分布位置依次鏈接的。假如free_list中不夠時,allocator會 自動再分配一塊新的較大的內(nèi)存區(qū)塊來加入到free_list鏈表中。
可以自動管理多種不同大小內(nèi)存塊并可以自動增長的內(nèi)存池,這是 SGI STL 分配器設(shè)計的特點(diǎn)。
??? Loki中的小對象分配器(small object allocator)
Loki的分配器與 SGI STL的原理類似,不同之處是它管理free_list不是固定大小的數(shù)組,而是用一個vector來實(shí)現(xiàn),因此可以用戶指定fixed size block的大小,不像 SGI STL是固定_大128 bytes的。另外它管理free chunks的方式也不太一樣,Loki是由一列記錄了free block位置等信息的Chunk類的鏈表來維護(hù)的,free blocks則是分布在另外一個連續(xù)的大內(nèi)存區(qū)間中。而且free Chunks也可以根據(jù)使用情況自動增長和減少合適的數(shù)目,避免內(nèi)存分配得過多或者過少。
Loki的分配器使用也不太一樣,可以直接調(diào)用,如下
SmallObjAllocator myAlloc(2048, 256); // 參數(shù) 1 為 chunk size
// 參數(shù) 2 為 max fixed size block size
// 可以用于小于 256 bytes 的各種大小內(nèi)存的分配
void *p1 = (void*)myAlloc.Allocate(20);
void *p2 = (void*)myAlloc.Allocate(100);
void *p3 = (void*)myAlloc.Allocate(256);
void *p4 = (void*)myAlloc.Allocate(300); // 大于 256 將轉(zhuǎn)交給系統(tǒng)處理
myAlloc.Deallocate(p1,20);
myAlloc.Deallocate(p2,100);
myAlloc.Deallocate(p3,256);
myAlloc.Deallocate(p4,300);
???? MFC的CPlex和CPtrList(扮演memory pool角色)
CPlex任務(wù)比較簡單,只負(fù)責(zé)管理一大塊memory并串接起來,用戶每次獲取都返回一大塊。分割由使用者(如Collection classes , CFixedAlloc)將這一大塊切割為一個個小的內(nèi)存塊。
CPtrList 則負(fù)責(zé)管理這些切割后的小內(nèi)存塊,這一點(diǎn)有點(diǎn)類似 Loki 中的 free Chunks ,不過要簡單多了。
MFC還有一個類叫CFixedAlloc,它是提供給應(yīng)用類來分配固定大?。ǜ鶕?jù)具體應(yīng)用類的大小)的內(nèi)存分配器。通過在應(yīng)用類中定義 DECLARE_FIXED_ALLOC(Foo)和IMPLEMENT_FIXED_ALLOC(Foo)兩個宏來實(shí)現(xiàn)。
???? Boost的object_pool
Boost中的object_pool也是一個可以根據(jù)用戶具體應(yīng)用類的大小來分配內(nèi)存塊的,也是通過維護(hù)一個 free nodes 的鏈表來管理的??梢宰詣釉黾?nodes塊,初始是32個nodes,每次增加都以兩倍數(shù)向 system heap 要內(nèi)存塊。 object_pool 管理的內(nèi)存塊需要在其對象銷毀的時候才返還給 system heap 。
ACE 中的 ACE_Cached_Allocator 和 ACE_Free_List
ACE 框架中也有一個可以維護(hù)固定大小的內(nèi)存塊的分配器,原理與上面講的內(nèi)存池都差不多。它是通過在ACE_Cached_Allocator中定義個 Free_list鏈表來管理一個連續(xù)的大內(nèi)存塊的,里面包含很多小的固定大小的未使用的區(qū)塊(free chunk),同時還使用ACE_unbounded_Set維護(hù)一個已使用的chuncks,管理方式與上面講的內(nèi)存池類似。也可以指定chunks的 數(shù)目,也可以自動增長,定義大致如下所示:

template<class T>

class ACE_Cached_Allocator : public ACE_New_Allocator<T> {

public:

??? // Create a cached memory pool with @a n_chunks chunks

??? // each with sizeof (TYPE) size.

??? ACE_Cached_Allocator(SIZET n_chunks = ACE_DEFAULT_INIT_CHUNKS);

??? T* allocate();

??? void deallocate(T* p);

private:

??? // List of memory that we have allocated.

??? Fast_Unbounded_Set<char *> _allocated_chunks;

??? // Maintain a cached memory free list.

??? ACE_Cached_Free_List<ACE_Cached_Mem_Pool_Node<T> > _free_list;

};

???? 設(shè)計模式
_后一個主題重點(diǎn)講講設(shè)計模式,設(shè)計模式現(xiàn)在已經(jīng)應(yīng)用很廣泛了,可以說是無處不在。設(shè)計模式現(xiàn)在對程序員是非常的重要,甚至到了不懂設(shè)計模式就不算 真正的程序員一樣。不過設(shè)計模式卻又是非常高階的理論,需要有多年的編程經(jīng)驗(yàn)才能真正領(lǐng)悟,所以學(xué)習(xí)起來非常頭痛。因?yàn)樗览矸浅:唵危菂s非常抽象, 候捷老師通過一大堆實(shí)際案例給我們逐個講述了幾個常用的模式的區(qū)別和用法。設(shè)計模式_經(jīng)典_權(quán)威當(dāng)屬著名的有字天書 GoF 的《 Design Patterns 》了,我結(jié)合自己學(xué)習(xí)和實(shí)踐的體會介紹一下幾個模式。
???? 結(jié)構(gòu)型模式之Composite(合成模式)
GoF的定義:Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects.翻譯為中文大致意思是:將對象 (s) 組成為樹狀結(jié)構(gòu),用以表示“局部 - 整體”的層次體系,使得讓 clients 可以以一致的方式對待“單個對象”和“合成對象”。
比較典型的例子就是文件系統(tǒng)中“文件”和“目錄”的關(guān)系,還有Windows窗口系統(tǒng)也是,在一個窗口中還可以開另一個窗口,多個窗口組合成的窗口 還可以當(dāng)作一個窗口放入另一個窗口中,比如在Word中打開多個文檔就是這種情況。Composite模式的好處就是使得clients調(diào)用簡單,可以用 一致的接口處理單個對象或者多個單一對象組合成的對象。
實(shí)例:Java swing library 中 Component , Label , Container就是Composite模式的應(yīng)用。其中 Label 和 Container 都繼承自 Component ,但是Container中只是一個存放Component的數(shù)組,所以Container中就可以放很多Component,比如ScrollPane 就是繼承自Container,它可以放Label,還有List,Scrollbar等等,甚至還可以放一個ScrollPane,所以就達(dá)到了 Composite模式的效果,簡化了 client的使用。
???? 結(jié)構(gòu)型模式之 Decorator(裝飾模式)
GoF 的定義: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. 翻譯為中文大致的意思是:以動態(tài)的方式給一個對象添加一些額外的職責(zé),使得不必進(jìn)行 subclassing 就能擴(kuò)展功能。
Decorator模式與Composite 模式的區(qū)別就是它只內(nèi)含一個 component object field ,而 Composite 則內(nèi)含一個 collection of component field 。 Decorator 負(fù)責(zé)將一個對象“裝飾”起來,做一些“改造或者擴(kuò)展”,提供額外的功能,它只針對一個 class 。而 Composite 是一組“類似”的對象及其容納它們的容器一視同仁,使得 client 更簡單地處理單個對象和一組對象。它們目的不一樣。
實(shí)例: Java IO library 中 BufferedReader , Reader 之間使用的就是 Decorator 模式,其中 BufferedReader 繼承自 Reader ,同時它內(nèi)部含有一個 Reader 引用,它是通過另一個 Reader 對象構(gòu)造而來,因此就為 Reader 提供更多的功能,如帶緩沖的 Reader 。使用非常簡單,只需要如此定義:
Reader in = new BufferedReader(new FileReader("test.txt"));
就為文件讀取增加了帶緩沖的 IO 功能,非常方便。還可以多個 Decorator 的類組合使用,可以提供更強(qiáng)大的功能,多使用一下 Java IO library 就會體會到。
??? 行為模式之Observer(觀察者模式)
GoF的定義: Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
翻譯為中文大致意思是:在 objects 之間定義一個“一對多”的依賴關(guān)系,使得當(dāng)這個 object 改變狀態(tài)時,所有依賴它的 objects 都能獲得通知并自動更新。
Observer是用于做“通知”用途的,就像“ publish-subscribe ”,它能夠做到注冊需要通知的對象,并自動通知它們來更新,它們都是被動地被通知,而不是主動觀察。
實(shí)例:MFC 里 CView 和 CDocument 之間就是一個觀察者模式, CView 是 Observer 即觀察者, CDocument 是 Observable 即被觀察者,當(dāng) CDocument 修改后會自動通知所有的 CView 對象來自動更新它們顯示的內(nèi)容,這一點(diǎn)可以用 Word 很容易試出來。還有_新的 Windows 圖形界面框架 WinForm 中的窗口之間消息傳遞等用的也是 Observer 模式,一個窗口發(fā)生改變時會自動通知所有與它有關(guān)系的窗口,來自動更新信息等,這一點(diǎn) Jeffrey Richter 可以作證
行為模式之Template Method(模板方法)
GoF的定義:Define the skeleton of an algorithm in an operation, deferring somesteps to subclasses. Template Method lets subclasses redefine certain steps ofan algorithm without changing the algorithm's structure. 翻譯為中文大致意思是:定義一個算法的骨干,延緩其中某些步驟以便在 subclasses 中定義它們。 Template Method 使得 subclasses 在不改變算法的體系結(jié)構(gòu)的前提下得到重新定義算法內(nèi)的某些步驟。
Template Method其實(shí)_常用了,在C++里的應(yīng)用就是使用 virtual function 實(shí)現(xiàn)的,給一個base class 定義一個virtual方法,但是不實(shí)現(xiàn),而是在它的subclasses 中實(shí)現(xiàn)它,這就是Template Method。這個模式的好處顯而易見,就是在你設(shè)計base class的時候并不知道這個方法具體如何實(shí)現(xiàn),但是卻需要在base class里某個地方需要調(diào)用它以完成一個完整的算法,這時候就是需要用這個模式了。
實(shí)例:例子太多了,到處都是。
???? 行為模式之Strategy(策略模式)
GoF的定義: Define a family of algorithms, encapsulate each one, and make theminterchangeable. Strategy lets the algorithm vary independently from client that use it. 翻譯為中文大致意思是:定義一族算法,把每個算法封裝起來,并使它們可以相互替換。 Stategy 使得算法給 client 使用的時候變得完全獨(dú)立。
Strategy模式完全符合 OCP ( Open-Closed Principle ,開閉原則),可以在不需要做 subclass 更不需要修改 base class 的情況下在 Runtime 的時候擴(kuò)展系統(tǒng)的功能,它不像 Template Method 需要 subclass 才能擴(kuò)展新的功能。
實(shí)例: Strategy 典型的應(yīng)用是在薪資系統(tǒng)中,當(dāng)定義 Employee 類的時候,如果使用 Template Method 模式,就無法更改員工領(lǐng)薪資的方式等,比如員工晉升的時候。這時候就需要用 Strategy 模式,在 Employee 中定義一個指針指向具體的 PaymentMethod 對象,如果需要更改領(lǐng)薪資的方式的時候,只需要將它指向新的 PaymentMehtod 實(shí)現(xiàn)就可以了。
???? 結(jié)構(gòu)模式之Adapter(適配器模式)
GoF的定義: Convert the interface of a class into another interface clients expect.Adapter lets classes work together that couldn't otherwise because of incompatible interfaces. 翻譯為中文大致意思是:將一個 class 的接口轉(zhuǎn)換為另外一種 clients 所期望的接口,使得這些 classes 可以更好地協(xié)同工作起來,而不至于因?yàn)閯e的不兼容的問題所影響。
Adapter 模式屬于結(jié)構(gòu)型模式,需要有 Adaptee (被適配者)和 Adaptor (適配器)兩個對象。一般情況下,我們通過繼承( Inheritance )或者合成( Composition )的方式擴(kuò)展類的功能后,會產(chǎn)生很多接口形式不同的類,但是我們想用同樣的方式調(diào)用它們,又不想改造它們(否則違反 OCP 原則),怎么辦呢?這種情況下就需要用到 Adapter 模式了,這些被“改造”的類就叫做 Adaptee ,而我們就需要寫個 Adaptor 類來轉(zhuǎn)調(diào)它們,把調(diào)用的接口改成統(tǒng)一的形式。
實(shí)例:Java IO library 里的InputStreamReader 就是一個 Adapter ,它負(fù)責(zé)將 InputStream 對象轉(zhuǎn)換為 Reader 對象的接口形式,使得用戶可以像使用其它 Reader 一樣的方式來使用InputStream對象,比如

InputStreamReader isr = new InputStreamReader(

new FileInputStream("test.txt"));

BufferedReader br = new BufferedReader(isr);

String line = br.readLine();

這就做到了在不改造原來設(shè)計的類的接口的情況,擴(kuò)展了類的應(yīng)用范圍。一般情況下, Adapter 模式需要結(jié)合 Factory 模式和 Proxy 模式來使用,使得接口的訪問更加一致性,更容易改造系統(tǒng)。
???? 結(jié)構(gòu)模式之Facade(外觀模式)
GoF的定義: Provide a unified interface to a set of interfaces in a subsystem.Facade defines a higher-level interface that makes the subsystem easier to use. 翻譯為中文大致意思是:為一個子系統(tǒng)的一批接口提供一個統(tǒng)一標(biāo)準(zhǔn)的接口, Facade 定義更高層次的接口,使得子系統(tǒng)更容易使用。
Facade 模式我感覺是一個更高層次的 Adapter ,它是用來理順系統(tǒng)之間的關(guān)系,降低系統(tǒng)間的耦合度的常用方法,其實(shí)我們可能在設(shè)計系統(tǒng)的時候就在不知不覺地應(yīng)用這個模式了。大部分將業(yè)務(wù)邏輯層和表示層 分離的框架都是應(yīng)用 Facade 模式實(shí)現(xiàn)的,使得上層使用者完全不必理會底層的實(shí)現(xiàn),卻又有統(tǒng)一的使用界面。
實(shí)例: J2EE EJB 中 Session Bean 就是一種典型的 Facade 模式,即 Session Facade 。它完全將業(yè)務(wù)對象封裝起來, EJB 客戶端訪問 Session Bean 來代替訪問業(yè)務(wù)對象。這就大大簡化了 EJB 的系統(tǒng)結(jié)構(gòu), Session Bean 就是相當(dāng)于一個外觀,也相當(dāng)于一個總管,把業(yè)務(wù)對象都管理起來,不讓客戶端直接“接觸”到它們。

侯捷再次受邀C++設(shè)計模式企業(yè)培訓(xùn) -- 第1張

侯捷老師,原名侯俊杰,年近花甲的侯老師從業(yè)30余年,編譯與著作40余本書籍,堪稱華人C++教父級專家,在C++底層控制、C++標(biāo)準(zhǔn)庫、C++源碼、C++內(nèi)訓(xùn)管理方便均有深入研究。學(xué)生遍及五湖四海(美國、加拿大、澳大利亞、臺北、香港、新加坡、上海、北京、廣州等地);

【艾威(中國)】簡介:

  艾威(AVTECH)總部 設(shè)在美國NEW JERSEY,是北美排行_的專業(yè)培訓(xùn)機(jī)構(gòu),設(shè)有4大分校,數(shù)十個培訓(xùn)點(diǎn)遍布北美、西歐和東亞;2000年進(jìn)入中國,以培養(yǎng)國際化的中高端信息人才為己任,專注于國際前沿的新技術(shù)研發(fā)與信息科技新興行業(yè)的開拓教育。

艾威培訓(xùn)(Avtech Institute of Technology),源于美國,始于1998;是北美著名的培訓(xùn)機(jī)構(gòu),公司總部位于美國新澤西州,2000年進(jìn)入中國,以培養(yǎng)國際化的中高端信息人才為己任,專注于國際前沿的新技術(shù)研發(fā)新興行業(yè)的開拓教育,艾威主要的服務(wù)為培訓(xùn)與咨詢兩大類,目前培訓(xùn)的主要產(chǎn)品有:項目管理培訓(xùn)、IT管理培訓(xùn)、IT技術(shù)培訓(xùn)、云計算大數(shù)據(jù)培訓(xùn)、需求管理培訓(xùn)、產(chǎn)品管理培訓(xùn),信息安全類,AI人工智能等....近十類上幾百門的課程的培訓(xùn)與咨詢服務(wù)。
艾威進(jìn)入中國這十八年來已經(jīng)服務(wù)了超過5000多家客戶,獲得了良好的口碑!也成為了眾多500強(qiáng)企業(yè)指定的培訓(xùn)服務(wù)供應(yīng)商.
● 艾威培訓(xùn)(Avtech Institute of Technology),源于美國,始于1998.
● 艾威培訓(xùn)(Avtech Institute of Technology)是Prometric,VUE,PSI等眾多國際認(rèn)證中心授權(quán)的考點(diǎn)

  ● 2003年成為國際項目管理協(xié)會PMI授權(quán)的全球(PMP,PGMP,ACP,PBA)教育機(jī)構(gòu)
  ● 2008年成為國際需求管理協(xié)會IIBA授權(quán)的全球(CCBA,CBAP)教育機(jī)構(gòu)
  ● 2012年成為IT服務(wù)管理官方EXIN授權(quán)的ITILITIL EXPERT,Prince2,EXIN Agile Scrum Master教育機(jī)構(gòu)
  ● 2016年成為國際信息審計協(xié)會ISACA授權(quán)的CISA,CISM,CRISC,CGEIT,COBIT教育機(jī)構(gòu)
  ● 2017年成為The Open Group授權(quán)的TOGAF企業(yè)架構(gòu)的官方培訓(xùn)機(jī)構(gòu)。
● 2017年成為EPI 授權(quán)的數(shù)據(jù)中心CDCP培訓(xùn)機(jī)構(gòu),華東地區(qū)_CDCP授權(quán)培訓(xùn)機(jī)構(gòu),同時也是CDCP認(rèn)證考試考場。
● 2017年成為國際外包專業(yè)協(xié)會(IAOP)_授權(quán)外包治理國際認(rèn)證SGF(Sourcing GovernanceFoundation)。

本文來自于艾威培訓(xùn)

轉(zhuǎn)載請注明:http://m.guidepoststore.com/news/683.html

上一篇:侯捷C++ Design Patterns企業(yè)培訓(xùn)
下一篇:上海Oracle Sql Tuning企業(yè)培訓(xùn)

發(fā)表回復(fù)

您的電子郵箱地址不會被公開。 必填項已用*標(biāo)注

  • 2024-11-28 20:00
    智能財務(wù)運(yùn)營的未來視角:RPA與AI技術(shù)的融合應(yīng)用
  • 2024-11-29 14:00
    周五課堂:如何帶團(tuán)隊?靠什么服眾?那些無處不在的“軟技能”
  • 2024-12-04 20:00
    職場故事:PMP與BA的協(xié)同與本地化策略
  • 2024-12-05 20:00
    職場故事:策劃崗如何快速學(xué)習(xí)新領(lǐng)域新知識?Get新技能√
  • 2024-12-10 20:00
    數(shù)字化轉(zhuǎn)型與TOGAF:不謀全局者,不足謀一隅,數(shù)字化轉(zhuǎn)型的“頂層設(shè)計”
  • 2024-12-12 20:00
    神秘莫測:密碼學(xué)和加密解密
  • 2024-12-17 20:00
    財務(wù)運(yùn)營智能化與數(shù)據(jù)驅(qū)動:商業(yè)智能(BI)系統(tǒng)的實(shí)施與運(yùn)用
  • 2024-12-19 20:00
    職場故事:項目管理的藝術(shù)與日常
  • 2024-12-25 20:00
    案例分析:深入探討商業(yè)分析工具的實(shí)際應(yīng)用
  • 2024-12-26 20:00
    存量數(shù)據(jù)“由亂到治”:如何解決已有數(shù)據(jù)的數(shù)據(jù)質(zhì)量問題?
  • 更多直播講座
    小艾老師還在安排中…
查看全部 >

掃碼一鍵預(yù)約全部

查看更多 > 查看更多 >

數(shù)字化轉(zhuǎn)型8大核心認(rèn)證

  1. PMP項目管理認(rèn)證

    艾威最近一期班: 針對2025年03月考試
  2. CBAP業(yè)務(wù)分析認(rèn)證

    艾威最近一期班·開課時間: 2025-01-18
  3. CBPP流程管理認(rèn)證

    艾威最近一期班·開課時間: 2025-03-15
  4. ITIL4 IT管理認(rèn)證

    艾威最近一期班·開課時間: 2025-01-18
  5. TOGAF企業(yè)架構(gòu)認(rèn)證

    艾威最近一期班·開課時間: 2025-01-18
  6. CDMP數(shù)據(jù)管理認(rèn)證

    艾威最近一期班·開課時間: 2025-02-22
  7. CISA信息安全審計師認(rèn)證

    艾威最近一期班·開課時間: 2025-03-02
  8. CISSP信息安全專家認(rèn)證

    艾威最近一期班·開課時間: 2025-02-15
近期課程安排