設計模式可以說是老生常談的乙個知識點。工作這麼多年來也是陸陸續續看過幾本書。比如《大話設計模式》、《head first 設計模式》,這兩本書是前期接觸比較多,而且質量還是不錯的兩本書,不過之前看的感覺有點像豬八戒吃人參果——食而不知其味。
近來正好又重新拾起設計模式在看另外一本書《設計模式之禪》這本書,這本書較之其他兩本書感覺比較接地氣吧。這次看著很慢,每個模式都在細細的琢磨,再加上之前專案的經驗和這次槽糕的老專案,收穫比較多,感悟也比較深。
要說設計模式,設計原則是必不可缺少的。如果單單去看這幾個原則,其實一眼就能看完。原則只是原則,是要盡量保持,而不是必須保持的哦!所以不能一言而論,根據業務和情景懂得變通。
應該有且僅有乙個原因引起類的變更。這個原則在使用的過程中要做到適度,如果過度使用的話,可以將乙個類中所有的方法都對應做成乙個類。 其實在使用過程中說白了就是根據業務或某一方面將功能歸類,同一功能的放在一起,宣告乙個介面。
比如上圖,我們根據使用者的屬性和用的行為,劃分為兩個介面。
根據以上例子單一原則的有點也是顯而易見:類的複雜性降低,可維護性高。
只要父類出現的地方子類就可以出現,而且替換為子類也不會產生任何錯誤或異常,使用這可能根本就不需要知道是父類還是子類。但是,反過來就不行了。這個原則用到的其實就是類的繼承,在一些情況下繼承的優點不言而喻,不過在專案中不要隨便使用繼承。繼承是可以用其他設計模式替換的,比如裝飾模式等。 繼承具有以下缺點:
如果子類不能完整地實現父類的方法,或者父類的某些方法在子類中已經發生"畸形",則建議斷開父子繼承關係,採用依賴、聚集、組合等關係代替繼承
高層模組不應該依賴底層模組,兩者都應該依賴其抽象(介面或實現類)。一句大白話就是面向介面程式設計
建立單一介面,不要建立臃腫龐大的介面。單一職責要求的是類和介面職責單一,注重的是職責,這是業務邏輯上的劃分,而介面隔離原則要求介面的方法盡量少。
例如乙個介面的職責可能包含10個方法,這10個方法都放在乙個介面中,並且提供給多個模組訪問,各個模組按照規定的許可權來訪問,在系統外通過文件約束「不使用的方法不要訪問」,按照單一職位原則是允許的,按照介面隔離原則是不允許的,因為它要求「盡量使用多個專門的介面」。就是指提供給每個模組的都應該是單一介面,提供給幾個模組就應該有幾個介面,而不是建議乙個龐大的臃腫的介面。 我們在使用元件化的過程中,由於模組間的呼叫,每個模組都對外宣告乙個公共介面,這時候其實就違背了介面隔離原則。比如我們可以按照同一層級呼叫宣告乙個介面,不同層級的呼叫宣告乙個介面。
乙個物件應該對其他物件有最少的了解
乙個軟體實體如類、模組和函式應該對外擴充套件開放,對修改關閉。即軟體實體應該對擴充套件開放,對修改關閉,其含義是說乙個軟體實體應該通過擴充套件來實現變化,而不是通過修改已有的**來實現變化。上邊囉嗦一下設計模式的原則,其實我們在專案實踐中也就是因為**違背了其中的原則,然後進行改進,進而演化出設計模式。
所以設計模式都是基於以上原則產生的。
這次我們介紹的是責任鏈模式
責任鏈模式的重點是在「鏈」上,由一條鏈去處理相似的請求在鏈中決定誰來處理這個請求,並返回相應的結果。通過這個定義不知道大家有沒有能想到應用的場景呢?
像在我們工程中由於業務場景的複雜性,就存在大量的if...else
判斷。這樣的邏輯導致業務交叉在一起,導致每個業務不清晰,擴充套件起來不是很方便,並且在ios中會導致uiviewcontroller
臃腫。
這個時候我們可以引入責任鏈模式,呼叫方不用關心真正的業務處理,只要關心業務分類就行,真正的業務交給乙個實體類來處理。
首先我們看一下責任鏈模式通用類圖
這個看著可能有點不知道所以然,所以我們來個例項講解一下,相信看了之後就會恍然大悟。
這是demo所有的類圖
actionclickprotocol
@protocol actionclickprotocol - (void)handleclick;
- (void)setnext:(id)actionclickhandle;
@end
typedef ns_enum(nsuinteger, handletype) ;
複製**
actionclickhandle
@inte***ce actionclickhandle : nsobject@property (nonatomic,assign)handletype type;
@property (nonatomic,strong)actionclickhandle *nexthandle;
@end
@implementation actionclickhandle
- (void)handleclick
- (void)setnext:(nonnull id)actionclickhandle
@end
複製**
actionclickevent1
@inte***ce actionclickevent1 : actionclickhandle
@end
@implementation actionclickevent1
-(void)handleclick
@end
複製**
actionclickevent2
@inte***ce actionclickevent2 : actionclickhandle
@end
@implementation actionclickevent2
-(void)handleclick
@end
複製**
myhandle這個類是核心對外使用的類
@inte***ce myhandle : nsobject
- (instancetype)initwithtype:(handletype)type;
- (void)handleclick;
@end
@inte***ce 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
return self;
}- (void)handleclickelse
[self.nexthandle handleclick];
}}@end
複製**
使用範例:
myhandle *myhandle = [[myhandle alloc] initwithtype:click2];
[myhandle handleclick];
複製**
我們在使用的過程中可以面向model開發,將model傳入handleclick
方法中。type則是mode中根據介面資料的返回對應的不同型別。
這種使用方法完全可以避免if...else的使用,並且業務邏輯很清晰。
其實專案使用過程中,關鍵一點還是要去發現那塊**會一直變,將經常變換的**進行設計模式的封裝,則以後的**擴充套件是非常的方便
我的部落格
實現領域驅動設計之感悟(一)
接觸領域驅動設計的概念,已有4年了。從看書了解的純理論,到實際專案應用中遇到建模問題的思考,逐漸提公升了建模能力。正好碰到2020年五一放假,想趁這個機會,寫一下我的學習感悟。公司內的業務沉澱達到一定量,現有老系統維護困難,這個時候,有必要引入領域驅動設計,在這裡簡稱ddd。產品經理的業務設計和最終...
前期需求與後期開發之感悟 (1)
2018 11 06 背景 從某同事 架構師 那接手某專案需求,並擔任專案leader,負責專案的需求和開發任務 agile模式 現狀 sprint1 已經開始了,其中包含了很多模組的實現。突然跟客戶方it人員確認某流程時,他說不應該是當前的這種流程,應該怎樣怎樣。我說從我接手這專案需求就是這麼定的...
設計模式 1 策略模式原理及實踐
策略模式作為一種軟體設計模式,指物件有某個行為,但是在不同的場景中,該行為有不同的實現演算法。比如每個人都要 交個人所得稅 但是 在美國交個人所得稅 和 在中國交個人所得稅 就有不同的算稅方法。策略模式的結構組成 抽象策略角色 策略類,通常由乙個介面或者抽象類實現。環境角色 持有乙個策略類的引用,最...