裝飾模式:
給原有的物件新增新的功能,但不繼承原有的類。
Cocoa 中 Category 就屬於這種設計模式。
舉例:實現一個執行緒安全的陣列
模板/原型模式:
某個物件,它的構成/建立十分複雜,可以考慮這種模式。
Cocoa 中 NSCoping 就屬於這種模式。
舉例: 假設有一個類 Model,它裡面有 100 個屬性 property1 ~ property100。有個物件 model1,這些屬性都已經複製。現在如果需要一個 model2 和 model3 ,它們都與 model1 只有一個屬性的值是不同的,那麼有一種做法就是 把生成 model1 的 101 行程式碼複製貼上兩次再修改一下。 還有一種做法,在 Model 類中加一個方法:- (Model *)clone;
,然後實現 clone
:
- (Model *)clone {
Model *model = [[self class] init];
model.property1 = self.property1;
...
model.property100 = self.property100;
return model;
}
複製程式碼
這樣我們建立其它 model 的時候就可以這樣做:
Model *model2 = [model1 clone];
model2.propertyN = xxx;
複製程式碼
NSCopying 就是這樣的。NSCopying 協議使用的時候要注意以下問題,假設 Person 類是這樣的:
copyWithZone:的實現: 這樣就會出現一個問題,如下所示: person 的 sons 和 person2 的 sons 完全是同一個物件,假設 sons 可以修改的話,那麼修改 person.sons 和 person2.sons 會相互影響。這完全不是我們想要的結果了。我們可以這樣做:修改之後,看下面這段程式碼的輸出:
person.sons 與 person2.sons 是兩個不同的陣列了。但是裡面的元素卻是相同的。這裡就牽涉到幾個比較繞的概念了:
- 淺拷貝
- 單層拷貝/單層深拷貝/深拷貝
- 完全拷貝(可以用歸檔來處理)
感興趣的話可以自己搜一下。現在我們這種情況屬於第二種。
外觀/Facade模式(可以解耦)
先舉個例子:假設我們要從西安去北京,可以選擇自駕/坐飛機/坐火車等方式,都可以去,可以理解為通過不同的手段達到同一個目的,但是細節不同,但是我們不關心它的細節,只關心它的目的。
外觀模式使用場景:
有一個複雜的子系統,它為了得到某種結果,裡面有很多複雜的邏輯,客戶端只想要這個結果,並不關心裡面複雜的邏輯。可以寫一箇中間類,操作這個子系統,客戶端只用從中間類來獲取結果即可。
外觀模式的好處:
解耦合
簡化操作
外觀模式與介面卡模式的區別:
外觀模式 -- 意圖提供簡單的介面
介面卡模式 -- 轉換介面
舉例:
假設我們有一個 Shape 類,和他的一些子類們:
@interface Shape : NSObject
- (void)draw;
@end
****************************************
@interface Rectangle : Shape
@property (assign, nonatomic) CGFloat width;
@property (assign, nonatomic) CGFloat height;
@end
@implementation Rectangle
- (void)draw
{
繪製一個矩形;
}
@end
****************************************
@interface Circle : Shape
@property (assign, nonatomic) CGFloat radius;
@end
@implementation Circle
- (void)draw
{
繪製一個圓形;
}
@end
複製程式碼
假設我們在 ViewController 中寫了如下程式碼:
- (void)viewDidLoad
{
[super viewDidLoad];
//繪製一個矩形
Rectangle *tangle = [[Rectangle alloc] init];
tangle.width = 10;
tangle.height = 20;
[tangle draw];
//繪製一個圓形
Circle *cir = [[Circle alloc] init];
cir.radius = 5;
[cir draw];
}
複製程式碼
如果 Shape 有多個子類,比如平行四邊形、梯形、八邊形等。那麼它會是一個特別複雜的系統,並且我們還需要知道這個系統的細節,把資料具體地傳遞到每個物件對應的屬性上才可以。
但其實上我們並不關心在這個系統中它們是怎麼實現的,我們就只想讓它畫個圖形就 OK 了。這是可以這麼做,建立一箇中間類 ShapeMaker:
@interface ShapeMaker : Shape
- (void)drawRectangleWithParams:(NSDictionary *)dic;
- (void)drawCircleWithParams:(NSDictionary *)dic;
- (void)drawRectangleAndCircleWithParams:(NSDictionary *)dic;
...
@end
複製程式碼
在 ShapeMaker 中去實現這些複雜的操作,ShapeMaker 提供一些簡單的介面供 ViewController 使用,ViewController 只用使用介面,傳遞資料即可,ViewController 並不關心具體實現,也不知道具體每個資料用在哪個地方,它只是讓 ShapeMaker 畫個形狀就可以了。