ios 设计模式 - 装饰模式

本文介绍iOS中装饰模式的应用,通过具体实例展示如何为现有对象动态添加职责,而不改变其结构。这种方式不仅简化了原有类的设计,还提高了系统的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

iOS实现装饰模式  其实就是类别,需要添加属性的话需要runtime ,也不难。  简单高效。


在面向对象编程中有个重要的原则,里氏代换原则:一个软件实体如果使用的是一个父类的话,那么一定适用其子类,而且它察觉不出父类对象与子类对象的区别。也就是说,在软件设计里面,把父类替换成它的子类,程序的行为没有变化。简单的说,子类类型必须能替换掉它的父类类型。

就好像继承的概念,子类继承自父类,那么子类可以以父类的身份出现。有这样一个问题,在面向对象设计中,一个是鸟类,一个是企鹅类,如果鸟是可以飞得,企鹅不会飞,那么企鹅是鸟么?企鹅可以继承自鸟类么?

需要面向对象设计,那么意味着,子类拥有父类所以非private的属性和行为,鸟会飞,而企鹅不会,所以企鹅是鸟,但它不能继承自上面那个会飞的鸟类,抽象出一个更高的鸟类,然后分为会飞的鸟子类、不会飞的鸟子类,企鹅应该继承自不会飞的鸟子类。

这因为有了里氏代换原则,才使得继承复用成为可能,只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也可以在父类的基础上增加新的行为。正是由于子类的可替换性才使得父类类型模块在无需修改的情况下就能扩展,这是前面提到的,对扩展的开放,对修改的封闭(ocp原则)。

装饰模式

穿衣问题,要求写一个给人搭配不同服饰的系统,那种可以换各种各样衣服和裤子的服饰系统,如下图:

首先排除这样的结果设计,如果我需要新增加超人的服饰设计,又得更改Person类,很明显违背了开发-封闭原则(ocp,对扩展的开放,对修改的封闭)。其实把这些服饰类写成子类就好,代码结构:

如此,需要增加超人的装扮 ,只需要增加子类即可。不需要对已有的代码进行修改。

就可以用到装饰模式:动态的给一个对象添加一些额外的职能,就增加功能来说,装饰模式比添加子类更加灵活。无论是衣服、鞋子、裤子等,其实我们都可以把它理解为对Person的装饰,那么有下图结构:

代码:

Person类:

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
#import <Foundation/Foundation.h>
@interface  ZYPerson :  NSObject
{
     @protected
     NSString  *_name;
}
- (instancetype)initWithName:( NSString  *)name;
- ( void )display;
@end
#import "ZYPerson.h"
@implementation  ZYPerson
- (instancetype)initWithName:( NSString  *)name
{
     if  ( self  = [ super  init]) {
         _name = name;
     }
     return  self ;
}
- ( void )display
{
     NSLog (@ "装扮的%@:" ,_name);
}
@end

 clothing类:

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
#import "ZYPerson.h"
@interface  ZYClothing : ZYPerson
@property  ( nonatomic , strong) ZYPerson *decorate;
- (instancetype)initWithDecorate:(ZYPerson *)decorate;
@end
#import "ZYClothing.h"
@implementation  ZYClothing
- (instancetype)initWithDecorate:(ZYPerson *)decorate
{
     if  ( self  = [ super  init]) {
         _decorate = decorate;
     }
     return  self ;
}
- ( void )display
{
     if  ( self .decorate) {
         [ self .decorate display];
     }
}
@end

 TShirts类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#import "ZYClothing.h"
@interface  ZYTShirts : ZYClothing
@end
#import "ZYTShirts.h"
@implementation  ZYTShirts
- ( void )display
{
     [ super  display];
     NSLog (@ "大衬衫" );
}
@end

 Pants类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import "ZYClothing.h"
@interface  ZYPants : ZYClothing
@end
#import "ZYPants.h"
@implementation  ZYPants
- ( void )display
{
     [ super  display];
     NSLog (@ "大裤衩" );
}
@end

 Shoe类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#import "ZYClothing.h"
@interface  ZYShoe : ZYClothing
@end
#import "ZYShoe.h"
@implementation  ZYShoe
- ( void )display
{
     [ super  display];
     NSLog (@ "破鞋子" );
}
@end

 viewController里面的代码:

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
#import "ViewController.h"
#import "ZYPerson.h"
#import "ZYClothing.h"
#import "ZYTShirts.h"
#import "ZYPants.h"
#import "ZYShoe.h"
@interface  ViewController ()
@end
@implementation  ViewController
- ( void )viewDidLoad {
     [ super  viewDidLoad];
     // Do any additional setup after loading the view, typically from a nib.
     
     ZYPerson *person = [[ZYPerson alloc] initWithName:@ "晶童鞋" ];
     ZYClothing *clothing = [[ZYClothing alloc] initWithDecorate:person];
     ZYTShirts *shirts = [[ZYTShirts alloc] init];
     ZYPants *pants = [[ZYPants alloc] init];
     ZYShoe *shoe = [[ZYShoe alloc] init];
     
     //装扮过程,相当于在室内穿衣服,控制器并不知道它是怎么的顺序
     shirts.decorate = clothing;
     pants.decorate = shirts;
     shoe.decorate = pants;
     [shoe display];
     
     //第二次装扮
     pants.decorate = clothing;
     shoe.decorate = pants;
     shirts.decorate = shoe;
     [shirts display];
}
@end

 运行效果图:

 额, 这个例子是模仿<大话设计模式>这本书上的例子, 但是感觉不太好. 在iOS中的装饰模式实现有2种方法, 

  1. 系统提供的类别, 某个类的主功能已经完成, 我们需要扩充一些方法, 使用类别更简单的完成此目标;
  2. 第二种方式, 比如Person类功能已经很完善,会开车,工作,学习 ,..., 在极个别场景下需要新的功能, 比如穿衣服的功能, (如果是全量场景都需要此功能还是修改Person合适)
    就使用一个新类CloseingPerson(注意:CloseingPerson继承NSObject,不是继承自Person), 新类持有Person, CloseingPerson中添加衣服属性和穿衣服的动作, 在这个特殊场景下使用CloseingPerson, 同时如果需要使用Person的工作,学习方法, 可以通过[self.person work]进行处理.  
    对使用者而言,有以下好处,
    1. 还是同一个Person, 拥有Person的所有属性和方法,
    2. 同时有可以新增穿衣服的功能,
    3. 对于已经完善的Person功能无任何修改, 不影响Person的核心功能

装饰模式总结:

我觉得装饰模式,是为已有功能动态的添加更多功能的一种方法。但是到底什么时候用它呢?

在本文的最初设计中,当系统需要添加新功能的时候,是向旧的类中添加新的代码,这些新增的代码通常装饰了原有类的核心职能或主要行为。这种设计方式问题在于,他们在主类中增加了新的字段、新的方法、新的逻辑,从而增加了主类的复杂度。而这些新加入的东西仅仅是为了满足一些在某种特定情况下才会执行的特殊行为的需求。

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

装饰模式的优点:

  1. 把类中的装饰功能从类中搬移出去,这样可以简化原有的类。
  2. 当有效的把类中的核心功能和装饰功能区分开了,可以去除相关类中重复的装饰逻辑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值