設計模式能夠說是老生常談的一個知識點。工做這麼多年來也是陸陸續續看過幾本書。好比《大話設計模式》、《Head First 設計模式》,這兩本書是前期接觸比較多,並且質量仍是不錯的兩本書,不過以前看的感受有點像豬八戒吃人參果——食而不知其味。編程
不少時候有的人在寫代碼的過程當中對設計模式並不爲然。像本人是作APP開發的,APP開發結束後,迭代和新增業務邏輯不是不少的話,確實之前寫成啥樣其實真的無所謂。直到近來接手了公司一個歷史悠久的主項目,因爲業務的發展,業務邏輯愈來愈多,改動愈來愈大,每次新增業務都舉步維艱,讓我深入的體會到了設計模式的優勢和威力。設計模式
近來正好又從新拾起設計模式在看另一本書《設計模式之禪》這本書,這本書較之其餘兩本書感受比較接地氣吧。此次看着很慢,每一個模式都在細細的琢磨,再加上以前項目的經驗和此次槽糕的老項目,收穫比較多,感悟也比較深。api
要說設計模式,設計原則是必不可缺乏的。若是單單去看這幾個原則,其實一眼就能看完。原則只是原則,是要儘可能保持,而不是必須保持的哦!因此不能一言而論,根據業務和情景懂得變通。函數
應該有且僅有一個緣由引發類的變動。組件化
這個原則在使用的過程當中要作到適度,若是過分使用的話,能夠將一個類中全部的方法都對應作成一個類。 其實在使用過程當中說白了就是根據業務或某一方面將功能歸類,同一功能的放在一塊兒,聲明一個接口。atom
好比上圖,咱們根據用戶的屬性和用的行爲,劃分爲兩個接口。根據以上例子單一原則的有點也是顯而易見:類的複雜性下降,可維護性高。spa
只要父類出現的地方子類就能夠出現,並且替換爲子類也不會產生任何錯誤或異常,使用這可能根本就不須要知道是父類仍是子類。可是,反過來就不行了。設計
這個原則用到的其實就是類的繼承,在一些狀況下繼承的優勢不言而喻,不過在項目中不要隨便使用繼承。繼承是能夠用其餘設計模式替換的,好比裝飾模式等。 繼承具備如下缺點:3d
若是子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生"畸形",則建議斷開父子繼承關係,採用依賴、彙集、組合等關係代替繼承code
高層模塊不該該依賴底層模塊,二者都應該依賴其抽象(接口或實現類)。一句大白話就是面向接口編程
也就是APP開發過程當中,只要有接口文檔,咱們就能夠實現APP啦,不須要後臺人員api的實現。也能夠這麼理解。
創建單一接口,不要創建臃腫龐大的接口。
單一職責要求的是類和接口職責單一,注重的是職責,這是業務邏輯上的劃分,而接口隔離原則要求接口的方法儘可能少。
例如一個接口的職責可能包含10個方法,這10個方法都放在一個接口中,而且提供給多個模塊訪問,各個模塊按照規定的權限來訪問,在系統外經過文檔約束「不使用的方法不要訪問」,按照單一職位原則是容許的,按照接口隔離原則是不容許的,由於它要求「儘可能使用多個專門的接口」。就是指提供給每一個模塊的都應該是單一接口,提供給幾個模塊就應該有幾個接口,而不是建議一個龐大的臃腫的接口。 咱們在使用組件化的過程當中,因爲模塊間的調用,每一個模塊都對外聲明一個公共接口,這時候其實就違背了接口隔離原則。好比咱們能夠按照同一層級調用聲明一個接口,不一樣層級的調用聲明一個接口。
一個對象應該對其餘對象有最少的瞭解
一個軟件實體如類、模塊和函數應該對外擴展開放,對修改關閉。即軟件實體應該對擴展開放,對修改關閉,其含義是說一個軟件實體應該經過擴展來實現變化,而不是經過修改已有的代碼來實現變化。
上邊囉嗦一下設計模式的原則,其實咱們在項目實踐中也就是由於代碼違背了其中的原則,而後進行改進,進而演化出設計模式。
因此設計模式都是基於以上原則產生的。
此次咱們介紹的是責任鏈模式
責任鏈模式的重點是在「鏈」上,由一條鏈去處理類似的請求在鏈中決定誰來處理這個請求,並返回相應的結果。
經過這個定義不知道你們有沒有能想到應用的場景呢?
像在咱們工程中因爲業務場景的複雜性,就存在大量的if...else
判斷。這樣的邏輯致使業務交叉在一塊兒,致使每一個業務不清晰,擴展起來不是很方便,而且在iOS中會致使UIViewController
臃腫。
這個時候咱們能夠引入責任鏈模式,調用方不用關心真正的業務處理,只要關心業務分類就行,真正的業務交給一個實體類來處理。
首先咱們看一下責任鏈模式通用類圖
這個看着可能有點不知道因此然,因此咱們來個實例講解一下,相信看了以後就會恍然大悟。
這是demo全部的類圖
ActionClickProtocol
@protocol ActionClickProtocol <NSObject>
- (void)handleClick;
- (void)setNext:(id<ActionClickProtocol>)actionClickHandle;
@end
typedef NS_ENUM(NSUInteger, HandleType) {
CLICK1,
CLICK2,
};
複製代碼
ActionClickHandle
@interface ActionClickHandle : NSObject<ActionClickProtocol>
@property (nonatomic,assign)HandleType type;
@property (nonatomic,strong)ActionClickHandle *nextHandle;
@end
@implementation ActionClickHandle
- (void)handleClick {
NSLog(@"共有的處理方法");
}
- (void)setNext:(nonnull id<ActionClickProtocol>)actionClickHandle {
self.nextHandle = actionClickHandle;
}
@end
複製代碼
ActionClickEvent1
@interface ActionClickEvent1 : ActionClickHandle
@end
@implementation ActionClickEvent1
-(void)handleClick{
NSLog(@"事件1的處理");
}
@end
複製代碼
ActionClickEvent2
@interface ActionClickEvent2 : ActionClickHandle
@end
@implementation ActionClickEvent2
-(void)handleClick{
NSLog(@"事件2的處理");
}
@end
複製代碼
MyHandle 這個類是核心對外使用的類
@interface MyHandle : NSObject
- (instancetype)initWithType:(HandleType)type;
- (void)handleClick;
@end
@interface MyHandle()
@property (nonatomic,assign)HandleType type;
@property (nonatomic,strong)ActionClickHandle *nextHandle;
@property (nonatomic,strong)ActionClickEvent1 *event1;
@property (nonatomic,strong)ActionClickEvent2 *event2;
@end
@implementation MyHandle
- (instancetype)initWithType:(HandleType)type{
self = [super init];
if (self) {
_type = type;
_event1 = [[ActionClickEvent1 alloc] init];
_event1.type = CLICK1;
_event2 = [[ActionClickEvent2 alloc] init];
_event2.type = CLICK2;
[_event1 setNextHandle:_event2];
self.nextHandle = _event1;
}
return self;
}
- (void)handleClick{
if (self.nextHandle.type==self.type) {
[self.nextHandle handleClick];
}else{
while (self.nextHandle.type!=self.type) {
self.nextHandle = self.nextHandle.nextHandle;
}
[self.nextHandle handleClick];
}
}
@end
複製代碼
使用範例:
MyHandle *myHandle = [[MyHandle alloc] initWithType:CLICK2];
[myHandle handleClick];
複製代碼
咱們在使用的過程當中能夠面向model開發,將model傳入 handleClick
方法中。type則是mode中根據接口數據的返回對應的不一樣類型。
這種使用方法徹底能夠避免if...else的使用,而且業務邏輯很清晰。
其實項目使用過程當中,關鍵一點仍是要去發現那塊代碼會一直變,將常常變換的代碼進行設計模式的封裝,則之後的代碼擴展是很是的方便