dependency injection 關于IOS依賴注入那些事
本文介紹的是另一個屎上最牛叉的ios開發新框架,最大的特點就是:幫助我們開發出松散耦合(loose coupled)、可維護、可測試的代碼和程序。這條原則的做法是大家熟知的面向接口,或者說是面向抽象編程。 眾所周知 該編程思想在各大語言中都有體現如 jave C++ PHP以及.net中。當然設計模式的廣泛程度遠遠大于這些,IOS 當然也不例外。 本文主要介紹本人在學習dependency injection的時候的學習過程以及對一些學習資料的總結,主要介紹ios中的兩大框架objection和Typhoon。 閑話不多吹下面進入正題。
什么是dependency injection?
簡單來說:
關于什么是依賴注入,在Stack Overflow上面有一個問題,如何向一個5歲的小孩解釋依賴注入,其中得分最高的一個答案是:
“When you go and get things out of the refrigerator for yourself, you can cause problems. You might leave the door open, you might get something Mommy or Daddy doesn’t want you to have. You might even be looking for something we don’t even have or which has expired.
What you should be doing is stating a need, “I need something to drink with lunch,” and then we will make sure you have something when you sit down to eat.”
映射到面向對象程序開發中就是:高層類(5歲小孩)應該依賴底層基礎設施(家長)來提供必要的服務。
編寫松耦合的代碼說起來很簡單,但是實際上寫著寫著就變成了緊耦合。
更詳細點的解釋:
依賴倒置解決了高層次模塊依賴于低層次模塊和其細節的問題。
Dependency injection 是一個將行為從依賴中分離的技術,簡單地說,它允許開發者定義一個方法函數依賴于外部其他各種交互,而不需要編碼如何獲得這些外部交互的實例。 這樣就在各種組件之間解耦,從而獲得干凈的代碼,相比依賴的硬編碼, 一個組件只有在運行時才調用其所需要的其他組件,因此在代碼運行時,通過特定的框架或容器,將其所需要的其他依賴組件進行注入,主動推入。
依賴注入可以看成是 反轉控制 inversion of control 的一個特例。反轉的是依賴,而不是其他,JNDI也是一種反轉控制,它反轉的JNDI名稱或資源。參考: “Inversion of Control Containers and the Dependency Injection pattern”。
依賴注入是最早Spring和piconcontainer等提出,如今已經是一個缺省主流模式,并擴展到前端如Angular.js等等。
依賴注入與IOC模式類似工廠模式,是一種解決調用者和被調用者依賴耦合關系的模式,自2004年誕生以來,至今已經成為Java和其他領域的主流模式。它解決了對象之間的依賴關系,使得對象只依賴IOC/DI容器,不再直接相互依賴,實現松耦合,然后在對象創建時,由IOC/DI容器將其依賴的對象注入Inject其體內,故又稱依賴注入依賴注射模式,最大程度實現松耦合,特別是Autowiring/Autowired自動配對引入,再結合Java的垃圾回收機制,使得在Java中,對象不再需要開發者自己創建,也需要開發者自己銷毀,只需要直接使用即可,大大提升了開發效率。
詳細解釋:依賴注入說白一點,就是容器將某個類依賴的其他類注入到這個類中。
為什么要用dependency injection
依賴注入框架的運用可以幫我們將APP的設計分割成好幾個模塊,分給不同的開人員,當完成開發之后再進行合并充分解決了團隊之間模塊化分工的不足.借objic.io上一篇關于Dependency Injection的一句話:
My initial motivation for exploring DI came from doing test-driven development, because in TDD you constantly wrestle with the question of “How do I write a unit test for this?” But I discovered that DI is actually concerned with a bigger idea: that our code should be composed of modules that we snap together to build an application.
There are many benefits to such an approach. Graham Lee’s article, “Dependency Injection, iOS and You,” describes some of them: “to adapt… to new requirements, make bug fixes, add new features, and test components in isolation.”
大體意思:
我在探索DI最初的動機來自做測試驅動的開發,因為在TDD你不斷地與問題搏斗“我怎樣寫單元測試嗎?”但我發現,DI實際上是涉及一個更大的想法:即我們的代碼應該由我們扣合在一起來構建應用程序模塊。
有許多好處,這樣的做法。格雷厄姆李的文章,“依賴注入,iOS和你”,介紹了其中一些:“適應......新的要求,作出錯誤修復,隔離增加新的功能以及測試組件。”
用文字說這些概念其實很抽象,下面用幾張圖片說明下:
通過objection實現依賴注入后,就能更好地實現SRP(Single Responsibility Principle),代碼更簡潔,心情更舒暢,生活更美好。拿Pinterest來說,下面的頁面就可以劃分為3個Section。

各個Section可以由不同的人負責,然后串到一起就行,也能一定程度地避免MVC(Mess View Controller)的出現,對于提高開發成員的效率也會有不少的幫助。
其實用簡單的一句話來說就是: 通過DI設計模式,將項目模塊化,以提高開發效率。
dependency injection試圖解決什么問題呢
我們知道,在IOS基本教程中有一個定律告訴我們:所有的對象都必須創建;或者說:使用對象之前必須創建,但是現在我們可以不必一定遵循這個定律了,我們可以從DI容器中直接獲得一個對象然后直接使用,無需事先創建它們。
這種變革,就如同我們無需考慮對象銷毀一樣;因為IOS的 ARC 幫助我們實現了對象銷毀;現在又無需考慮對象創建,對象的創建和銷毀都無需考慮了,這給編程帶來的影響是巨大的
我們可以通過一篇博文了解下原理,該文章是由Limboy大神寫的使用objection來模塊化開發iOS項目
這里提前介紹了一個DI框架就是Objection,詳細介紹就去看博文,在此只分析下DI的設計原理:
類似于Objection的大部分DI框架,主要為我們提供了一個容器,來管理創建銷毀對象,我們并不會過多考慮創建對象的方法內容以及其再其他類中的依賴關系,這些都在框架中為我們解決了,我們只需要再需要的時候調用即可,并不需要重復的導入import,避免不同類直接多次重復的import導致的依賴循環問題。
那么問題來了?如何學習dependency injection呢
ios有關DI依賴注入的框架比較好用的有兩個:objection 和 Typhoon
下面就從幾個方便來介紹下這兩個框架
一:objection 和 Typhoon這兩個框架有什么區別呢
其實這兩個框架各有優勢:
1.objection框架,使用起來比較靈活,用法比較簡單。示例代碼如下:
屬性注冊:
@class Engine, Brakes;
@interface Car : NSObject
{
Engine *engine;
Brakes *brakes;
BOOL awake;
}
// Will be filled in by objection
@property(nonatomic, strong) Engine *engine;
// Will be filled in by objection
@property(nonatomic, strong) Brakes *brakes;
@property(nonatomic) BOOL awake;
@implementation Car
objection_requires(@"engine", @"brakes") //屬性的依賴注入
@synthesize engine, brakes, awake;
@end
方法注入:
@implementation Truck
objection_requires(@"engine", @"brakes")
objection_initializer(truckWithMake:model:)//方法的依賴注入
+ (instancetype)truckWithMake:(NSString *) make model: (NSString *)model {
...
}
@end
2.對比來說Typhoon的使用起來就比較規范,首先需要創建一個 TyphoonAssembly的子類。其需要注入的方法和屬性都需要寫在這個統一個子類中,當然可以實現不同的子類來完成不同的功能
@interface MiddleAgesAssembly : TyphoonAssembly
- (Knight*)basicKnight;
- (Knight*)cavalryMan;
- (id<Quest>)defaultQuest;
@end
屬性注入:
- (Knight *)cavalryMan
{
return [TyphoonDefinition withClass:[CavalryMan class]
configuration:^(TyphoonDefinition *definition) {
[definition injectProperty:@selector(quest) with:[self defaultQuest]];
[definition injectProperty:@selector(damselsRescued) with:@(12)];
}];
}
方法注入:
- (Knight *)knightWithMethodInjection
{
return [TyphoonDefinition withClass:[Knight class]
configuration:^(TyphoonDefinition *definition) {
[definition injectMethod:@selector(setQuest:andDamselsRescued:)
parameters:^(TyphoonMethod *method) {
[method injectParameterWith:[self defaultQuest]];
[method injectParameterWith:@321];
}];
}];
}
3.當然還有一些硬性的區別就是Typhoon現在已經支持Swift。
4.兩者維護時間都超過2年以上。
Tythoon官方介紹的優勢:
1)Non-invasive. No macros or XML required. Uses powerful ObjC runtime instrumentation.
2)No magic strings – supports IDE refactoring, code-completion and compile-time checking.
3)Provides full-modularization and encapsulation of configuration details. Let your architecture tell a story.
4)Dependencies declared in any order. (The order that makes sense to humans).
5)Makes it easy to have multiple configurations of the same base-class or protocol.
6)Supports injection of view controllers and storyboard integration. Supports both initializer and property injection, plus life-cycle management.
7)Powerful memory management features. Provides pre-configured objects, without the memory overhead of singletons.
8)Excellent support for circular dependencies.
9)Lean. Has a very low footprint, so is appropriate for CPU and memory constrained devices.
10)While being feature-packed, Typhoon weighs-in at just 3000 lines of code in total.
11)Battle-tested — used in all kinds of Appstore-featured apps.
大體翻譯過來:
1)非侵入性。不需要宏或XML。使用強大的ObjC運行時儀器。
2)沒有魔法字符串——支持IDE重構,完成和編譯時檢查。
3)提供full-modularization和封裝的配置細節。讓你的架構告訴一個故事。
4)依賴關系中聲明的任何順序。(對人類有意義的順序)。
5)很容易有多個配置相同的基類或協議。
6)支持注射的視圖控制器和故事板集成。同時支持初始化器和屬性注入,以及生命周期管理。
7)強大的內存管理功能。提供預配置對象,沒有單件的內存開銷。
8)優秀的支持循環依賴。
9)精益。占用很低,所以適合CPU和內存受限的設備。
10),功能強大,臺風重總共只有3000行代碼。
11)久經沙場,用于各種Appstore-featured應用。
針對這兩個框架網上教程并不多,收集了一些比較有用的資料。最主要的用法還得看官方文檔分別在:
大體學習步驟:
(一)了解依賴注入的原理
依賴注入各大語言都一樣,相關資料:
其中最需要看的是來自
objc.io官網的博文 Dependency Injection 和 Typhoon原創大神(Graham Lee)的文章 Dependency Injection, iOS and You 不看后悔一輩子_
2.某知名博主寫的文章--依賴注入(Dependency Injection)模式
4.國人翻譯的國外牛人的文章---依賴注入——讓iOS代碼更簡潔
進階內容了解和學習框架
首先來看看有關objection的資料
資料比較少
1.Limboy大大大神的--使用objection來模塊化開發iOS項目
其次Typhoon的教程可能就比較詳細了----官網
1.首先來看官方github文檔詳細程度已經不需要其他教程了??????