我們先來看一段golang代碼,如果它走起來像隻鴨子,叫起來像隻鴨子,那麼它可能是一隻包裝了鴨子擴充卡的火雞。假設缺少鴨子對象,想用一些火雞對象來冒充,顯而易見火雞的接口不同,需要寫個擴充卡:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<code>package</code> <code>main</code>
<code> </code>
<code>import</code> <code>(</code>
<code> </code><code>"fmt"</code>
<code>)</code>
<code>func main() {</code>
<code> </code><code>duck := &MallardDuck{}</code>
<code> </code><code>turkey := &WildTurkey{}</code>
<code> </code><code>turkeyAdapter := NewTurkeyAdapter(turkey)</code>
<code> </code><code>fmt.Println(</code><code>"The Turkey says..."</code><code>)</code>
<code> </code><code>turkey.gobble()</code>
<code> </code><code>turkey.fly()</code>
<code> </code><code>fmt.Println(</code><code>"The Duck says..."</code><code>)</code>
<code> </code><code>duck.quack()</code>
<code> </code><code>duck.fly()</code>
<code> </code><code>fmt.Println(</code><code>"The TurkeyAdapter says..."</code><code>)</code>
<code> </code><code>turkeyAdapter.quack()</code>
<code> </code><code>turkeyAdapter.fly()</code>
<code>}</code>
<code> </code>
<code>//鴨子Duck接口,具備呱呱叫和飛行的能力</code>
<code>type Duck </code><code>interface</code> <code>{</code>
<code> </code><code>quack() </code><code>//呱呱叫</code>
<code> </code><code>fly() </code><code>//飛行</code>
<code>//火雞Turkey接口</code>
<code>type Turkey </code><code>interface</code> <code>{</code>
<code> </code><code>gobble() </code><code>//火雞不會呱呱叫,隻會咯咯叫(gobble)</code>
<code> </code><code>fly() </code><code>//火雞也會飛,雖然飛不遠</code>
<code>//實作了Duck接口</code>
<code>type MallardDuck struct{}</code>
<code>func (*MallardDuck) quack() {</code>
<code> </code><code>fmt.Println(</code><code>"Quack..."</code><code>)</code>
<code>func (*MallardDuck) fly() {</code>
<code> </code><code>fmt.Println(</code><code>"I'm flying"</code><code>)</code>
<code>//實作了Turkey接口</code>
<code>type WildTurkey struct{}</code>
<code>func (*WildTurkey) gobble() {</code>
<code> </code><code>fmt.Println(</code><code>"Gobble..."</code><code>)</code>
<code>func (*WildTurkey) fly() {</code>
<code> </code><code>fmt.Println(</code><code>"I'm flying a short distance"</code><code>)</code>
<code>//首先,需要實作想轉換成的類型接口,也就是</code>
<code>//客戶所期望看到的接口</code>
<code>type TurkeyAdapter struct {</code>
<code> </code><code>turkey Turkey</code>
<code>//接着,需要取得适配的對象引用</code>
<code>func NewTurkeyAdapter(turkey Turkey) *TurkeyAdapter {</code>
<code> </code><code>return</code> <code>&TurkeyAdapter{ turkey }</code>
<code>//現在需要實作接口中所有的方法,</code>
<code>//quack在類之間的轉換很簡單,調用gobble就可以。</code>
<code>func (</code><code>this</code> <code>*TurkeyAdapter) quack() {</code>
<code> </code><code>this</code><code>.turkey.gobble()</code>
<code>//兩個接口都具備了fly方法,火雞飛行距離短,</code>
<code>//要讓火雞和鴨子的飛行能對應,必須連續五次調用火雞的fly</code>
<code>func (</code><code>this</code> <code>*TurkeyAdapter) fly() {</code>
<code> </code><code>for</code> <code>i := </code><code>0</code><code>; i < </code><code>5</code><code>; i++ {</code>
<code> </code><code>this</code><code>.turkey.fly()</code>
<code> </code><code>}</code>
現在我們知道什麼是擴充卡了,再看看各部分之間的關系:
<a href="http://s3.51cto.com/wyfs02/M00/12/4A/wKiom1MB7T3x_RE4AAROTBX8dOk215.jpg" target="_blank"></a>
客戶使用擴充卡的過程如下:
1.客戶通過目标接口調用擴充卡的方法對擴充卡送出請求。
2.擴充卡使用被适配者接口把請求轉換成被适配者的一個或者多個調用接口。
3.客戶接收到調用的結果,但并未察覺這一切是擴充卡在起轉換作用。
擴充卡模式:将一個類的接口,轉換成客戶期望的另一個接口。擴充卡讓原本接口不相容的類可以合作無間。
<a href="http://s3.51cto.com/wyfs02/M00/12/4B/wKiom1MB_IvRYOV3AAF9gGc2rnY763.jpg" target="_blank"></a>
這個擴充卡模式充滿着良好的OO設計原則:使用對象組合,以修改的接口包裝被适配者。這種做法還有額外的優點,那就是,被适配者的任何子類,都可以搭配着擴充卡使用。
實際上,有“兩種”擴充卡:“對象”擴充卡和“類”擴充卡。上述所述為“對象”擴充卡。“類”擴充卡不是使用組合來适配被适配者,而是繼承被适配者和目标類。
本文轉自 ponpon_ 51CTO部落格,原文連結:http://blog.51cto.com/liuxp0827/1359920,如需轉載請自行聯系原作者