用OC代碼認(rèn)識設(shè)計模式(一)--創(chuàng)建型模式
用OC代碼認(rèn)識設(shè)計模式(二)--結(jié)構(gòu)型模式
用OC代碼認(rèn)識設(shè)計模式(三)--行為型模式
用OC代碼認(rèn)識六大設(shè)計原則
- 單一職責(zé)原則:類的職責(zé)要單一;
- 里氏替換原則:不要破壞繼承體系;
- 依賴倒置原則:要面向接口編程;
- 接口隔離原則:設(shè)計接口的時候要精簡修肠;
- 迪米特法原則:降低耦合逊谋;
- 開放封閉原則:對擴展開放禀崖,對修改關(guān)閉。
1粮彤、單一職責(zé)原則(Single Responsibility Principle兵志,簡稱SRP )
定義:就一個類而言醇蝴,應(yīng)該僅有一個引起它變化的原因。
示例:
1想罕、員工的工資計算悠栓。剛開始的時候,我們會新建一個員工類按价,在員工類里面有一個計算工資的方法闸迷,代碼如下所示:
//Employee.h
@interface Employee : NSObject
// 計算工資
- (void)calculateSalary:(NSString *)name;
@end
//Employee.m
@implementation Employee
- (void)calculateSalary:(NSString *)name
{
NSLog(@"%@的工資是100",name);
}
@end
Employee *employee = [[Employee alloc] init];
[employee calculateSalary:@"張三"];
[employee calculateSalary:@"李四"];
/*結(jié)果輸出
張三的工資是100
李四的工資是100
*/
產(chǎn)品上線后,問題出來了俘枫,因為員工的崗位不同,工資的計算是不一樣的逮走。一般有三種修改方法:
(1)簡單做法鸠蚪,修改calculateSalary,增加參數(shù)
// 計算工資,增加員工崗位的標(biāo)識(Director:總監(jiān);Manager:經(jīng)理;Staff:普通員工)
- (void)calculateSalary:(NSString *)name flag:(NSString *)flag
{
if ([flag isEqualToString:@"Director"])
{
NSLog(@"%@總監(jiān)的工資是10000",name);
}
else if ([flag isEqualToString:@"Manager"])
{
NSLog(@"%@經(jīng)理的工資是1000",name);
}
else if ([flag isEqualToString:@"Staff"])
{
NSLog(@"%@員工的工資是100",name);
}
}
(2)新建方法
// 總監(jiān)工資計算
- (void)directorCalculateSalary:(NSString *)name;
// 經(jīng)理工資計算
- (void)managerCalculateSalary:(NSString *)name;
// 普通員工工資計算
- (void)staffCalculateSalary:(NSString *)name;
(3)新建類
Director *director = [[Director alloc] init];
Manager *manager = [[Manager alloc] init];
Staff *staff = [[Staff alloc] init];
上面三種方式各有優(yōu)缺點师溅,那么在實際編程中茅信,該采用哪一種呢?這個問題沒有標(biāo)準(zhǔn)答案墓臭,需要根據(jù)實際情況來確定蘸鲸。
但是只有(3)是符合單一職責(zé)原則,也是最復(fù)雜的窿锉。
2酌摇、里氏替換原則(Liskov Substitution Principle,簡稱LSP)
定義:在使用基類的的地方可以任意使用其子類膝舅,能保證子類完美替換基類。
里氏替換原則通俗的來講就是:子類可以擴展父類的功能窑多,但不能改變父類原有的功能仍稀。
它包含以下2層含義:
1、子類可以實現(xiàn)父類的抽象方法埂息,但不能覆蓋父類的非抽象方法技潘;
2、子類中可以增加自己特有的方法千康。
3享幽、依賴倒置原則(Dependence Inversion Principle,簡稱DIP)
定義:高層模塊不應(yīng)該依賴于低層模塊,二者都應(yīng)該依賴于抽象拾弃;抽象不應(yīng)該依賴細(xì)節(jié)值桩;細(xì)節(jié)應(yīng)該依賴抽象。
例子:
SalaryManage類負(fù)責(zé)工資的管理砸彬;Director是總監(jiān)類颠毙,現(xiàn)在我們要通過SalaryManage類來給總監(jiān)發(fā)放工資了,主要代碼片段如下所示:
// SalaryManage.h
- (void)calculateSalary:(Director *)director
{
[director calculateSalary];
}
// 員工類
Director *director = [[Directoralloc] init];
director.strName = @"張三";
// 工資管理(財務(wù)部)
SalaryManage *salaryManage = [[SalaryManagealloc] init];
[salaryManage calculateSalary:director];
假設(shè)我們還需要給普通員工砂碉、財務(wù)總監(jiān)蛀蜜、研發(fā)總監(jiān)等更多的崗位發(fā)送工資,那么我們就只能不斷的去修改SalaryManage類來滿足業(yè)務(wù)的需求增蹭。產(chǎn)生這種現(xiàn)象的原因就是SalaryManage與Director之間的耦合性太高了滴某,必須降低它們之間的耦合度才行。因此我們引入一個委托EmployeeDelegate滋迈,它提供一個發(fā)放工資的方法定義霎奢,如下所示:
然后我們讓具體的員工類Director、Manager等都實現(xiàn)EmployeeDelegate委托方法
@protocol EmployeeDelegate <NSObject>
- (void)calculateSalary;
@end
// 修改后的SalaryManage計算工資方法:
- (void)calculateSalary:(id<EmployeeDelegate>)employee
{
[employee calculateSalary];
}
// 使用例子
Director *director = [[Directoralloc] init];
director.strName = @"張三";
Manager *manager = [[Manageralloc] init];
manager.strName = @"李四";
SalaryManage *salaryManage = [[SalaryManagealloc] init];
[salaryManage calculateSalary:director];
[salaryManage calculateSalary:manager];
這與對象適配器模式差不多饼灿。
4幕侠、接口隔離原則(Interface Segregation Principle,簡稱ISP)
定義:類間的依賴關(guān)系應(yīng)該建立在最小的接口上
在這里,我們定義了一個動物活動的接口IAnimal碍彭,里面有4個方法:飛行fly晤硕、行走walk、吃eat和工作work庇忌,然后分別用人類People和鳥類Bird實現(xiàn)了這個接口舞箍。中國人類ChinesePeople和鸚鵡類Parrot通過接口IAnimal分別依賴類People和類Bird。很明顯皆疹,對于ChinesePeople來說疏橄,fly方法是多余的,因為人不會飛略就;對于Parrot類來說捎迫,work方法是多余的晃酒,因為鸚鵡不需要工作。接口IAnimal對于類ChinesePeople和類Parrot來說不是最小接口立砸。
解決方案
將臃腫的接口IAnimal拆分為獨立的幾個接口掖疮,類ChinesePeople和類Parrot分別與它們需要的接口建立依賴關(guān)系,也就是采用接口隔離原則颗祝。修改后的UML圖如下所示:
5浊闪、迪米特法則(Law of Demeter,簡稱LoD)
定義:如果兩個類不必彼此直接通信,那么這兩個類就不應(yīng)當(dāng)發(fā)生直接的相互作用螺戳。如果其中的一個類需要調(diào)用另一個類的某一個方法的話搁宾,可以通過第三者轉(zhuǎn)發(fā)這個調(diào)用,這里的第三者就是接口InmatesDelegate倔幼。
6盖腿、開放封閉原則(Open Close Principle,簡稱OCP)
定義:一個軟件實體(如類、模塊损同、函數(shù))應(yīng)當(dāng)對擴展開放翩腐,對修改關(guān)閉。
盡量讓設(shè)計的類做好后就不再修改膏燃,如果有新的需求茂卦,通過新加類的方式來滿足,而不去修改現(xiàn)有的類(代碼)组哩。