穿衣问题,要求写一个给人搭配不同服饰的系统,那种可以换各种各样衣服和裤子的服饰系统,如下图:
首先排除这样的结果设计,如果我需要新增加超人的服饰设计,又得更改Person类,很明显违背了开发-封闭原则(ocp,对扩展的开放,对修改的封闭)。其实把这些服饰类写成子类就好,代码结构
如此,需要增加超人的装扮 ,只需要增加子类即可。不需要对已有的代码进行修改。但是这样还打不到最好,我们需要在控制器里面来开辟诸如'破球鞋'、“垮裤”等对象,将他们一个词一个词的显示出来,就好比是在众目睽睽下穿衣服。
对于这些,应当去优化它们。就可以用到装饰模式:动态的给一个对象添加一些额外的职能,就增加功能来说,装饰模式比添加子类更加灵活。无论是衣服、鞋子、裤子等,其实我们都可以把它理解为对Person的装饰,那么有下图结构:
Person类
1 #import <Foundation/Foundation.h> 2 3 @interface Person : NSObject 4 @property(copy,nonatomic)NSString *name; 5 -(instancetype)initWithName:(NSString *)name; 6 -(void)zhuangban; 7 @end
1 #import "Person.h" 2 3 @implementation Person 4 - (instancetype)initWithName:(NSString *)name 5 { 6 self = [super init]; 7 if (self) { 8 _name=name; 9 } 10 return self; 11 } 12 -(void)zhuangban 13 { 14 NSLog(@"装扮的是:%@",_name); 15 } 16 @end
Clothing类 继承与人类
1 #import "Person.h" 2 3 @interface Clothing : Person //服装类继承与人类 4 @property(strong,nonatomic) Person *decorate;//装饰 5 -(instancetype)initWithDecorate:(Person *)decorate; 6 @end
1 #import "Clothing.h" 2 3 @implementation Clothing 4 -(instancetype)initWithDecorate:(Person *)decorate 5 { 6 if (self=[super init]) { 7 _decorate=decorate; 8 } 9 return self; 10 } 11 12 -(void)zhuangban 13 { 14 if (self.decorate) { 15 [self.decorate zhuangban]; 16 } 17 } 18 @end
TShirts类
1 #import "Clothing.h" 2 3 @interface TShirts : Clothing 4 5 @end
1 #import "TShirts.h" 2 3 @implementation TShirts 4 -(void)zhuangban 5 { 6 [super zhuangban]; 7 NSLog(@"破T恤"); 8 } 9 @end
Pants类
1 #import "Clothing.h" 2 3 @interface Pants : Clothing 4 5 @end
1 #import "Pants.h" 2 3 @implementation Pants 4 -(void)zhuangban 5 { 6 [super zhuangban]; 7 NSLog(@"破裤子"); 8 } 9 10 11 @end
Shoe类
1 #import "Clothing.h" 2 3 @interface Shoe : Clothing 4 5 @end
1 #import "Shoe.h" 2 3 @implementation Shoe 4 -(void)zhuangban 5 { 6 [super zhuangban]; 7 NSLog(@"破鞋子"); 8 } 9 @end
在main.m里
1 #import <Foundation/Foundation.h> 2 #import "Pants.h" 3 #import "Clothing.h" 4 #import "TShirts.h" 5 #import "Pants.h" 6 #import "Shoe.h" 7 8 9 int main(int argc, const char * argv[]) { 10 @autoreleasepool { 11 Person *person=[[Person alloc]initWithName:@"叫花子"]; 12 Clothing *clothing=[[Clothing alloc]initWithDecorate:(person)]; 13 TShirts *tshirts=[TShirts new]; 14 Pants *pants=[Pants new]; 15 Shoe *shoe=[Shoe new]; 16 17 //装饰的顺序可以任意的选择 18 //装饰一 19 tshirts.decorate=clothing; 20 pants.decorate=tshirts; 21 shoe.decorate=pants; 22 [shoe zhuangban]; 23 24 //装饰二 25 shoe.decorate=clothing; 26 tshirts.decorate=shoe; 27 pants.decorate=tshirts; 28 [pants zhuangban]; 29 30 31 32 } 33 return 0; 34 }
运行效果
2016-03-06 22:06:08.089 装饰模式[1280:78257] 装扮的是:叫花子
2016-03-06 22:06:08.091 装饰模式[1280:78257] 破T恤
2016-03-06 22:06:08.091 装饰模式[1280:78257] 破裤子
2016-03-06 22:06:08.091 装饰模式[1280:78257] 破鞋子
2016-03-06 22:06:08.091 装饰模式[1280:78257] 装扮的是:叫花子
2016-03-06 22:06:08.092 装饰模式[1280:78257] 破鞋子
2016-03-06 22:06:08.092 装饰模式[1280:78257] 破T恤
2016-03-06 22:06:08.092 装饰模式[1280:78257] 破裤子
Program ended with exit code: 0
装饰模式的优点:
- 把类中的装饰功能从类中搬移出去,这样可以简化原有的类。
- 当有效的把类中的核心功能和装饰功能区分开了,可以去除相关类中重复的装饰逻辑。