文章目錄
導言
- 下面將會用簡潔的語言分別描述什麼是類圖、類與類有哪些關係。
- 以下描述可能不太準確,但保證易懂。
類圖
類圖是什麼?有什麼用?
類圖是什麼呢?
類圖其實就是描述類(對象)與類(對象)之間的關係的一種圖。
類(對象)與類(對象)之間的關係有六種: 依賴、泛化(繼承)、實現、關聯、聚合、組合。
類圖有什麼用呢?
透過類圖,人們可以更爲方便的交流。
爲了 印證類圖可以方便交流,這裏舉個例子:
有人向你問路,問到肯德基怎麼走。你有 2
種方式告訴他
- 語言描述
從這裏直走,走到第三個十字路口後,左轉,再走到第二個路口後右轉,前面一百米的右側就是肯德基了。 - 畫圖描述
顯然,以上兩種方式孰優孰略,一眼便能看出。
接下來,我們來看個簡單的類圖。
簡單類圖舉例
現在有個 Person
類,它擁有 name
、sex
屬性,而且它有 Eat
、Run
方法。
那麼這個類的代碼如下:
type Person struct {
name string
sex bool
}
func (p *Person) Eat() {
// ....
}
func (p *Person) Run() {
// ...
}
類圖如下:
小夥伴們注意到:
name
和sex
之前有個符號~
,這些符號用來表示字段的可見範圍,~
表示字段包內可見。
Eat
和Run
之前有個符號+
,這表示它們是公有的,包外可見。
六大關係
上文中寫到,類(對象)與類(對象)之間的關係有六種,分別是 依賴、泛化(繼承)、實現、關聯、聚合、組合。
接下來,我們來對它們進行區分。
1. 依賴
當 類A
使用到了 類B
,我們就說 類A
依賴於 類B
。
什麼時候算 類A
使用到了 類B
呢?
- 類
B
是 類A
的成員 - 類
B
是 類A
的某個方法的參數、局部變量、返回值。
接下來舉個例子說明 依賴關係:
猴子喜歡偷什麼?偷桃對吧,那麼 猴子 就 依賴於 桃子。
代碼如下:
// 猴子類
type Monkey struct {
// ...
}
// 桃子類 是 猴子類 steal 方法的參數。
func(m *Monkey)steal(peach Peach) {
// ...
}
// 桃子類
type Peach struct {
// ...
}
畫圖時,我們採用「帶箭頭的虛線」表示依賴關係,箭頭由「依賴類」指向 「被依賴類」。
類圖如下:
2. 泛化(繼承) — 依賴關係的特例
當 類A
繼承 類B
,我們就說 類A
是 類B
的泛化。
泛化和繼承是同一個意思。
舉個例子:
豬都有大鼻子,而豬豬俠是豬,但是豬豬俠具有一般豬沒有的特性 — 他會飛~
代碼如下:
// 豬類
type Pig struct {
bigNose int // 類型我亂起的
}
// 豬豬俠類
type SuperPig struct {
Pig // 表示 繼承Pig
}
// 豬豬俠獨特的技能,飛行~~~
func (sp *SuperPig) Fly() {
// ...
}
畫圖時,我們採用「帶空心三角箭頭的實線」表示繼承關係,箭頭由「繼承類」指向 「被繼承類」。
類圖如下:
3. 實現 — 依賴關係的特例
當 類A
具有 接口I
的所有方法,我們就說 類A
實現了 接口I
。
舉個例子:
只要是能喫的就是 食物,而 麪包、飯 都是能喫的,所以可以說 麪包、飯 實現了 食物 這個接口。
代碼如下:
// 食物類
type Food interface {
BeEaten()
}
// 麪包類
type Bread struct {
// ...
}
func (b *Bread) BeEaten() {
fmt.Println("包包給吃了")
}
// 飯類
type Rice struct {
// ...
}
func (r *Rice) BeEaten() {
fmt.Println("飯飯給吃了")
}
畫圖時,我們採用「帶空心三角箭頭的虛線」表示實現關係,箭頭由「實現類」指向 「接口」。
類圖如下:
4. 關聯 — 依賴關係的特例
當 類A
中存在 類B
的成員,我們就說 類A
關聯了 類B
。
- 關聯關係可以是雙向的,即
A
中有B
且B
中有A
。 - 關聯關係也可以是一對多的,即
A
中有B
的數組。
接下來用個例子說明 一對多關聯關係:
我有很多個女朋友。
代碼如下:
// 我 類
type Me struct {
girlFriends []GirlFriend
}
// 女朋友 類
type GirlFriend struct {
// ...
}
畫圖時有以下規則:
- 採用「帶箭頭的實線」表示 單向關聯,箭頭由「關聯類」指向 「被關聯類」。
- 採用「實線」表示 雙向關聯。
- 可以在「線」的兩端標明是 一對一、一對多、多對多 關係。
那麼,這個例子的類圖如下:
5. 聚合 — 關聯關係的特例
當 類A
中存在 類B
的成員,且這個成員可通過 Set
方法進行設定,我們就說 類A
聚合了 類B
。
舉個例子:
富豪去 4S
店買車,當富豪沒買時,他處於沒車的狀態,買了之後,他才進入有車的狀態。
代碼如下:
// 富豪類
type RichPerson struct {
car Car
}
// 富豪買車(假設富豪只能擁有一輛車)
// 這裏相當於 Set 方法
func (rp *RichPerson) BuyCar(car Car){
rp.car = car
}
// 車類
type Car struct {
// ...
}
畫圖時,我們採用「帶空心棱形箭頭的實線」表示聚合關係,箭頭由「被聚合類」指向 「聚合類」。
類圖如下:
6. 組合 — 關聯關係的特例
當 類A
中存在 類B
的成員,且這個成員在 類A
初始化完畢時就已經存在,我們就說 類A
組合了 類B
。
舉個例子:
兔子都有長長的耳朵,而且是與生俱來的。
代碼如下:
// 兔子類
type Rabbit struct {
ear LongEar
}
// 相當於 Rabbit 的構造函數
func NewRabbit() Rabbit{
return Rabbit{
NewLongEar(), // 兔子出生時就有長長的耳朵了
}
}
// 長耳朵類
type LongEar struct {
// ...
}
// 相當於 LongEar 的構造函數
func NewLongEar() LongEar{
return LongEar{}
}
畫圖時,我們採用「帶實心棱形箭頭的實線」表示組合關係,箭頭由「被組合類」指向 「組合類」。
類圖如下:
總結
-
類圖是什麼?有什麼用?
類圖是描述類(對象)與類(對象)之間的關係的一種圖。透過類圖,人們可以更爲方便的交流。 -
類(對象)與類(對象)之間有哪六種關係?
依賴、泛化(繼承)、實現、關聯、聚合、組合。 -
六種關係的關係是什麼?
- 其他五種關係都是依賴關係的特例。
- 組合、聚合關係是關聯關係的特例。
-
聚合 和 組合 有什麼差別?
被聚合對象可以在後期傳入,而被組合對象在類初始化時就已經存在。 -
六種關係的圖像表示。
最後
以上內容參考了 韓順平老師 的設計模式課程,在此謝謝 韓老師。學習鏈接
歡迎在評論區中指出文中的任何錯誤,也歡迎大家進行提問~