定義
裝飾模式指的是在不必改變原類文件和使用繼承的情況下,動態(tài)地擴展一個對象的功能。它是通過創(chuàng)建一個包裝對象,也就是裝飾來包裹真實的對象。(其實每次看定義我都是很懵逼的,明白最好還是通過UML 圖和源碼仔細體會才行)
特點
(1) 裝飾對象和真實對象有相同的接口。這樣客戶端對象就能以和真實對象相同的方式和裝飾對象交互。
(2) 裝飾對象包含一個真實對象的引用(reference)
(3) 裝飾對象接受所有來自客戶端的請求。它把這些請求轉(zhuǎn)發(fā)給真實的對象。
(4) 裝飾對象可以在轉(zhuǎn)發(fā)這些請求以前或以后增加一些附加功能。這樣就確保了在運行時,不用修改給定對象的結(jié)構(gòu)就可以在外部增加附加的功能。在面向?qū)ο蟮脑O計中,通常是通過繼承來實現(xiàn)對給定類的功能擴展。
適用性
- 需要擴展一個類的功能,或給一個類添加附加職責。
- 需要動態(tài)的給一個對象添加功能,這些功能可以再動態(tài)的撤銷。
- 需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能,從而使繼承關(guān)系變的不現(xiàn)實。
- 當不能采用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸性增長。另一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。
優(yōu)缺點
優(yōu)點
- 裝飾者模式與繼承關(guān)系的目的都是要擴展對象的功能,但是裝飾者可以提供比繼承更多的靈活性。
- 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創(chuàng)造出很多不同行為的組合。
缺點
- 這種比繼承更加靈活機動的特性,也同時意味著更加多的復雜性。
- 裝飾模式會導致設計中出現(xiàn)許多小類,如果過度使用,會使程序變得很復雜。
- 裝飾模式是針對抽象組件(Component)類型編程。但是,如果你要針對具體組件編程時,就應該重新思考你的應用架構(gòu),以及裝飾者是否合適。當然也可以改變Component接口,增加新的公開的行為,實現(xiàn)“半透明”的裝飾者模式。在實際項目中要做出最佳選擇。
設計原則
- 多用組合,少用繼承。
利用繼承設計子類的行為,是在編譯時靜態(tài)決定的,而且所有的子類都會繼承到相同的行為。然而,如果能夠利用組合的做法擴展對象的行為,就可以在運行時動態(tài)地進行擴展。- 類應設計的對擴展開放,對修改關(guān)閉。(開閉原則)
角色
(1)抽象構(gòu)件(Component)角色:給出一個抽象接口,以規(guī)范準備接收附加責任的對象。
(2)具體構(gòu)件(Concrete Component)角色:定義一個將要接收附加責任的類。
(3)裝飾(Decorator)角色:持有一個構(gòu)件(Component)對象的實例,并實現(xiàn)一個與抽象構(gòu)件接口一致的接口。
(4)具體裝飾(Concrete Decorator)角色:負責給構(gòu)件對象添加上附加的責任。
場景模擬
假設讓你給咖啡店設計算費后臺,咖啡中可以添加不同的配料,牛奶,糖,奶泡等,不同的飲品加上不同的配料會有不同的價格。
UML 圖

簡單代碼
#import <Foundation/Foundation.h>
@protocol Coffce <NSObject>
-(float)getPrice;
-(NSString*)getName;
@end
#import <Foundation/Foundation.h>
#import "Coffce.h"
@interface Decorator : NSObject<Coffce>
@property (nonatomic,strong) id<Coffce> coffce;
- (instancetype)initWithCoffce:(id<Coffce>)coffce;
@end
#import "Decorator.h"
@interface Decorator()
@end
@implementation Decorator
- (instancetype)initWithCoffce:(id<Coffce>)coffce
{
self = [super init];
if (self) {
self.coffce = coffce;
}
return self;
}
@end
#import <Foundation/Foundation.h>
#import "Coffce.h"
@interface SimpleCoffce : NSObject<Coffce>
@end
#import "SimpleCoffce.h"
@interface SimpleCoffce()
@property (nonatomic,assign) float price;
@property (nonatomic,strong) NSString * name;
@end
@implementation SimpleCoffce
- (instancetype)init
{
self = [super init];
if (self) {
self.price = 10;
self.name = @"simpleCoffce";
}
return self;
}
-(float)getPrice{
return self.price;
}
-(NSString *)getName{
return @"simpleCoffice";
};
@end
#import "Decorator.h"
@interface MilkPriceDecorator : Decorator
@end
#import "MilkPriceDecorator.h"
@implementation MilkPriceDecorator
-(float)getPrice{
return [self.coffce getPrice]+7;
}
-(NSString *)getName{
return [[self.coffce getName] stringByAppendingString:@" addMilk"];
}
@end
#import "Decorator.h"
@interface MilkFoamDecrator : Decorator
@end
#import "MilkFoamDecrator.h"
@implementation MilkFoamDecrator
-(float)getPrice{
return [self.coffce getPrice]+12;
}
-(NSString *)getName{
return [[self.coffce getName] stringByAppendingString:@" addMilkFoam"];
}
@end
#import "Decorator.h"
@interface SugarDecrator : Decorator
@end
#import "SugarDecrator.h"
@implementation SugarDecrator
-(float)getPrice{
return [self.coffce getPrice]+5;
}
-(NSString *)getName{
return [[self.coffce getName] stringByAppendingString:@" addSugar"];
}
@end
測試代碼
id <Coffce> coffce = [SimpleCoffce new];
coffce= [[SugarDecrator alloc]initWithCoffce:coffce];
coffce = [[MilkFoamDecrator alloc]initWithCoffce:coffce];
coffce = [[MilkPriceDecorator alloc]initWithCoffce:coffce];
float price = [coffce getPrice];
NSString * name = [coffce getName];
NSLog(@"%@ %lf" ,name,price);
測試結(jié)果
[34339:7420628] simpleCoffice addSugar addMilkFoam addMilk 34.000000
個人理解:裝飾者模式首先你需要一個功能,需要再給這個功能修飾添加新的能力才行,相當于拓展。
百度百科
[借鑒博客](https://blog.csdn.net/gdutxiaoxu/article/details/51885105)
源代碼地址
下一篇博客
結(jié)構(gòu)型設計模式-外觀模式