iOS 21種設計模式之工廠模式
感謝
感謝《Pro Objective-C Design Pattern for iOS》一書,這個部落格系列由很多靈感源自次書。同時,也感謝Wiki以及一些部落格博主。每篇文章最後,都會列出參考連結。
這個系列的文章(程式碼Swift)
- 工廠
- 抽象工廠
- 單例
- 原型
- 生成器
- 介面卡
- 橋接
- 中介者
- 觀察者
- 組合
- 迭代器
- 訪問者
- 裝飾
- 責任鏈
- 模版
- 策略
- 命令
- 享元
- 代理
- 備忘錄
- 總結篇:MVC
- 進階篇:MVVM
設計模式是為了解決一類問題而出現的,要深刻理解某個模式的應用場景,優點,缺點。千萬不要為了使用而實用,那樣很可能寫出不倫不類的東西。
對於同一種模式,每個人的理解都不同,能解決實際問題才是關鍵
什麼是工廠模式?
工廠是用來生產產品的。在iOS開發中,產品就是類的物件,工廠就是工廠方法。
工廠模式就是定義建立物件的介面,讓子類決定例項化哪一個類。這樣,類的例項化就推遲到了子類
先看看工廠模式提供的介面,也就是客戶端(API使用者)呼叫的介面
let factory:Factory = ...//獲取工廠物件
let product:Product = factory.createProduct()//這裡獲得到的可能是Product,也可能是Product的子類
可以看到,客戶端只需要關注Factory和Product兩個類即可,而不需要關注他的子類到底是啥
解決什麼問題?
類有一組子類,可以共用一套介面,但是例項化的方式略有差異。用工廠的方式實現,使得客戶端(類的呼叫著)能夠專注於介面。而不需要訪問具體的實現類。
什麼時候使用工廠模式?
- 編譯器無法定義建立物件類
- 類可以讓其子類決定在執行期具體例項化的物件
實現原理
- 介面定義:工廠類的介面定義可以是類,也可以是協議。
- 工廠方法定義:
工廠模式的UML圖
- 注意其中紅線圈住的部分,那是實際的客戶端(API呼叫著)接觸的部分,也就是你設計的介面。在面向物件程式設計裡有個關鍵的概念:面向介面程式設計,而不是面向實現程式設計
對於,客戶端來說,只需要接觸工廠基類或者協議,得到產品基類就行了。
- 比如,有一個鞋廠,它告訴我,跟他的代表人(工廠方法)說生產鞋子就行了,今天來的是跑鞋廠的代表,我跟他說生產鞋子,他就給我一雙跑鞋。這樣,我只需要專注一點:跟我要接觸的代表人(工廠方法)說生產鞋子(統一介面),我就能夠拿到對應的產品(例項)而我只關心鞋子的通用屬性,不關心具體屬性。
一個簡單例子
Swift的例子採用協議作為抽象基礎類,用一個方法來返回不同的物件。
//產品
protocol Shoes{
func logDescription();
}
class RunningShoes:Shoes{
func logDescription() {
NSLog("跑鞋")
}
}
class Sneakers:Shoes{
func logDescription() {
NSLog("板鞋")
}
}
//工廠
protocol Factory{
func createShoes()->Shoes;
}
class RunningShoesFactory:Factory{
func createShoes() -> Shoes {
return RunningShoes()
}
}
class SneakerFactory:Factory{
func createShoes() -> Shoes {
return Sneakers()
}
}
//模擬Runtime的不確定性
class SimulateDynamicFactory{
class func simulateFactory()->Factory{
let randomInt = random()%2
if randomInt == 0{
return RunningShoesFactory()
}else{
return SneakerFactory()
}
}
}
然後,看看客戶端程式碼
let factory:Factory = SimulateDynamicFactory.simulateFactory()
let product = factory.createShoes()
product.logDescription()
可能有同學問了,我為何不直接訪問shoes的物件,直接呼叫構造方法()
,豈不是更簡單直接。面向物件開發還有一個原則對擴充套件開發,對修改封閉。如果直接使用if else 進行Shoes()
,那麼當有一種新的鞋子出現的時候,客戶端將不得不修改大量程式碼來支援新的鞋子。而使用工廠模式,由於介面始終是一直的,客戶端幾乎不需要修改什麼程式碼。只需要擴充套件一類產品,增加一個Factory就可以了。
舉個例子,假如我對上文的例子進行擴充套件,增加一類新的鞋子叫做leoShoes,我需要增加的程式碼是這樣的
class LeoShoes:Shoes{
func logDescription() {
NSLog("擴充套件鞋子")
}
}
class LeoShoesFactory:Factory{
func createShoes() -> Shoes {
return LeoShoes()
}
}
然後,修改SimulateDynamicFactory.simulateFactory
方法,看到了吧,客戶端程式碼不用任何修改,假如你是在一個Team負責給別的人開發庫,那麼庫的使用者肯定會謝謝你,否則你每釋出一個版本,他都要修改呼叫
參考連結
下一篇
- 抽象工廠模式