iOS 工廠模式的面向協議程式設計思想

aron1992發表於2019-04-04

UML概述

UML簡介

UML (Unified Modeling Language)為物件導向軟體設計提供統一的、標準的、視覺化的建模語言。適用於描述以用例為驅動,以體系結構為中心的軟體設計的全過程。

UML的定義包括UML語義和UML表示法兩個部分。

  1. UML語義:UML對語義的描述使開發者能在語義上取得一致認識,消除了因人而異的表達方法所造成的影響。
  2. UML表示法:UML表示法定義UML符號的表示法,為開發者或開發工具使用這 些圖形符號和文字語法為系統建模提供了標準。

UML模型圖的構成

  1. 事物(Things):UML模型中最基本的構成元素,是具有代表性的成分的抽象
  2. 關係(Relationships):關係把事物緊密聯絡在一起
  3. 圖(Diagrams ):圖是事物和關係的視覺化表示

UML關係

圖例使用astah軟體繪製

1. 泛化 Generalization:

子類繼承父類的關係
[站外圖片上傳中...(image-11e40b-1512824786008)]

2. 實現 Relization:

子類實現協議或者介面
[站外圖片上傳中...(image-f48dac-1512824786008)]

3. 依賴 Dependency:

A類中應用了B類,這種關係具有偶然性和臨時性,同時B類發生的變化會影響到A類
[站外圖片上傳中...(image-602edf-1512824786008)]

4. 雙向關聯 Association:

一種特殊的依賴關係,比較強的依賴關係,一方依賴另一方
集合對映的情況:
1:單個
0..1:單個或者沒有
1..:至少一個
0..
:0個或者多個
*:任意個
[站外圖片上傳中...(image-d11cb7-1512824786008)]

5. 單向關聯 Directed Associated:

一種特殊的依賴關係,比較強的兩者互為依賴關係
[站外圖片上傳中...(image-391538-1512824786008)]

6. 聚合關係 Aggregation:

一種特殊的依賴關係,整體和部分的關係,各自有各自的生命週期,互不干擾,部分強調共享
eg:電腦和電池的關係,電池是共享的,電池也有自己的生命週期
[站外圖片上傳中...(image-7e2d9b-1512824786008)]

7. 組合關係 Composition:

一種特殊的依賴關係,整體和部分的關係,部分依賴於整體,不能獨立於整體存在
eg.公司和部門

組合關係 Composition
組合關係 Composition

常用的UML

類圖

  • 屬性的定義:
    <屬性訪問許可權> <屬性名> : <屬性型別>
  • 屬性訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個私有的String型別的name屬性:
- name : String
複製程式碼
  • 方法的定義:
    <方法訪問許可權> <方法名>([方法引數列表]) : <方法的返回值>
  • 方法訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個公有的makeSound方法:
+ makeSound() : void
複製程式碼

[站外圖片上傳中...(image-f07a01-1512824786008)]

用例圖

用例圖是從使用者角度描述系統功能, 是使用者所能觀察到的系統功能的模型圖,用例是系統中的一個功能單元

  • 參與者與用例之間的關係

關聯: 表示參與者與用例之間的互動,通訊途徑。 (關聯有時候也用帶箭頭的實線來表示,這樣的表示能夠顯示地表明發起用例的是參與者。)

  • 用例之間的關係

包含<>:箭頭指向的用例為被包含的用例,稱為包含用例;箭頭出發的用例為基用例。包含用例是必選的,如果缺少包含用例,基用例就不完整;包含用例必須被執行,不需要滿足某種條件;其執行並不會改變基用例的行為。
擴充套件<>:箭頭指向的用例為被擴充套件的用例,稱為擴充套件用例;箭頭出發的用例為基用例。擴充套件用例是可選的,如果缺少擴充套件用例,不會影響到基用例的完整性;擴充套件用例在一定條件下才會執行,並且其執行會改變基用例的行為。

  • 參與者之間的關係

泛化:發出箭頭的事物“is a”箭頭指向的事物。泛化關係是一般和特殊關係,發出箭頭的一方代表特殊的一方,箭頭指向的一方代表一般一方。特殊一方繼承了一般方的特性並增加了新的特性。 [站外圖片上傳中...(image-a8769e-1512824786008)]

時序圖

  • 順序圖用來表示用例中的行為順序。當執行一個用例行為時,順序圖中的每條訊息對應了一個類操作或狀態機中引起轉換的事件。
  • 順序圖展示物件之間的互動,這些互動是指在場景或用例的事件流中發生的。 順序圖屬於動態建模。
  • 順序圖的重點在訊息序列上,也就是說,描述訊息是如何在物件間傳送和接收的。表示了物件之間傳送訊息的時間順序。
  • 瀏覽順序圖的方法是:從上到下檢視物件間交換的訊息。

以微信支付為例的一個時序圖:
[站外圖片上傳中...(image-8165a1-1512824786008)]### UML概述

UML簡介

UML (Unified Modeling Language)為物件導向軟體設計提供統一的、標準的、視覺化的建模語言。適用於描述以用例為驅動,以體系結構為中心的軟體設計的全過程。

UML的定義包括UML語義和UML表示法兩個部分。

  1. UML語義:UML對語義的描述使開發者能在語義上取得一致認識,消除了因人而異的表達方法所造成的影響。
  2. UML表示法:UML表示法定義UML符號的表示法,為開發者或開發工具使用這 些圖形符號和文字語法為系統建模提供了標準。

UML模型圖的構成

  1. 事物(Things):UML模型中最基本的構成元素,是具有代表性的成分的抽象
  2. 關係(Relationships):關係把事物緊密聯絡在一起
  3. 圖(Diagrams ):圖是事物和關係的視覺化表示

UML關係

圖例使用astah軟體繪製

1. 泛化 Generalization:

子類繼承父類的關係
[站外圖片上傳中...(image-11e40b-1512824786008)]

2. 實現 Relization:

子類實現協議或者介面
[站外圖片上傳中...(image-f48dac-1512824786008)]

3. 依賴 Dependency:

A類中應用了B類,這種關係具有偶然性和臨時性,同時B類發生的變化會影響到A類
[站外圖片上傳中...(image-602edf-1512824786008)]

4. 雙向關聯 Association:

一種特殊的依賴關係,比較強的依賴關係,一方依賴另一方
集合對映的情況:
1:單個
0..1:單個或者沒有
1..:至少一個
0..
:0個或者多個
*:任意個
[站外圖片上傳中...(image-d11cb7-1512824786008)]

5. 單向關聯 Directed Associated:

一種特殊的依賴關係,比較強的兩者互為依賴關係
[站外圖片上傳中...(image-391538-1512824786008)]

6. 聚合關係 Aggregation:

一種特殊的依賴關係,整體和部分的關係,各自有各自的生命週期,互不干擾,部分強調共享
eg:電腦和電池的關係,電池是共享的,電池也有自己的生命週期
[站外圖片上傳中...(image-7e2d9b-1512824786008)]

7. 組合關係 Composition:

一種特殊的依賴關係,整體和部分的關係,部分依賴於整體,不能獨立於整體存在
eg.公司和部門
[站外圖片上傳中...(image-73e2-1512824786008)]

常用的UML

類圖

  • 屬性的定義:
    <屬性訪問許可權> <屬性名> : <屬性型別>
  • 屬性訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個私有的String型別的name屬性:
- name : String
複製程式碼
  • 方法的定義:
    <方法訪問許可權> <方法名>([方法引數列表]) : <方法的返回值>
  • 方法訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個公有的makeSound方法:
+ makeSound() : void
複製程式碼

[站外圖片上傳中...(image-f07a01-1512824786008)]

用例圖

用例圖是從使用者角度描述系統功能, 是使用者所能觀察到的系統功能的模型圖,用例是系統中的一個功能單元

  • 參與者與用例之間的關係

關聯: 表示參與者與用例之間的互動,通訊途徑。 (關聯有時候也用帶箭頭的實線來表示,這樣的表示能夠顯示地表明發起用例的是參與者。)

  • 用例之間的關係

包含<>:箭頭指向的用例為被包含的用例,稱為包含用例;箭頭出發的用例為基用例。包含用例是必選的,如果缺少包含用例,基用例就不完整;包含用例必須被執行,不需要滿足某種條件;其執行並不會改變基用例的行為。
擴充套件<>:箭頭指向的用例為被擴充套件的用例,稱為擴充套件用例;箭頭出發的用例為基用例。擴充套件用例是可選的,如果缺少擴充套件用例,不會影響到基用例的完整性;擴充套件用例在一定條件下才會執行,並且其執行會改變基用例的行為。

  • 參與者之間的關係

泛化:發出箭頭的事物“is a”箭頭指向的事物。泛化關係是一般和特殊關係,發出箭頭的一方代表特殊的一方,箭頭指向的一方代表一般一方。特殊一方繼承了一般方的特性並增加了新的特性。

用例圖
用例圖

時序圖

  • 順序圖用來表示用例中的行為順序。當執行一個用例行為時,順序圖中的每條訊息對應了一個類操作或狀態機中引起轉換的事件。
  • 順序圖展示物件之間的互動,這些互動是指在場景或用例的事件流中發生的。 順序圖屬於動態建模。
  • 順序圖的重點在訊息序列上,也就是說,描述訊息是如何在物件間傳送和接收的。表示了物件之間傳送訊息的時間順序。
  • 瀏覽順序圖的方法是:從上到下檢視物件間交換的訊息。

以微信支付為例的一個時序圖:
[站外圖片上傳中...(image-8165a1-1512824786008)]### UML概述

UML簡介

UML (Unified Modeling Language)為物件導向軟體設計提供統一的、標準的、視覺化的建模語言。適用於描述以用例為驅動,以體系結構為中心的軟體設計的全過程。

UML的定義包括UML語義和UML表示法兩個部分。

  1. UML語義:UML對語義的描述使開發者能在語義上取得一致認識,消除了因人而異的表達方法所造成的影響。
  2. UML表示法:UML表示法定義UML符號的表示法,為開發者或開發工具使用這 些圖形符號和文字語法為系統建模提供了標準。

UML模型圖的構成

  1. 事物(Things):UML模型中最基本的構成元素,是具有代表性的成分的抽象
  2. 關係(Relationships):關係把事物緊密聯絡在一起
  3. 圖(Diagrams ):圖是事物和關係的視覺化表示

UML關係

圖例使用astah軟體繪製

1. 泛化 Generalization:

子類繼承父類的關係
[站外圖片上傳中...(image-11e40b-1512824786008)]

2. 實現 Relization:

子類實現協議或者介面
[站外圖片上傳中...(image-f48dac-1512824786008)]

3. 依賴 Dependency:

A類中應用了B類,這種關係具有偶然性和臨時性,同時B類發生的變化會影響到A類
[站外圖片上傳中...(image-602edf-1512824786008)]

4. 雙向關聯 Association:

一種特殊的依賴關係,比較強的依賴關係,一方依賴另一方
集合對映的情況:
1:單個
0..1:單個或者沒有
1..:至少一個
0..
:0個或者多個
*:任意個
[站外圖片上傳中...(image-d11cb7-1512824786008)]

5. 單向關聯 Directed Associated:

一種特殊的依賴關係,比較強的兩者互為依賴關係

關聯 Association
關聯 Association

6. 聚合關係 Aggregation:

一種特殊的依賴關係,整體和部分的關係,各自有各自的生命週期,互不干擾,部分強調共享
eg:電腦和電池的關係,電池是共享的,電池也有自己的生命週期
[站外圖片上傳中...(image-7e2d9b-1512824786008)]

7. 組合關係 Composition:

一種特殊的依賴關係,整體和部分的關係,部分依賴於整體,不能獨立於整體存在
eg.公司和部門
[站外圖片上傳中...(image-73e2-1512824786008)]

常用的UML

類圖

  • 屬性的定義:
    <屬性訪問許可權> <屬性名> : <屬性型別>
  • 屬性訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個私有的String型別的name屬性:
- name : String
複製程式碼
  • 方法的定義:
    <方法訪問許可權> <方法名>([方法引數列表]) : <方法的返回值>
  • 方法訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個公有的makeSound方法:
+ makeSound() : void
複製程式碼

[站外圖片上傳中...(image-f07a01-1512824786008)]

用例圖

用例圖是從使用者角度描述系統功能, 是使用者所能觀察到的系統功能的模型圖,用例是系統中的一個功能單元

  • 參與者與用例之間的關係

關聯: 表示參與者與用例之間的互動,通訊途徑。 (關聯有時候也用帶箭頭的實線來表示,這樣的表示能夠顯示地表明發起用例的是參與者。)

  • 用例之間的關係

包含<>:箭頭指向的用例為被包含的用例,稱為包含用例;箭頭出發的用例為基用例。包含用例是必選的,如果缺少包含用例,基用例就不完整;包含用例必須被執行,不需要滿足某種條件;其執行並不會改變基用例的行為。
擴充套件<>:箭頭指向的用例為被擴充套件的用例,稱為擴充套件用例;箭頭出發的用例為基用例。擴充套件用例是可選的,如果缺少擴充套件用例,不會影響到基用例的完整性;擴充套件用例在一定條件下才會執行,並且其執行會改變基用例的行為。

  • 參與者之間的關係

泛化:發出箭頭的事物“is a”箭頭指向的事物。泛化關係是一般和特殊關係,發出箭頭的一方代表特殊的一方,箭頭指向的一方代表一般一方。特殊一方繼承了一般方的特性並增加了新的特性。 [站外圖片上傳中...(image-a8769e-1512824786008)]

時序圖

  • 順序圖用來表示用例中的行為順序。當執行一個用例行為時,順序圖中的每條訊息對應了一個類操作或狀態機中引起轉換的事件。
  • 順序圖展示物件之間的互動,這些互動是指在場景或用例的事件流中發生的。 順序圖屬於動態建模。
  • 順序圖的重點在訊息序列上,也就是說,描述訊息是如何在物件間傳送和接收的。表示了物件之間傳送訊息的時間順序。
  • 瀏覽順序圖的方法是:從上到下檢視物件間交換的訊息。

以微信支付為例的一個時序圖:
[站外圖片上傳中...(image-8165a1-1512824786008)]### UML概述

UML簡介

UML (Unified Modeling Language)為物件導向軟體設計提供統一的、標準的、視覺化的建模語言。適用於描述以用例為驅動,以體系結構為中心的軟體設計的全過程。

UML的定義包括UML語義和UML表示法兩個部分。

  1. UML語義:UML對語義的描述使開發者能在語義上取得一致認識,消除了因人而異的表達方法所造成的影響。
  2. UML表示法:UML表示法定義UML符號的表示法,為開發者或開發工具使用這 些圖形符號和文字語法為系統建模提供了標準。

UML模型圖的構成

  1. 事物(Things):UML模型中最基本的構成元素,是具有代表性的成分的抽象
  2. 關係(Relationships):關係把事物緊密聯絡在一起
  3. 圖(Diagrams ):圖是事物和關係的視覺化表示

UML關係

圖例使用astah軟體繪製

1. 泛化 Generalization:

子類繼承父類的關係
[站外圖片上傳中...(image-11e40b-1512824786008)]

2. 實現 Relization:

子類實現協議或者介面
[站外圖片上傳中...(image-f48dac-1512824786008)]

3. 依賴 Dependency:

A類中應用了B類,這種關係具有偶然性和臨時性,同時B類發生的變化會影響到A類
[站外圖片上傳中...(image-602edf-1512824786008)]

4. 雙向關聯 Association:

一種特殊的依賴關係,比較強的依賴關係,一方依賴另一方
集合對映的情況:
1:單個
0..1:單個或者沒有
1..:至少一個
0..
:0個或者多個
*:任意個
[站外圖片上傳中...(image-d11cb7-1512824786008)]

5. 單向關聯 Directed Associated:

一種特殊的依賴關係,比較強的兩者互為依賴關係
[站外圖片上傳中...(image-391538-1512824786008)]

6. 聚合關係 Aggregation:

一種特殊的依賴關係,整體和部分的關係,各自有各自的生命週期,互不干擾,部分強調共享
eg:電腦和電池的關係,電池是共享的,電池也有自己的生命週期
[站外圖片上傳中...(image-7e2d9b-1512824786008)]

7. 組合關係 Composition:

一種特殊的依賴關係,整體和部分的關係,部分依賴於整體,不能獨立於整體存在
eg.公司和部門
[站外圖片上傳中...(image-73e2-1512824786008)]

常用的UML

類圖

  • 屬性的定義:
    <屬性訪問許可權> <屬性名> : <屬性型別>
  • 屬性訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個私有的String型別的name屬性:
- name : String
複製程式碼
  • 方法的定義:
    <方法訪問許可權> <方法名>([方法引數列表]) : <方法的返回值>
  • 方法訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個公有的makeSound方法:
+ makeSound() : void
複製程式碼

泛化 Generalization
泛化 Generalization

用例圖

用例圖是從使用者角度描述系統功能, 是使用者所能觀察到的系統功能的模型圖,用例是系統中的一個功能單元

  • 參與者與用例之間的關係

關聯: 表示參與者與用例之間的互動,通訊途徑。 (關聯有時候也用帶箭頭的實線來表示,這樣的表示能夠顯示地表明發起用例的是參與者。)

  • 用例之間的關係

包含<>:箭頭指向的用例為被包含的用例,稱為包含用例;箭頭出發的用例為基用例。包含用例是必選的,如果缺少包含用例,基用例就不完整;包含用例必須被執行,不需要滿足某種條件;其執行並不會改變基用例的行為。
擴充套件<>:箭頭指向的用例為被擴充套件的用例,稱為擴充套件用例;箭頭出發的用例為基用例。擴充套件用例是可選的,如果缺少擴充套件用例,不會影響到基用例的完整性;擴充套件用例在一定條件下才會執行,並且其執行會改變基用例的行為。

  • 參與者之間的關係

泛化:發出箭頭的事物“is a”箭頭指向的事物。泛化關係是一般和特殊關係,發出箭頭的一方代表特殊的一方,箭頭指向的一方代表一般一方。特殊一方繼承了一般方的特性並增加了新的特性。 [站外圖片上傳中...(image-a8769e-1512824786008)]

時序圖

  • 順序圖用來表示用例中的行為順序。當執行一個用例行為時,順序圖中的每條訊息對應了一個類操作或狀態機中引起轉換的事件。
  • 順序圖展示物件之間的互動,這些互動是指在場景或用例的事件流中發生的。 順序圖屬於動態建模。
  • 順序圖的重點在訊息序列上,也就是說,描述訊息是如何在物件間傳送和接收的。表示了物件之間傳送訊息的時間順序。
  • 瀏覽順序圖的方法是:從上到下檢視物件間交換的訊息。

以微信支付為例的一個時序圖:
[站外圖片上傳中...(image-8165a1-1512824786008)]### UML概述

UML簡介

UML (Unified Modeling Language)為物件導向軟體設計提供統一的、標準的、視覺化的建模語言。適用於描述以用例為驅動,以體系結構為中心的軟體設計的全過程。

UML的定義包括UML語義和UML表示法兩個部分。

  1. UML語義:UML對語義的描述使開發者能在語義上取得一致認識,消除了因人而異的表達方法所造成的影響。
  2. UML表示法:UML表示法定義UML符號的表示法,為開發者或開發工具使用這 些圖形符號和文字語法為系統建模提供了標準。

UML模型圖的構成

  1. 事物(Things):UML模型中最基本的構成元素,是具有代表性的成分的抽象
  2. 關係(Relationships):關係把事物緊密聯絡在一起
  3. 圖(Diagrams ):圖是事物和關係的視覺化表示

UML關係

圖例使用astah軟體繪製

1. 泛化 Generalization:

子類繼承父類的關係
[站外圖片上傳中...(image-11e40b-1512824786008)]

2. 實現 Relization:

子類實現協議或者介面
[站外圖片上傳中...(image-f48dac-1512824786008)]

3. 依賴 Dependency:

A類中應用了B類,這種關係具有偶然性和臨時性,同時B類發生的變化會影響到A類
[站外圖片上傳中...(image-602edf-1512824786008)]

4. 雙向關聯 Association:

一種特殊的依賴關係,比較強的依賴關係,一方依賴另一方
集合對映的情況:
1:單個
0..1:單個或者沒有
1..:至少一個
0..
:0個或者多個
*:任意個
[站外圖片上傳中...(image-d11cb7-1512824786008)]

5. 單向關聯 Directed Associated:

一種特殊的依賴關係,比較強的兩者互為依賴關係
[站外圖片上傳中...(image-391538-1512824786008)]

6. 聚合關係 Aggregation:

一種特殊的依賴關係,整體和部分的關係,各自有各自的生命週期,互不干擾,部分強調共享
eg:電腦和電池的關係,電池是共享的,電池也有自己的生命週期
[站外圖片上傳中...(image-7e2d9b-1512824786008)]

7. 組合關係 Composition:

一種特殊的依賴關係,整體和部分的關係,部分依賴於整體,不能獨立於整體存在
eg.公司和部門
[站外圖片上傳中...(image-73e2-1512824786008)]

常用的UML

類圖

  • 屬性的定義:
    <屬性訪問許可權> <屬性名> : <屬性型別>
  • 屬性訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個私有的String型別的name屬性:
- name : String
複製程式碼
  • 方法的定義:
    <方法訪問許可權> <方法名>([方法引數列表]) : <方法的返回值>
  • 方法訪問許可權定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個公有的makeSound方法:
+ makeSound() : void
複製程式碼

[站外圖片上傳中...(image-f07a01-1512824786008)]

用例圖

用例圖是從使用者角度描述系統功能, 是使用者所能觀察到的系統功能的模型圖,用例是系統中的一個功能單元

  • 參與者與用例之間的關係

關聯: 表示參與者與用例之間的互動,通訊途徑。 (關聯有時候也用帶箭頭的實線來表示,這樣的表示能夠顯示地表明發起用例的是參與者。)

  • 用例之間的關係

包含<>:箭頭指向的用例為被包含的用例,稱為包含用例;箭頭出發的用例為基用例。包含用例是必選的,如果缺少包含用例,基用例就不完整;包含用例必須被執行,不需要滿足某種條件;其執行並不會改變基用例的行為。
擴充套件<>:箭頭指向的用例為被擴充套件的用例,稱為擴充套件用例;箭頭出發的用例為基用例。擴充套件用例是可選的,如果缺少擴充套件用例,不會影響到基用例的完整性;擴充套件用例在一定條件下才會執行,並且其執行會改變基用例的行為。

  • 參與者之間的關係

泛化:發出箭頭的事物“is a”箭頭指向的事物。泛化關係是一般和特殊關係,發出箭頭的一方代表特殊的一方,箭頭指向的一方代表一般一方。特殊一方繼承了一般方的特性並增加了新的特性。 [站外圖片上傳中...(image-a8769e-1512824786008)]

時序圖

  • 順序圖用來表示用例中的行為順序。當執行一個用例行為時,順序圖中的每條訊息對應了一個類操作或狀態機中引起轉換的事件。
  • 順序圖展示物件之間的互動,這些互動是指在場景或用例的事件流中發生的。 順序圖屬於動態建模。
  • 順序圖的重點在訊息序列上,也就是說,描述訊息是如何在物件間傳送和接收的。表示了物件之間傳送訊息的時間順序。
  • 瀏覽順序圖的方法是:從上到下檢視物件間交換的訊息。

以微信支付為例的一個時序圖:

時序圖
時序圖
#### 前言 OOP開發有個原則是針對抽象程式設計而不是針對具體程式設計,實際的軟體開發中,因為時間和專案進度等客觀不可抵抗和主觀的因素,我們偏向使用最簡單的的方式去實現功能,而沒有考慮到未來可能會有的擴充套件問題,導致未來發生擴充套件的時候出現了維護性的災難,軟體模組不好擴充套件,需求變動就得修改模組,這就違反了開閉原則,所以,很有必要在設計的時候去考慮未來可能會引入的變化,使用合適的模式去應對未來的這種變化。

簡單工廠

簡單工廠作為工廠模式的最簡單的一種,與其說是一種模式,不如說是一種程式設計習慣,軟體開發中,我們會無意識或者有意思的把經常用到的那部分內容抽取到一個模組中統一建立,而不是在多個使用者單獨的建立,這也遵循軟體開發中的don't repeat yourself原則,一般的我們會把建立的方法定義為靜態的方法,如果內容有差異,一般滴我們會使用型別進行區分,比如下面程式碼,我們建立不同型別的mapview物件,這是一個典型的簡單工廠的例子。

//
//  SimpleMapFactory.h
//  DesignPatternProject
//
//  Created by aron on 2017/5/18.
//  Copyright © 2017年 aron. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef NS_ENUM(NSUInteger, MapType) {
    MapTypeBaidu,
    MapTypeGaode,
    MapTypeTencent,
};

@interface SimpleMapFactory : NSObject

+ (UIView*)mapViewWithFrame:(CGRect)frame type:(MapType)mapType;

@end


//
//  SimpleMapFactory.m
//  DesignPatternProject
//
//  Created by aron on 2017/5/18.
//  Copyright © 2017年 aron. All rights reserved.
//

#import "SimpleMapFactory.h"
#import <MAMapKit/MAMapKit.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <BaiduMapAPI_Map/BMKMapView.h>


@implementation SimpleMapFactory

+ (UIView*)mapViewWithFrame:(CGRect)frame type:(MapType)mapType {
    if (mapType == MapTypeGaode) {
        MAMapView *maMapView = [[MAMapView alloc] initWithFrame:frame];
        return maMapView;
    } else if (mapType == MapTypeBaidu) {
        BMKMapView* mapView = [[BMKMapView alloc]initWithFrame:frame];
        return mapView;
    }
    
    return nil;
}

@end
複製程式碼

簡單工廠的侷限

定義一個靜態方法+ (UIView*)mapViewWithFrame:(CGRect)frame type:(MapType)mapType,實現中使用分支語句建立不同的例項,如果後面有其他型別的例項,那麼這個方法就得進行相應的修改,如果型別變得多了,建立的過程複雜了,這個模組就得經常的修改,這還沒什麼,簡單工廠返回的是一個UIView的通用型別,使用者需要強轉為對應的型別,才能充分的使用到這個UIView物件,在這個場景中MAMapViewBMKMapView這兩個類的介面是完全不同的,這意味著,新增了一個新型別,修改的不僅僅是工廠靜態方法,呼叫者的使用方式也必須進行相應的修改,違法了開閉原則,讓維護和擴充套件變得困難起來了,這不是我們想要的。

工廠方法

工廠方法是對簡單工廠的抽象,讓工廠具有了良好的擴充套件性,使得容易擴充套件和維護,工廠方法抽象了兩個方面,首先對產品進行了抽象,在上面的案例中就是對mapview進行了抽象,在抽象了mapview中定義公共的介面提供給呼叫者使用;其次對工廠進行了抽象,工廠返回的不是一個具體的mapview,而是抽象之後的mapview,呼叫者可以使用抽象的mapview種定義的公共的介面和具體的mapview物件互動。
工廠方法的UML描述如下:

工廠方法類圖
工廠方法類圖

工廠方法程式碼實現

  • 對產品的抽象
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@protocol MapView <NSObject>

- (instancetype)initWithFrame:(CGRect)frame;

- (UIView*)getView;

@end
複製程式碼
  • 對工廠的抽象
#import <Foundation/Foundation.h>
#import "MapView.h"

@protocol MapFactory <NSObject>

+ (id<MapView>)mapViewWithFrame:(CGRect)frame;

@end
複製程式碼
  • 具體的產品,以百度地圖為例
#import "BaiduMapView.h"
#import <BaiduMapAPI_Map/BMKMapView.h>

@interface BaiduMapView () {
    BMKMapView* _mapView;
}

@end

@implementation BaiduMapView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super init];
    if (self) {
        BMKMapView* mapView = [[BMKMapView alloc]initWithFrame:frame];
        _mapView = mapView;
    }
    return self;
}

- (UIView *)getView {
    return _mapView;
}

@end
複製程式碼
  • 具體的工廠(百度地圖建立工廠)
#import "BaiduMapView.h"
#import <BaiduMapAPI_Map/BMKMapView.h>

@interface BaiduMapView () {
    BMKMapView* _mapView;
}

@end

@implementation BaiduMapView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super init];
    if (self) {
        BMKMapView* mapView = [[BMKMapView alloc]initWithFrame:frame];
        _mapView = mapView;
    }
    return self;
}

- (UIView *)getView {
    return _mapView;
}

@end
複製程式碼

上面的程式碼片段就是一個簡單的工廠方法的例子,抽象的產品只提供了一個介面,真是的場景使用到的不止一個公有介面,因需求而定。

  • 呼叫者的呼叫方式
    id<MapView> mapView = [BaiduMapFactory mapViewWithFrame:CGRectMake(0, 0, 320, 200)];
    [self.view addSubview:[mapView getView]];
    
    id<MapView> maMapView = [GaodeMapFactory mapViewWithFrame:CGRectMake(0, 200, 320, 200)];
    [self.view addSubview:[maMapView getView]];
複製程式碼

當需求有變化需要替換底層元件,呼叫者只要修改工廠就行了,需要新增相應的具體產品和具體的工廠就行了,不會依賴於具體的實現,擴充套件起來相當的方便,當然,因為抽象級別的提高,程式碼量也會相應的變多,不過這是必要的犧牲,魚和熊掌不可兼得。

抽象工廠

工廠方法返回的是多個同種型別的物件,未來的擴充套件我們可能會遇到返回的是一組同種型別的物件,比如在我們的軟體場景中,我麼未來可能擴充套件我們的工廠返回定位物件,這種場景,需要定義一個定位物件的協議,工廠協議需要新增一個公共介面返回一個定位物件,這樣工廠方法轉換為了抽象工廠,可以這麼說抽象工廠是對工廠方法的再次抽象和擴充套件。
抽象工廠的UML描述如下:

抽象工廠類圖
抽象工廠類圖

抽象工廠程式碼實現

抽象工廠在工廠方法的基礎上進行了擴充套件,新增了兩部分:1、新增了一個Location抽象介面和Location對應的實現;2、工廠的介面新增了一個返回Location物件的公有方法。下面程式碼只展示了新增加的部分,完整的程式碼可以檢視文章底部的連結。

  • Location抽象介面
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

@protocol AbsLocation <NSObject>

- (void)startLocateWithResult:(void(^)(CLLocation* location))complete;

@end
複製程式碼
  • 工廠的介面新增了一個返回Location物件的公有方法
@protocol AbsMapFactory <NSObject>

+ (id<AbsMapView>)mapViewWithFrame:(CGRect)frame;

+ (id<AbsLocation>)location;

@end
複製程式碼
  • Location抽象介面的實現,例子只是模擬,真正的以實際的定位物件為準

//.h

#import <Foundation/Foundation.h>
#import "AbsLocation.h"

@interface AbsBaiduLocation : NSObject <AbsLocation>

@end

.m

#import "AbsBaiduLocation.h"

@implementation AbsBaiduLocation

- (void)startLocateWithResult:(void(^)(CLLocation* location))complete {
    NSLog(@"BaiduLocation started");
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        // 模擬返回
        !complete ?: complete([[CLLocation alloc] initWithLatitude:123 longitude:123]);
    });
}
@end
複製程式碼

使用方法:

 // abstract factory usuage
    id<AbsMapView> absBaiduMapView = [AbsBaiduMapFactory mapViewWithFrame:CGRectMake(0, 0, 320, 200)];
    [self.view addSubview:[absBaiduMapView getView]];
    id<AbsLocation> baiduMapLocation = [AbsBaiduMapFactory location];
    [baiduMapLocation startLocateWithResult:^(CLLocation *location) {
        NSLog(@"location result");
    }];
    
    
    id<AbsMapView> absGaodeMapView = [AbsGaodeMapFactory mapViewWithFrame:CGRectMake(0, 200, 320, 200)];
    [self.view addSubview:[absGaodeMapView getView]];
複製程式碼

總結

工廠模式在實際軟體開發中使用的場景是很多的,如果在可預見的未來軟體會很有可能發生擴充套件變化,那麼引入工廠方法或者抽象工廠設計出良好擴充套件的模組還是很有必要的,如果這個模組相對固定不容易改變,那麼使用工廠方法也沒什麼問題,畢竟簡單高效才是王道,引入模式反而把問題複雜化了,維護起來工作量反而大了,一點個人不成熟的想法,以上。

相關連結

本文Demo原始碼傳送門>>>

相關文章