用OC程式碼認識設計模式(一)--建立型模式 用OC程式碼認識設計模式(二)--結構型模式 用OC程式碼認識設計模式(三)--行為型模式 用OC程式碼認識六大設計原則
- 單一職責原則:類的職責要單一;
- 里氏替換原則:不要破壞繼承體系;
- 依賴倒置原則:要面向介面程式設計;
- 介面隔離原則:設計介面的時候要精簡;
- 迪米特法原則:降低耦合;
- 開放封閉原則:對擴充套件開放,對修改關閉。
#####1、單一職責原則(Single Responsibility Principle,簡稱SRP ) 定義:就一個類而言,應該僅有一個引起它變化的原因。
示例: 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:@"李四"];
/*結果輸出
張三的工資是100
李四的工資是100
*/
複製程式碼
產品上線後,問題出來了,因為員工的崗位不同,工資的計算是不一樣的。一般有三種修改方法:
(1)簡單做法,修改calculateSalary,增加引數
// 計算工資,增加員工崗位的標識(Director:總監;Manager:經理;Staff:普通員工)
- (void)calculateSalary:(NSString *)name flag:(NSString *)flag
{
if ([flag isEqualToString:@"Director"])
{
NSLog(@"%@總監的工資是10000",name);
}
else if ([flag isEqualToString:@"Manager"])
{
NSLog(@"%@經理的工資是1000",name);
}
else if ([flag isEqualToString:@"Staff"])
{
NSLog(@"%@員工的工資是100",name);
}
}
複製程式碼
(2)新建方法
// 總監工資計算
- (void)directorCalculateSalary:(NSString *)name;
// 經理工資計算
- (void)managerCalculateSalary:(NSString *)name;
// 普通員工工資計算
- (void)staffCalculateSalary:(NSString *)name;
複製程式碼
(3)新建類
Director *director = [[Director alloc] init];
Manager *manager = [[Manager alloc] init];
Staff *staff = [[Staff alloc] init];
複製程式碼
上面三種方式各有優缺點,那麼在實際程式設計中,該採用哪一種呢?這個問題沒有標準答案,需要根據實際情況來確定。 但是隻有(3)是符合單一職責原則,也是最複雜的。
#####2、里氏替換原則(Liskov Substitution Principle,簡稱LSP) 定義:在使用基類的的地方可以任意使用其子類,能保證子類完美替換基類。
里氏替換原則通俗的來講就是:子類可以擴充套件父類的功能,但不能改變父類原有的功能。 它包含以下2層含義: 1、子類可以實現父類的抽象方法,但不能覆蓋父類的非抽象方法; 2、子類中可以增加自己特有的方法。
#####3、依賴倒置原則(Dependence Inversion Principle,簡稱DIP) 定義:高層模組不應該依賴於低層模組,二者都應該依賴於抽象;抽象不應該依賴細節;細節應該依賴抽象。
例子: SalaryManage類負責工資的管理;Director是總監類,現在我們要通過SalaryManage類來給總監發放工資了,主要程式碼片段如下所示:
// SalaryManage.h
- (void)calculateSalary:(Director *)director
{
[director calculateSalary];
}
複製程式碼
// 員工類
Director *director = [[Directoralloc] init];
director.strName = @"張三";
// 工資管理(財務部)
SalaryManage *salaryManage = [[SalaryManagealloc] init];
[salaryManage calculateSalary:director];
複製程式碼
假設我們還需要給普通員工、財務總監、研發總監等更多的崗位傳送工資,那麼我們就只能不斷的去修改SalaryManage類來滿足業務的需求。產生這種現象的原因就是SalaryManage與Director之間的耦合性太高了,必須降低它們之間的耦合度才行。因此我們引入一個委託EmployeeDelegate,它提供一個發放工資的方法定義,如下所示: 然後我們讓具體的員工類Director、Manager等都實現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) 定義:類間的依賴關係應該建立在最小的介面上
在這裡,我們定義了一個動物活動的介面IAnimal,裡面有4個方法:飛行fly、行走walk、吃eat和工作work,然後分別用人類People和鳥類Bird實現了這個介面。中國人類ChinesePeople和鸚鵡類Parrot通過介面IAnimal分別依賴類People和類Bird。很明顯,對於ChinesePeople來說,fly方法是多餘的,因為人不會飛;對於Parrot類來說,work方法是多餘的,因為鸚鵡不需要工作。介面IAnimal對於類ChinesePeople和類Parrot來說不是最小介面。解決方案
將臃腫的介面IAnimal拆分為獨立的幾個介面,類ChinesePeople和類Parrot分別與它們需要的介面建立依賴關係,也就是採用介面隔離原則。修改後的UML圖如下所示:
#####5、迪米特法則(Law of Demeter,簡稱LoD) 定義:如果兩個類不必彼此直接通訊,那麼這兩個類就不應當發生直接的相互作用。如果其中的一個類需要呼叫另一個類的某一個方法的話,可以通過第三者轉發這個呼叫,這裡的第三者就是介面InmatesDelegate。
#####6、開放封閉原則(Open Close Principle,簡稱OCP)
定義:一個軟體實體(如類、模組、函式)應當對擴充套件開放,對修改關閉。
儘量讓設計的類做好後就不再修改,如果有新的需求,通過新加類的方式來滿足,而不去修改現有的類(程式碼)。