装饰模式是指在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。通过创建一个包装对象,也就是装饰来包裹真实的对象。装饰模式中的装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互,同时装饰对象包含一个真实对象的引用(reference),装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。 装饰模式与继承都可以要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。 通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。

基础设计

单纯的看概念有点单调,看一张经典的装饰模式的UML类图:

Component定义ConcreteComponent和Decorator类要实现的方法,装饰对象和真实对象的之间的通信就是通过Component实现;

ConcreteComponent真实对象,使用ConcreteComponent的派生类提供核心功能,与Decorator是同一级别;

Decorator具有特定装饰功能的类,用来装饰ConcreteComponent类,具体的装饰子类通过继承Decorator实现;

关于整体的轮廓有了一个大概的了解,我们可以通过生活的例子来模拟装饰模式,关于房子,有商业住宅和民用住宅,买了房子我们需要装修,桌子,椅子必不可少,我们最终需要算一下总费用,思考几秒可以看下面具体实现;

功能实现

设计基础类House和协议:

@protocol HouseDelegate <NSObject>

@optional
-(double)totalMoney; @end @interface House : NSObject<HouseDelegate> -(NSString *)detialInfo; @end

House的子类CommercialHouse,被装饰对象:

@implementation CommercialHouse

-(double)totalMoney{
return 360000.89;
} -(NSString *)detialInfo{
return [NSString stringWithFormat:@"商业住宅"];
} @end

装饰对象的基类HouseDecorator,这里需要保持一个对被装饰对象的引用:

@interface HouseDecorator : House

-(instancetype)initWithHouse:(House *)house;

@property  (strong,nonatomic) House *house;

@end
@implementation HouseDecorator

-(instancetype)initWithHouse:(House *)house{
self=[super init];
if (self) {
self.house=house;
}
return self;
}
@end

装饰对象TableDecorator:

@implementation TableDecorator

-(double)totalMoney{
return self.house.totalMoney+10;
} -(NSString *)detialInfo{
return [NSString stringWithFormat:@"%@--桌子",self.house.detialInfo];
} @end

装饰对象ChairDecorator:

@implementation ChairDecorator

-(double)totalMoney{
return self.house.totalMoney+100;
} -(NSString *)detialInfo{
return [NSString stringWithFormat:@"%@--椅子",self.house.detialInfo];
} @end

回到最初的总费用问题,我们看下结果:

    House  *house=[[CommercialHouse alloc]init];
house=[[TableDecorator alloc]initWithHouse:house];
house=[[ChairDecorator alloc]initWithHouse:house];
NSLog(@"房子价格:%f", [house totalMoney]);
NSLog(@"房子详情:%@",[house detialInfo]);
NSLog(@"博客园-FlyElephant");
NSLog(@"http://www.cnblogs.com/xiaofeixiang/");

桌子椅子的价格是可以动态变化的,桌子椅子的数量的也是不确定的,从这些角度看例子稍微有点勉强,不过大概功能设计实现大同小异,万变不离其宗,相信大家会对装饰模式有自己独到的见解~

iOS开发-装饰模式的更多相关文章

  1. iOS开发系列--Swift语言

    概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...

  2. iOS开发系列--打造自己的“美图秀秀”

    --绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果,一方面得益于成功系统的设计,另一方面得益于它强大的开发框架.今天我们将围绕iOS中两大图形.图像绘图框架进行介绍:Quartz ...

  3. iOS开发之再探多线程编程:Grand Central Dispatch详解

    Swift3.0相关代码已在github上更新.之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread.操作队列以及GCD,介绍的不够深入.今天就以GCD为主题来全面的总结一下GCD ...

  4. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

  5. iOS开发系列文章(持续更新……)

    iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...

  6. iOS开发系列--App扩展开发

    概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...

  7. iOS开发系列--Swift进阶

    概述 上一篇文章<iOS开发系列--Swift语言>中对Swift的语法特点以及它和C.ObjC等其他语言的用法区别进行了介绍.当然,这只是Swift的入门基础,但是仅仅了解这些对于使用S ...

  8. iOS开发系列--通讯录、蓝牙、内购、GameCenter、iCloud、Passbook系统服务开发汇总

    --系统应用与系统服务 iOS开发过程中有时候难免会使用iOS内置的一些应用软件和服务,例如QQ通讯录.微信电话本会使用iOS的通讯录,一些第三方软件会在应用内发送短信等.今天将和大家一起学习如何使用 ...

  9. iOS开发系列--通知与消息机制

    概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...

随机推荐

  1. LeetCode(52):N皇后 II

    Hard! 题目描述: n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 上图为 8 皇后问题的一种解法. 给定一个整数 n,返回 n 皇后不同的解决方 ...

  2. Deep Learning系统实训之二:梯度下降原理

    基本概念理解: 一个epoch:当前所有数据都跑(迭代)了一遍: 那么两个epoch,就是把所有数据跑了两遍,三个epoch就是把所有数据跑了三遍,以此类推. batch_size:每次迭代多少个数据 ...

  3. Java中强、软、弱、虚引用

    1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象具有强引用,那垃圾回收器绝不会回收它.当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使 ...

  4. pytest十:用例 a 失败,跳过测试用例 b 和 c 并标记失败 xfail

    当用例 a 失败的时候,如果用例 b 和用例 c 都是依赖于第一个用例的结果,那可以直接跳过用例 b 和 c 的测试,直接给他标记失败 xfail用到的场景,登录是第一个用例,登录之后的操作 b 是第 ...

  5. python接口自动化测试十八:使用bs4框架爬取图片

    # 爬图片# 目标网站:http://699pic.com/sousuo-218808-13-1.htmlimport requestsfrom bs4 import BeautifulSoupimp ...

  6. python 全栈开发,Day126(创业故事,软件部需求,内容采集,显示内容图文列表,MongoDB数据导入导出JSON)

    作业讲解 下载代码: HBuilder APP和flask后端登录 链接:https://pan.baidu.com/s/1eBwd1sVXTNLdHwKRM2-ytg 密码:4pcw 如何打开APP ...

  7. python 全栈开发,Day19(组合,组合实例,初识面向对象小结,初识继承)

    一.组合 表示的一种什么有什么的关系 先来说一下,__init__的作用 class Dog: def __init__(self, name, kind, hp, ad): self.name = ...

  8. MVC中页面的传值方式总结

    MVC中的页面传值,通常指Controller和view之间的数据传递,经常用到的有几种方式,总结如下: 一:ViewData 获取或设置一个字典,其中包含在控制器和视图之间传递的数据.使用ViewD ...

  9. JS高级 - 面向对象3(面向过程改写面向对象)

    改写: 1.前提:所有东西都在 onload 里 2.改写:不能有函数嵌套,可以有全局变量 onload --> 构造函数 全局变量 --> 属性 函数 --> 方法 4.改错: t ...

  10. phpstrom破解

    lisence输入 2018/04/09  更新  license server:http://im.js.cn:8888 http://idea.iteblog.com/key.php 2018/0 ...