iOS 设计模式之装饰模式(Decorator)

来源:互联网 发布:spaltoon2 知乎 编辑:程序博客网 时间:2024/06/10 02:53

给一个人穿上衣服,使用装饰者模式

给一个人穿上衣服,首先要定义一个 Person 类。
Person 有一个 name,还可以展示自己穿了什么。

//Person.h@interface Person : NSObject@property (nonatomic, strong) NSString *name;- (void)show;@end

self.name 为 property,其实不用重写 setter,这里还是写一遍。
show 方法输出 self.name。

//Person.m#import "Person.h"@implementation Person- (void)show {    NSLog(@"装饰的 %@",self.name);}#pragma mark - Setters & Getters - (void)setName:(NSString *)name {    _name = name;}@end

再定义一个 Finery 类,继承 Person。这个 Finery 类其实就是 Decorator 类(装饰抽象类)

//Finery.h#import "Person.h"@interface Finery : Person@property (nonatomic,strong) Person *component;@end
//Finery.m#import "Finery.h"@implementation Finery- (void)show {    if (self.component != nil) {        [self.component show];    }}#pragma mark - Setters & Getters- (void)setCompont:(Person *)component {    _component = component;}@end

Finery 不会被直接使用,而是作为具体装饰类的父类存在。具体服饰类,就是 TShirts/Sneakers/BigTrouser 这些类,这些类需要在调用父类 show 方法的同时实现自己特有的方法。

//TShirts.m#import "TShirts.h"@implementation TShirts- (void)show {    [super show];    NSLog(@"T 恤");}@end

那么,在 viewController 中引用 Person 类及具体装饰类(不需引用 Finery 类), 调用如下方法。

- (void)expertmentB {    Person *xc = [Person new];    xc.name = @"小菜";    Sneakers *pqx = [Sneakers new];    BigTrouser *kk = [BigTrouser new];    TShirts *dtx = [TShirts new];    pqx.component = xc;    kk.component = pqx;    dtx.component = kk;    [dtx show];}

输出结果:
2016-02-17 13:12:10.367 Decorator[10940:2666311] 装饰的 小菜
2016-02-17 13:12:10.368 Decorator[10940:2666311] 运动鞋
2016-02-17 13:12:10.368 Decorator[10940:2666311] 垮裤
2016-02-17 13:12:10.368 Decorator[10940:2666311] T 恤

我们只调用了[dtx show],但是 Person、Sneaker、BigTrouser、TShirts 类里的 show 方法都被执行了。

即执行了[xc show]、[pqx show]、[kk show]、[dtx show]中所有的输出语句。

发生了什么呢?调用 [dtx show] 时,首先要执行 [super show],即 Finery 的 show 方法。

可以看出,Finery 的 show 方法调用 [self.component show]。此时 self.component 为 kk(因为 dtx.component = kk;)也就是说,调用[kk show]。

而调用 [kk show] 时,也是首先要执行 [super show],即 Finery 的 show 方法。此时 self.component 为 pqx。

以此类推,便可以看出调用逻辑。

为 装饰对象.component 赋值是关键句。

装饰者模式用 setCompont 对对象进行包装,每个装饰对象只需要关心自己的功能,不需要关心自己是怎么被添加到对象链中去的,而装饰对象的使用,是使用者(viewController)决定的。

装饰模式是为已有功能动态添加更多功能的一种方式。

当系统需要新功能时,向旧类中添加新的代码,这些新代码只是装饰了原有类的核心职责,并没有替换掉原有类的核心职责。新的字段、方法和逻辑增加了原有类的复杂度。

这些新加入的东西仅仅是为了满足一些只在某种特定情况下才执行的特殊需要,不必加入原有类,增加复杂度。

装饰者模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类当中,并让这个类包装它所要装饰的对象。当需要执行特殊行为时,viewController 中的代码就可以在运行时根据需要有选择、按顺序地使用装饰对象了。

装饰模式可以把类中的装饰功能去除,简化类,有效区分核心职责和装饰功能,去除相关类中重复的装饰逻辑。

实例地址:https://github.com/clairehu7/DesignPatterns(03Decorator)

补充说明:
Component 类定义一个对象接口,可以给这些对象动态地添加职责,而 ConcreteComponent 类是定义一个具体对象,也可以给这个对象添加一些职责。本例中只有一个 ConcreteComponent 类 (即 Person类),不需要再抽象出 Component 类。

Decorator 为装饰抽象类(本例中即 Finery 类),继承自 Component,从外类扩展 Component 类的功能。

0 0