装饰器模式,包装模式
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
通过一种对客户端透明的方式来扩展对象的功能,是继承关系的一种替换方案。
装饰模式就是把要添加的附加功能放在单独的类中,并让这个类包含它要装饰的对象,当需要执行时,客户端就可以有选择地、按顺序地使用装饰功能包装对象。
![](https://img.haomeiwen.com/i3115781/c0c9184ba32d9153.jpg)
角色和职责
- Component 原始类,抽象类(或者说是静态库,不知道具体的实现,又不想使用继承)
定义一个对象接口,可以给这些对象动态地添加职责。 - ConcreteComponent
定义一个对象,可以给这个对象添加一些职责。 - Decorator 抽象装饰者
维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。当仅添加一个职责时,可省略该抽象类。 - ConcreteDecorator 具体装饰者
向组件添加职责。
代码示例
#import <Foundation/Foundation.h>
//此处用协议Car来表示抽象类
@protocol Car <NSObject>
- (void)run1;
@end
@interface RunCar : NSObject<Car>
@end
@implementation RunCar
- (void)run1 {
NSLog(@"汽车在行驶");
}
@end
@interface Decorator : NSObject<Car>
@end
@implementation Decorator
- (void)run1 {
NSLog(@"抽象装饰者");
}
@end
@interface SwimDecorator : Decorator
@property (nonatomic, strong) RunCar *car;
@end
@implementation SwimDecorator
- (instancetype)initWithCar:(id<Car>)car {
if (self = [super init]) {
self.car = car;
}
return self;
}
- (void)swim {
NSLog(@"可以游");
}
- (void)run1 {
[self.car run1];
[self swim];
}
@end
@interface FlyDecorator : Decorator
@property (nonatomic, strong) RunCar *car;
@end
@implementation FlyDecorator
- (instancetype)initWithCar:(id<Car>)car {
if (self = [super init]) {
self.car = car;
}
return self;
}
- (void)fly {
NSLog(@"可以飞");
}
- (void)run1 {
[self.car run1];
[self fly];
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
RunCar *car = [[RunCar alloc] init];
[car run1];
NSLog(@"-----------1");
SwimDecorator *swimCar = [[SwimDecorator alloc]initWithCar:car];
[swimCar run1];
NSLog(@"-----------2");
FlyDecorator *flyCar = [[FlyDecorator alloc]initWithCar:swimCar];
[flyCar run1];
NSLog(@"-----------3");
}
return 0;
}
/*
汽车在行驶
-----------1
汽车在行驶
可以游
-----------2
汽车在行驶
可以游
可以飞
-----------3
*/
用处
主要解决继承关系过于复杂的问题,通过组合替代继承。
分类和装饰器模式的细微区别:
iOS中一般将分类、扩展看作是装饰模式。需要注意分类是在运行时决议的,扩展是在编译时。
另外:
- 分类添加属性
关联对象
- 分类重写被装饰者的方法会"覆盖"
- 不能为系统类添加扩展
- 扩展只以声明的形式存在,多数情况下寄生于宿主类的
.m
中
优点
- 比静态继承更灵活
- 避免在层次结构高层的类有太多的特征
可以先定义一个简单的类,用装饰器者逐渐的添加功能。
缺点
- Decorator与它的Component不一样
Decorator是一个透明的包装。如果我们从对象标识的观点出发,一个被装饰了的组件与这个组件是有差别的,因此,使用装饰时不应该依赖对象标识。 - 有许多小对象
采用装饰器模式进行系统设计往往会产生许多看上去类似的小对象,这些对象仅仅在他们相互连接的方式上有所不同,而不是他们的类或是他们的属性值有所不同。尽管对于那些了解系统的人来说,很容易对他们进行定制,但是很难学习这些系统,排错也很困难。
网友评论