美文网首页
iOS设计模式-装饰者模式

iOS设计模式-装饰者模式

作者: 渡口丶 | 来源:发表于2019-11-06 17:05 被阅读0次

一、定义

装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

装饰者模式采用了多用组合,少用继承对扩展开放,对修改关闭的OO原则。一个组件可以被无数个装饰者包装。

二、使用场景

  1. 需要扩展一个类的功能,或给一个类添加附加职责。
  2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。
  3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
  4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类。使得子类数目呈爆炸式增长。另一种可能是因为类定义被隐藏,或类定义不能用户生成子类。

三、具体实现

购买咖啡时,会根据要求加入各种调料,例如:牛奶、豆浆、摩卡等等,我们需要根据加入的不同调料收取不同的费用。下面我们使用装饰者模式来实现点单系统,返回正确的价格。

首先我们先确定咖啡是被装饰者,调料是装饰者,一个咖啡理论上可以添加无数的调料。

  1. 创建咖啡协议,所有的咖啡都有名称和价格属性。

     // Baverage.h
     @protocol Baverage <NSObject>
    
     @required
    
     - (NSString *)name;
    
     - (double)cost;
    
     @end
    
  2. 创建调料协议,装饰者和被装饰者必须是一样的类型,也就是需要有共同的超类(咖啡和调料的共同超类是NSObject,分别实现不同的协议)

     // Condiment.h
     @protocol Condiment <Baverage>
    
     - (instancetype)initWithBaverage:(id<Baverage>)baverage;
    
     @end
    
  3. 实现具体的咖啡对象,分别实现咖啡协议

     // Espresso.m
     @implementation Espresso
    
     - (NSString *)name {
         return @"Espresso";
     }
    
     - (double)cost {
         return 1.99;
     }
    
     @end
     
     // HouseBlend.m
     @implementation HouseBlend
    
     - (NSString *)name {
         return @"HouseBlend";
     }
     
     - (double)cost {
         return 0.9;
     }
    
     @end
    
  4. 实现具体的调料对象,实现调料协议.需要引用一个咖啡实例。

     // Moca.m
     @implementation Moca
     
     - (instancetype)initWithBaverage:(id<Baverage>)baverage
     {
         if (self = [super init]) {
             _baverage = baverage;
         }
         
         return self;
     }
     
     - (NSString *)name {
         return [NSString stringWithFormat:@"%@, Moca", [self.baverage name]];
     }
     
     - (double)cost {
         return 0.3 + [self.baverage cost];
     }
    
     @end
     
     // Milk.m
     @implementation Milk
    
     - (instancetype)initWithBaverage:(id<Baverage>)baverage
     {
         if (self = [super init]) {
             _baverage = baverage;
         }
         
         return self;
     }
     
     - (NSString *)name {
         return [NSString stringWithFormat:@"%@, Milk", [self.baverage name]];
     }
     
     - (double)cost {
         return 0.1 + [self.baverage cost];
     }
     
     @end
    
  5. 开始点咖啡

     // 来一杯添加摩卡、牛奶、豆浆的浓缩咖啡
     id<Baverage> baverage = [[Espresso alloc] init];
     baverage = [[Moca alloc] initWithBaverage:baverage];
     baverage = [[Milk alloc] initWithBaverage:baverage];
     baverage = [[Soy alloc] initWithBaverage:baverage];
     NSLog(@"%@ --- %lf",[baverage name], [baverage cost]);
     
     // 一杯加双倍摩卡的黑咖啡
     id<Baverage> houseBlend = [[HouseBlend alloc] init];
     houseBlend = [[Moca alloc] initWithBaverage:houseBlend];
     houseBlend = [[Moca alloc] initWithBaverage:houseBlend];
     NSLog(@"%@ --- %lf",[houseBlend name], [houseBlend cost]);
    

其实装饰模式在使用的时候,和程序中的递归操作很类似,逐级查询价格,逐级返回,最终得到一个总的价格。

四、总结

优点
  1. 装饰者模式与继承关系的目的都是要扩展对象的功能,但是装饰者模式可以提供比继承更多的灵活性。
  2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点
  1. 会在设计中加入大量的小类,如果过度使用,会让程序变得复杂。
  2. 增加代码的复杂度
  3. 需要相同的超类,否则会出现类型不匹配的问题。

Demo地址

相关文章

  • 03-设计模式(包括KVO/KVC)

    iOS开发常用设计模式? 详细blog链接 MVC模式 MVVM模式 代理模式 单例模式 工厂模式 装饰者模式 观...

  • iOS设计模式--中介者模式

    iOS设计模式--中介者模式 iOS设计模式--中介者模式

  • 设计模式

    设计模式 单例模式、装饰者模式、

  • 设计模式笔记汇总

    目录 设计原则 “依赖倒置”原则 未完待续... 设计模式 设计模式——策略模式 设计模式——装饰者模式 设计模式...

  • iOS设计模式-装饰者模式

    一、定义 装饰者模式动态的将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。 装饰者模式采用...

  • iOS设计模式-装饰者模式

    问题: 某煎饼店现有煎饼、手抓饼和烧饼三种商品出售,每种商品都可以另外加鸡蛋或者香肠,现要开发一套商品结算系统,那...

  • java IO 的知识总结

    装饰者模式 因为java的IO是基于装饰者模式设计的,所以要了解掌握IO 必须要先清楚什么事装饰者模式(装饰者模式...

  • iOS设计模式五(访问者,装饰,责任链)

    承接上文iOS设计模式四(组合,迭代器)本文为行为扩展--获取源码 目录1 访问者模式2 装饰模式3 责任链模式 ...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • JavaScript 设计模式核⼼原理与应⽤实践 之 结构型设计

    JavaScript 设计模式核⼼原理与应⽤实践 之 结构型设计模式 装饰器模式,又名装饰者模式。它的定义是“在不...

网友评论

      本文标题:iOS设计模式-装饰者模式

      本文链接:https://www.haomeiwen.com/subject/mbzubctx.html