基本概念的解讀
裝飾模式是指在不必改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。通過創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來包裹真實(shí)的對(duì)象。裝飾模式中的裝飾對(duì)象和真實(shí)對(duì)象有相同的接口。這樣客戶端對(duì)象就能以和真實(shí)對(duì)象相同的方式和裝飾對(duì)象交互,同時(shí)裝飾對(duì)象包含一個(gè)真實(shí)對(duì)象的引用(reference),裝飾對(duì)象接受所有來自客戶端的請(qǐng)求。它把這些請(qǐng)求轉(zhuǎn)發(fā)給真實(shí)的對(duì)象。 裝飾模式與繼承都可以要擴(kuò)展對(duì)象的功能,但是裝飾模式可以提供比繼承更多的靈活性。 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創(chuàng)造出很多不同行為的組合。
Component:定義ConcreteComponent和Decorator類要實(shí)現(xiàn)的方法,裝飾對(duì)象和真實(shí)對(duì)象的之間的通信就是通過Component實(shí)現(xiàn);
ConcreteComponent:真實(shí)對(duì)象,使用ConcreteComponent的派生類提供核心功能,與Decorator是同一級(jí)別;
Decorator:具有特定裝飾功能的類,用來裝飾ConcreteComponent類,具體的裝飾子類通過繼承Decorator實(shí)現(xiàn);
代碼的實(shí)現(xiàn)
定義一個(gè)Persion類,有name這個(gè)屬性,show方法展示name,如果需要添加一類是穿T恤,另一類是穿小破鞋的代碼如下,創(chuàng)建persion基類
#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è)類Finery,功能是提示這是一類好人
#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è)類都單寫的話,這些類繼承NSObject即可,這樣在實(shí)際的代碼中就需要繼承。
裝飾模式和繼承的區(qū)別
為什么要使用裝飾模式呢?
在項(xiàng)目開發(fā)的過程中,當(dāng)客戶提出了個(gè)新的需求(這個(gè)新的需求需要對(duì)我們的某個(gè)類進(jìn)行改動(dòng)),為了這個(gè)新的需求,當(dāng)然我們會(huì)想到去擴(kuò)展某個(gè)類,擴(kuò)展類的功能我們可以使用繼承和裝飾來達(dá)到我們的目的。那到底我們是使用繼承呢還是裝飾呢?如果使用繼承,那么我們貿(mào)然的就去修改這個(gè)類,勢(shì)必會(huì)影響其他的類。如果使用裝飾模式來解決這個(gè)問題的話,我們就可以在不修改源代碼的基礎(chǔ)上去增強(qiáng)這個(gè)類的功能。
擴(kuò)展性非常好:在一個(gè)項(xiàng)目中,你會(huì)有非常多因素考慮不到,特別是業(yè)務(wù)的變更,時(shí)不時(shí)的冒出一個(gè)需求,特別是提出一個(gè)令項(xiàng)目大量延遲的需求時(shí)候,那種心情是…,真想罵娘!裝飾模式可以給我們很好的幫助,通過裝飾模式重新封裝一個(gè)類,而不是通過繼承來完成,簡單點(diǎn)說,三個(gè)繼承關(guān)系ClassA,ClassB,ClassC 三個(gè)類,我要在ClassB 類上增強(qiáng)一些功能怎么辦?我想你會(huì)堅(jiān)決的頂回去!不允許,對(duì)了,為什么呢?你增強(qiáng)的功能是修改ClassB 類中的方法嗎?增加方法嗎 ?對(duì)ClassC的影響呢?特別是ClassC 有多個(gè)的情況,你怎么辦?這個(gè)評(píng)估的工作量就是夠你受的,所以這個(gè)是不允許的,那還是要解決問題的呀,怎么辦?通過建立ClassBDecorator 類來修飾ClassB,等于說是創(chuàng)建了一個(gè)新的類,這個(gè)對(duì)原有程序沒有變更,通過擴(kuò)充很好的完成了這次變更。