装饰者模式定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更加有弹性的替代方案。
我们都知道,可以使用两种方式给一个类或者对象添加行为。
一是使用继承。继承是给一个类添加行为的比较有效的途径。通过使用继承,可以使得子类在拥有自身方法的同时,还可以拥有父类的方法。但是使用继承是静态的,在编译的时候就已经决定了子类的行为,我们不便于控制增加行为的方式和时机。
二是使用关联。组合即将一个对象嵌入到另一个对象中,由另一个对象来决定是否引用该对象来扩展自己的行为。这是一种动态的方式,我们可以在应用程序中动态的控制。
与继承相比,关联关系的优势就在于不会破坏类的封装性,且具有较好的松耦合性,可以使系统更加容易维护。但是它的缺点就在于要创建比继承更多的对象。
优点:
1、装饰者模式可以提供比继承更多的灵活性
2、可以通过一种动态的方式来扩展一个对象的功能,在运行时选择不同的装饰器,从而实现不同的行为。
3、通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。可以使用多个具体装饰类来装饰同一对象,得到功能更为强大的对象。
4、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,在使用时再对其进行组合,原有代码无须改变,符合“开闭原则”。
5、把类中的装饰功能从类中搬移去除,这样可以简化原有的类。有效的把类的核心职责和装饰功能分开,且可以去除相关类中重复的装饰逻辑。
缺点:
1、会产生很多的小对象,增加了系统的复杂性
2、这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为烦琐。
3、对于装饰类的顺序容易出错。
总结:
装饰模式是为已有功能动态地添加更多功能的一种方式,它把每个装饰的功能放在一个单独的类中,并让这个类包装它所要装饰的对象,因此当需要执行特殊行为时,客户代码就可以在运行时根据需要有选择地、按顺序地使用装饰功能包装对象。
项目地址:https://github.com/GameRisker/Study-Design-Patterns.git
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 |
// // main.m // Decoration // // Created by GameRisker on 15/12/20. // Copyright (c) 2015年 GameRisker. All rights reserved. // #import "BigTrouser.h" #import "Person.h" #import "TShirts.h" #import <Foundation/Foundation.h> int main(int argc, const char *argv[]) { @autoreleasepool { // insert code here... Person *person = [[Person alloc] initWithName:@"GameRisker"]; TShirts *shirts = [[TShirts alloc] init]; BigTrouser *bigtrouser = [[BigTrouser alloc] init]; [shirts Decoration:person]; [bigtrouser Decoration:shirts]; [bigtrouser Show]; } return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// // Person.h // // // Created by GameRisker on 15/12/20. // // #import <Foundation/Foundation.h> @interface Person : NSObject { @private NSString *m_name; } - (id)initWithName:(NSString *)name; - (void)Show; @end |
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 |
// // Person.m // // // Created by GameRisker on 15/12/20. // // #import "Person.h" @implementation Person - (id)initWithName:(NSString *)name { if (self = [super init]) { m_name = name; } return self; } - (void)Show { NSLog(@" decorate : %@", m_name); } @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// // Finery.h // // // Created by GameRisker on 15/12/20. // // #import "Person.h" @interface Finery : Person @property(readwrite) Person *m_person; - (void)Decoration:(Person *)person; - (void)Show; @end |
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 |
// // Finery.m // // // Created by GameRisker on 15/12/20. // // #import "Finery.h" @implementation Finery - (void)Decoration:(Person *)person { self.m_person = person; } - (void)Show { if (self.m_person != nil) { [self.m_person Show]; } } @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// // TShirts.h // // // Created by GameRisker on 15/12/20. // // #import "Finery.h" @interface TShirts : Finery @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// // TShirts.m // // // Created by GameRisker on 15/12/20. // // #import "TShirts.h" @implementation TShirts - (void)Show { NSLog(@"this is TShirts!"); [super Show]; } @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// // BigTrouser.h // // // Created by GameRisker on 15/12/20. // // #import "Finery.h" @interface BigTrouser : Finery @end |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// // BigTrouser.m // // // Created by GameRisker on 15/12/20. // // #import "BigTrouser.h" @implementation BigTrouser - (void)Show { NSLog(@"this is BigTrouser!"); [super Show]; } @end |
参考:http://www.cnblogs.com/chenssy/(Java 版本)