定义:
不改变原有对象的前提下,动态地给一个对象增加一些额外的功能.
成员:
- Component, 抽象组件
- ConcreteComponent, 具体组件
- Decorator, 抽象装饰器
- ConcreteDecorator, 具体装饰器
类图:
实例:
装饰器复合开闭原则,在不改变原有类的结构下增加类的功能.例如,HeadFirst系列里的经典案例星巴兹咖啡,定义一个Coffee的抽象类,只能提供咖啡,但通过装饰器SugarCoffee装饰之后扩展了新功能,另外你还可以加点奶之类.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| @interface Coffee : NSObject
- (CGFloat)getCoffeePrice;
@end
@implementation Coffee
- (CGFloat)getCoffeePrice { return 0.f; }
@end
@interface CondimentDecorator : Coffee
@propety (nonatomic, strong) Coffee *coffee; - (instancetpe)initWithCoffee:(Coffee *)coffee;
@end
@implementation CondimentDecorator
- (instancetype)initWithCoffee:(Coffee *)coffee { self = [super init]; if (self) { self.coffee = coffee; } return self; }
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @interface ACoffee : Coffee
- (CGFloat)getCoffeePrice;
@end
@implementation : ACoffee
- (CGFloat)getCoffeePrice { return 1.99; }
- (NSString *)description { return @"A Coffee"; }
@end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @inteface SugerDecorator : CondimentDecorator
@end
@implementation SugerDecorator
- (CGFloat)getCoffeePrice { return [self.coffee getCoffeePrice] + 0.3; }
- (NSString *)description { return [NSString stringWithFormat:@"%@-Sugar",[self.coffee description]]; }
@end
|
1 2 3 4
| Coffee *coffee = [ACoffee new]; coffee = [[SugerDecorator alloc] initWithCoffee:coffee]; NSLog(@"%@-----%@",coffee,@([coffee getCoffeePrice]));
|
优点:
- 装饰器避免了修改原有功能代码,复合开闭原则
- 装饰器在运行时可以动态为对象添加功能,从而达到不同的效果
缺点:
- 需要根据每一个扩展的功能添加具体的装饰类,增加类的数量
总结:
- 对一些类业务本身比较复杂,继承关系比较多的时候,可以考虑用装饰器来扩展