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

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

常用的UML

類圖

  • 屬性的定義:
    <屬性訪問權限> <屬性名> : <屬性類型>
  • 屬性訪問權限定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個私有的String類型的name屬性:
- name : String
  • 方法的定義:
    <方法訪問權限> <方法名>([方法參數列表]) : <方法的返回值>
  • 方法訪問權限定義:
    public:+
    protected:#
    package:~
    private:-
  • 定義一個公有的makeSound方法:
+ makeSound() : void

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

用例圖

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

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

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

  • 用例之間的關系

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

  • 參與者之間的關系

泛化:發出箭頭的事物“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)]

用例圖

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

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

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

  • 用例之間的關系

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

  • 參與者之間的關系

泛化:發出箭頭的事物“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

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)]

用例圖

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

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

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

  • 用例之間的關系

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

  • 參與者之間的關系

泛化:發出箭頭的事物“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

用例圖

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

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

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

  • 用例之間的關系

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

  • 參與者之間的關系

泛化:發出箭頭的事物“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)]

用例圖

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

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

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

  • 用例之間的關系

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

  • 參與者之間的關系

泛化:發出箭頭的事物“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源碼傳送門>>>

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容