设计模式之装饰模式(iOS开发,代码用Objective-C展示)
在面向对象编程中有个重要的原则,里氏代换原则:一个软件实体如果使用的是一个父类的话,那么一定适用其子类,而且它察觉不出父类对象与子类对象的区别。也就是说,在软件设计里面,把父类替换成它的子类,程序的行为没有变化。简单的说,子类类型必须能替换掉它的父类类型。
就好像继承的概念,子类继承自父类,那么子类可以以父类的身份出现。有这样一个问题,在面向对象设计中,一个是鸟类,一个是企鹅类,如果鸟是可以飞得,企鹅不会飞,那么企鹅是鸟么?企鹅可以继承自鸟类么?
需要面向对象设计,那么意味着,子类拥有父类所以非private的属性和行为,鸟会飞,而企鹅不会,所以企鹅是鸟,但它不能继承自上面那个会飞的鸟类,抽象出一个更高的鸟类,然后分为会飞的鸟子类、不会飞的鸟子类,企鹅应该继承自不会飞的鸟子类。
这因为有了里氏代换原则,才使得继承复用成为可能,只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能真正被复用,而子类也可以在父类的基础上增加新的行为。正是由于子类的可替换性才使得父类类型模块在无需修改的情况下就能扩展,这是前面提到的,对扩展的开放,对修改的封闭(ocp原则)。
装饰模式
穿衣问题,要求写一个给人搭配不同服饰的系统,那种可以换各种各样衣服和裤子的服饰系统,如下图:
首先排除这样的结果设计,如果我需要新增加超人的服饰设计,又得更改Person类,很明显违背了开发-封闭原则(ocp,对扩展的开放,对修改的封闭)。其实把这些服饰类写成子类就好,代码结构:
如此,需要增加超人的装扮 ,只需要增加子类即可。不需要对已有的代码进行修改。但是这样还打不到最好,我们需要在控制器里面来开辟诸如"破球鞋"、“垮裤”等对象,将他们一个词一个词的显示出来,就好比是在众目睽睽下穿衣服。
对于这些,应当去优化它们。就可以用到装饰模式:动态的给一个对象添加一些额外的职能,就增加功能来说,装饰模式比添加子类更加灵活。无论是衣服、鞋子、裤子等,其实我们都可以把它理解为对Person的装饰,那么有下图结构:
代码:
Person类:
#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类:
#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类:
#import "ZYClothing.h" @interface ZYTShirts : ZYClothing @end #import "ZYTShirts.h" @implementation ZYTShirts
- (void)display
{
[super display];
NSLog(@"大衬衫");
}
@end
Pants类:
#import "ZYClothing.h" @interface ZYPants : ZYClothing @end #import "ZYPants.h" @implementation ZYPants
- (void)display
{
[super display];
NSLog(@"大裤衩");
}
@end
Shoe类:
#import "ZYClothing.h" @interface ZYShoe : ZYClothing @end #import "ZYShoe.h" @implementation ZYShoe
- (void)display
{
[super display];
NSLog(@"破鞋子");
}
@end
viewController里面的代码:
#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
运行效果图:
装饰模式总结:
我觉得装饰模式,是为已有功能动态的添加更多功能的一种方法。但是到底什么时候用它呢?
在本文的最初设计中,当系统需要添加新功能的时候,是向旧的类中添加新的代码,这些新增的代码通常装饰了原有类的核心职能或主要行为。这种设计方式问题在于,他们在主类中增加了新的字段、新的方法、新的逻辑,从而增加了主类的负责度。而这些新加入的东西仅仅是为了满足一些在某种特定情况下才会执行的特殊行为的需求。
而装饰模式提供了一个非常好的解决方案,它把每个要装饰的功能放在单独的类中,并让这个类包含它所要装饰的对象,因此,当执行特殊行为时,在viewController里就可以根据需求有选择、按顺序的使用装饰功能包装对象了。
所以就有了上面的代码,我可以通过装饰,让person武装到牙齿,也可以只让他穿条内裤。
装饰模式的优点:
- 把类中的装饰功能从类中搬移出去,这样可以简化原有的类。
- 当有效的把类中的核心功能和装饰功能区分开了,可以去除相关类中重复的装饰逻辑。
设计模式之装饰模式(iOS开发,代码用Objective-C展示)的更多相关文章
- iOS开发核心语言Objective C —— 全部知识点总结
本分享是面向有意向从事iOS开发的伙伴及苹果产品的发烧友,亦或是已经从事了iOS的开发人员,想进一步提升者.假设您对iOS开发有极高的兴趣,能够与我一起探讨iOS开发.一起学习,共同进步.假设您是零基 ...
- iOS开发核心语言Objective C —— 所有知识点总结
C和OC对比 OC中主要开发在什么平台上的应用程序?答:可以使用OC开发Mac OS X平台和iOS平台的应用程序 OC中新增关键字大部分是以什么开头?答:OC中新增关键字大部分是以@开头 OC中新增 ...
- iOS开发核心语言Objective C —— 面向对象思维、setter和getter方法及点语法
本分享是面向有意向从事iOS开发的伙伴们.或者已经从事了iOS的开发人员.假设您对iOS开发有极高的兴趣,能够与我一起探讨iOS开发.一起学习,共同进步.假设您是零基础,建议您先翻阅我之前分享的iOS ...
- IOS开发-代码规范
代码风格的重要性对于一个团队和项目来说不言而喻.网上有许多 Objective-C 的代码风格,但这份简洁而又最符合苹果的规范,同时有助于养成良好的代码习惯,也是我们团队一直遵循的代码风格. 写法没有 ...
- iOS开发 代码 或 <Home+Power>截屏
1. 截屏的两种简单方法, 注意这两种截图方法,都必须在视图完全加载完成后才能截图,即在 viewDidAppear 方法之后截屏,否则无法得到想要的截屏效果 (1) 利用绘图方法 renderI ...
- iOS开发代码规范(通用)
1. 关于命名 1> 统一要求 含义清楚,尽量做到不需要注释也能了解其作用,若做不到,就加注释 使用全称,不适用缩写 2> 类的命名 大驼峰式命名:每个单词的首字母都采用大写字母 例子:M ...
- iOS开发代码规范
1.关于命名 1.1统一要求 含义清楚, 尽量做到不需要注释也能了解其作用,若做不到,就加注释 使用全称不使用缩写 1.2类的命名 大驼峰式命名:每一个单词的首字母都采用大写字母例子: MFHomeP ...
- iOS - 开发代码部分规范
1. 关于命名 1.1 统一要求 含义清楚,尽量做到不需要注释也能了解其作用,若做不到,就加注释 使用全称,不适用缩写 1.2 类的命名 大驼峰式命名:每个单词的首字母都采用大写字母 例子:MFHom ...
- IOS开发代码分享之获取启动画面图片的string
http://www.jb51.net/article/55309.htm 本代码支持 iPhone 6 以下. 支持 iPhone 及 iPad ? 1 2 3 4 5 6 7 8 9 10 11 ...
- [IOS 开发代码]UIImage+Blur 网络图片模糊用法
UIImage-Helpers 网络图片模糊用法 float quality = .00001f; float blurred = .5f; NSURL *url = [NSURL URLW ...
随机推荐
- Kickstart无人值守安装[转载]
导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装. 常规的办法有什么? 光盘安装系统===>一个服务器DV ...
- TCP三次握手连接
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握 ...
- 【Struts2】Struts2获取session的三种方式
1.Map<String,Object> map = ActionContext.getContext().getSession(); 2.HttpSession session = S ...
- 一个“蝇量级” C 语言协程库
协程(coroutine)顾名思义就是“协作的例程”(co-operative routines).跟具有操作系统概念的线程不一样,协程是在用户空间利用程序语言的语法语义就能实现逻辑上类似多任务的编程 ...
- exp、Exploit、Exploit Pack、exp-gui、Payload、MetaSploit都是啥?
对于走在安全路上的小菜来说,这几个exp.Exploit.Exploit Pack.exp-gui.Payload.MetaSploit名词着实把人转的不轻,以下给大家解释下: Exp,就是Explo ...
- java 和 C++ Socket通信(java作为服务端server,C++作为客户端client,解决中文乱码问题GBK和UTF8)
原文链接: http://www.cnblogs.com/kenkofox/archive/2010/04/25/1719649.html 代码: http://files.cnblogs.com/k ...
- 如何将shell的打印日志输入到日志文件
如果shell打印的日志很多,屏幕无法完全显示,需要查看shell执行的情况,这是就需要输入到日值了: 如:echo "2012-6-14" | tee -a my.log -a表 ...
- VS Code 中文注释显示乱码 解决方法
将设置中的"files.autoGuessEncoding"项的值改为true即可. 1.文件 2.首选项 3.设置 4.搜索 "files.autoGuessEncod ...
- [转] Spring4.3.x 浅析xml配置的解析过程(6)——解析context命名空间之property-placeholder和property-override标签
在上一篇解析自定义命名空间的标签中,我们已经知道解析自定义命名空间的标签需要用到NamespaceHandler接口的实现类,并且知道spring是如何获取命名空间对应的命名空间处理器对象的.因此我们 ...
- linux杀掉tomcat应用进程。停止tomcat应用
ps -ef |grep tomcat |grep -v grep |awk '{print $2}' |xrags kill -9