1. 程式人生 > >iOS 21種設計模式之工廠模式

iOS 21種設計模式之工廠模式

profile for Leo on Stack Exchange, a network of free, community-driven Q&A sites

感謝

感謝《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負責給別的人開發庫,那麼庫的使用者肯定會謝謝你,否則你每釋出一個版本,他都要修改呼叫

參考連結

下一篇

  • 抽象工廠模式