類圖、依賴、泛化(繼承)、實現、關聯、組合、聚合

導言

  1. 下面將會用簡潔的語言分別描述什麼是類圖、類與類有哪些關係。
  2. 以下描述可能不太準確,但保證易懂。

類圖

類圖是什麼?有什麼用?

類圖是什麼呢?
類圖其實就是描述類(對象)與類(對象)之間的關係的一種圖。

類(對象)與類(對象)之間的關係有六種: 依賴、泛化(繼承)、實現、關聯、聚合、組合。

類圖有什麼用呢?
透過類圖,人們可以更爲方便的交流。

爲了 印證類圖可以方便交流,這裏舉個例子:
有人向你問路,問到肯德基怎麼走。你有 2 種方式告訴他

  1. 語言描述
    從這裏直走,走到第三個十字路口後,左轉,再走到第二個路口後右轉,前面一百米的右側就是肯德基了。
  2. 畫圖描述
    在這裏插入圖片描述

顯然,以上兩種方式孰優孰略,一眼便能看出。

接下來,我們來看個簡單的類圖。


簡單類圖舉例

現在有個 Person 類,它擁有 namesex 屬性,而且它有 EatRun 方法。

那麼這個類的代碼如下:

type Person struct {
	name string
	sex  bool
}

func (p *Person) Eat() {
	// ....
}

func (p *Person) Run() {
	// ...
}

類圖如下:
在這裏插入圖片描述

小夥伴們注意到:
namesex之前有個符號 ~,這些符號用來表示字段的可見範圍,~ 表示字段包內可見。
EatRun 之前有個符號+,這表示它們是公有的,包外可見。


六大關係

上文中寫到,類(對象)與類(對象)之間的關係有六種,分別是 依賴、泛化(繼承)、實現、關聯、聚合、組合。

接下來,我們來對它們進行區分。

1. 依賴

當 類A 使用到了 類B,我們就說 類A 依賴於 類B

什麼時候算 A 使用到了 類B 呢?

  1. B 是 類A 的成員
  2. 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中有BB中有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{}
}

畫圖時,我們採用「帶實心棱形箭頭的實線」表示組合關係,箭頭由「被組合類」指向 「組合類」。

類圖如下:
在這裏插入圖片描述

總結

  1. 類圖是什麼?有什麼用?
    類圖是描述類(對象)與類(對象)之間的關係的一種圖。透過類圖,人們可以更爲方便的交流。

  2. 類(對象)與類(對象)之間有哪六種關係?
    依賴、泛化(繼承)、實現、關聯、聚合、組合。

  3. 六種關係的關係是什麼?

    • 其他五種關係都是依賴關係的特例。
    • 組合、聚合關係是關聯關係的特例。
  4. 聚合 和 組合 有什麼差別?
    被聚合對象可以在後期傳入,而被組合對象在類初始化時就已經存在。

  5. 六種關係的圖像表示。
    在這裏插入圖片描述


最後

以上內容參考了 韓順平老師 的設計模式課程,在此謝謝 韓老師。學習鏈接

歡迎在評論區中指出文中的任何錯誤,也歡迎大家進行提問~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章