基本概念的解讀
裝飾模式是指在不必改變?cè)?lèi)文件和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裹真實(shí)的對(duì)象。裝飾模式中的裝飾對(duì)象和真實(shí)對(duì)象有相同的接口。這樣客戶(hù)端對(duì)象就能以和真實(shí)對(duì)象相同的方式和裝飾對(duì)象交互,同時(shí)裝飾對(duì)象包含一個(gè)真實(shí)對(duì)象的引用(reference),裝飾對(duì)象接受所有來(lái)自客戶(hù)端的請(qǐng)求。它把這些請(qǐng)求轉(zhuǎn)發(fā)給真實(shí)的對(duì)象。 裝飾模式與繼承都可以要擴(kuò)展對(duì)象的功能,但是裝飾模式可以提供比繼承更多的靈活性。 通過(guò)使用不同的具體裝飾類(lèi)以及這些裝飾類(lèi)的排列組合,可以創(chuàng)造出很多不同行為的組合。

Component:定義ConcreteComponent和Decorator類(lèi)要實(shí)現(xiàn)的方法,裝飾對(duì)象和真實(shí)對(duì)象的之間的通信就是通過(guò)Component實(shí)現(xiàn);
ConcreteComponent:真實(shí)對(duì)象,使用ConcreteComponent的派生類(lèi)提供核心功能,與Decorator是同一級(jí)別;
Decorator:具有特定裝飾功能的類(lèi),用來(lái)裝飾ConcreteComponent類(lèi),具體的裝飾子類(lèi)通過(guò)繼承Decorator實(shí)現(xiàn);
代碼的實(shí)現(xiàn)
定義一個(gè)Persion類(lèi),有name這個(gè)屬性,show方法展示name,如果需要添加一類(lèi)是穿T恤,另一類(lèi)是穿小破鞋的代碼如下,創(chuàng)建persion基類(lèi)
#import <Foundation/Foundation.h>
@interface Persion : NSObject
@property (nonatomic, strong)NSString *name;
- (void)show;
@end
#import "Persion.h"
@implementation Persion
- (void)show
{
NSLog(@"裝飾的%@",self.name);
}
@end
創(chuàng)建一個(gè)類(lèi)Finery,功能是提示這是一類(lèi)好人
#import "Persion.h"
@interface Finery : NSObject
@property (nonatomic, strong)Persion *component;
- (void)show;
@end
#import "Finery.h"
@implementation Finery
- (void)show
{
if (self.component != nil) {
[self.component show];
}
NSLog(@"好人");
}
創(chuàng)建穿T恤的人
#import "Finery.h"
@interface TShirts : Finery
@property (nonatomic, strong)Finery *component;
@end
#import "TShirts.h"
@implementation TShirts
- (void)show
{
if (self.component != nil) {
[self.component show];
NSLog(@"穿個(gè)體恤");
}
}
@end
創(chuàng)建穿小破鞋的人
#import "Finery.h"
@interface Shoot : Finery
@property (nonatomic, strong)Finery *component;
@end
#import "Shoot.h"
@implementation Shoot
- (void)show
{
if (self.component != nil) {
[self.component show];
NSLog(@"穿個(gè)了小破鞋");
}
}
@end
創(chuàng)建穿小破鞋和穿體恤的人
Persion *persion = [[Persion alloc] init];
persion.name = @"蘿卜";
Finery *fine = [[Finery alloc] init];
fine.component = persion;
TShirts *shirts = [[TShirts alloc] init];
shirts.component = fine;
[shirts show];
Shoot *shoot = [[Shoot alloc] init];
shoot.component = fine;
[shoot show];
代碼中所有的繼承都是為了那個(gè)show方法,如果每個(gè)類(lèi)都單寫(xiě)的話(huà),這些類(lèi)繼承NSObject即可,這樣在實(shí)際的代碼中就需要繼承。
裝飾模式和繼承的區(qū)別
為什么要使用裝飾模式呢?
在項(xiàng)目開(kāi)發(fā)的過(guò)程中,當(dāng)客戶(hù)提出了個(gè)新的需求(這個(gè)新的需求需要對(duì)我們的某個(gè)類(lèi)進(jìn)行改動(dòng)),為了這個(gè)新的需求,當(dāng)然我們會(huì)想到去擴(kuò)展某個(gè)類(lèi),擴(kuò)展類(lèi)的功能我們可以使用繼承和裝飾來(lái)達(dá)到我們的目的。那到底我們是使用繼承呢還是裝飾呢?如果使用繼承,那么我們貿(mào)然的就去修改這個(gè)類(lèi),勢(shì)必會(huì)影響其他的類(lèi)。如果使用裝飾模式來(lái)解決這個(gè)問(wèn)題的話(huà),我們就可以在不修改源代碼的基礎(chǔ)上去增強(qiáng)這個(gè)類(lèi)的功能。
擴(kuò)展性非常好:在一個(gè)項(xiàng)目中,你會(huì)有非常多因素考慮不到,特別是業(yè)務(wù)的變更,時(shí)不時(shí)的冒出一個(gè)需求,特別是提出一個(gè)令項(xiàng)目大量延遲的需求時(shí)候,那種心情是…,真想罵娘!裝飾模式可以給我們很好的幫助,通過(guò)裝飾模式重新封裝一個(gè)類(lèi),而不是通過(guò)繼承來(lái)完成,簡(jiǎn)單點(diǎn)說(shuō),三個(gè)繼承關(guān)系ClassA,ClassB,ClassC 三個(gè)類(lèi),我要在ClassB 類(lèi)上增強(qiáng)一些功能怎么辦?我想你會(huì)堅(jiān)決的頂回去!不允許,對(duì)了,為什么呢?你增強(qiáng)的功能是修改ClassB 類(lèi)中的方法嗎?增加方法嗎 ?對(duì)ClassC的影響呢?特別是ClassC 有多個(gè)的情況,你怎么辦?這個(gè)評(píng)估的工作量就是夠你受的,所以這個(gè)是不允許的,那還是要解決問(wèn)題的呀,怎么辦?通過(guò)建立ClassBDecorator 類(lèi)來(lái)修飾ClassB,等于說(shuō)是創(chuàng)建了一個(gè)新的類(lèi),這個(gè)對(duì)原有程序沒(méi)有變更,通過(guò)擴(kuò)充很好的完成了這次變更。