设计模式之开放-封闭原则(引申出Objective-C中继承、Category、Protocol三者的区别,这点面试常问)
- 开放封闭原则(OCP原则The Open-Closed Principle)是面向对象的核心设计所在。它是说,软件开发实体(类、模块、函数等)应该可以扩展,但是不能修改。
这个原则有两个特征,一个是说“对于扩展是开放的”,另一个是说“对于更改是封闭的”。
我们在编写任何app时,不要寄希望于需求是固定的、不变化的,这是不现实也是不科学的想法,既然需求一定会有变化,那么如何应对这种变化?也就是说。我们所设计的代码可以相对容易的修改,不至于新的需求一来,就将整个程序推倒重写?怎么样的设计才能面对需求的改变却可以保持相对稳定,从而使得app可以在第一个版本后不断推出新的版本呢?开放-封闭原则可以给我们答案。
答案:代码要容易维护又不容易出问题的最好办法是,就是多扩展,少修改。
就比如说,你作为一个公司的老板,规定九点上班,不允许迟到,但是有几个公司骨干,老是迟到,你怎么办?
仔细想想,其实迟到不是主要问题,每天保证8小时工作量,是老板最需要的。甚至说,这个也不是问题,按时完成业绩目标,才是最重要的指标。于是应该改变管理方式,弹性上班,早到早走,晚到晚走等。这其实就是对工作时间或者业绩成绩修改的封闭,对时间制度扩展的开放。
开放-封闭原则的意思是,在设计的时候,要时刻考虑,尽量让这个类足够好,写好了就不要去修改了,如果新的需求来了,我们增加一些类就完事了,原来的代码能不动就不动。绝对对修改关闭是不可能的,无论模块是多么的封闭,多会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对他设计的模块应该对哪种变化进行封装做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。
在我们最初编写代码时,先假设变化不会发生,当变化发生时,我们就创建抽象来隔离以后发生的同类变化。保证在面对需求时,对新需求的改变是通过增加新代码进行的,而不是更改现有代码。(要做到这一步,强烈推荐《大话设计模式》这本书,我所有关于设计模式的博客,都是从这本书中学习而来,只是这本书籍代码是C#实现的,而我学习的时候,是带入了个人对OC以及iOS开发的理解)
开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对应用程序中每个部分都刻意的进行抽象同样不是好主意,拒绝不成熟的抽象和抽象本身一样重要。
2. Objective-C中继承、Category、Protocol三者的区别
众所周知,OC是单继承,新出的Swift也是单继承。那么在iOS开发中,我们怎么实现类似多继承的关系?
这是一道面试\笔试题,基本应聘时,如果面试官是从事iOS开发的,很有可能会问到这道题。事实上,我们可以利用OC中的Category和Protocol来达到多继承的效果。如果仅仅只是想要回答这个题目,这样说足够了。
可是,有很多面试官是不会满足于这样一个回答的,会追问你,那么Category和Protocol有什么区别呢?即使没有这样的面试题,我想基于自身驱动,这也是必然要了解,学习的。
利用继承、多态可以很好的保持"对扩展开放,对更改封闭"(即上文提到的开放-封闭原则OCP),这也是面向对象语言保持开放-封闭原则最常见的办法。OC中还有另外两种语法来支持OCP:即Category和Protocol。
Protocol只是声明一套接口,并不能提供具体实现,变相的也算是一种抽象基类的实现方式(OC本身语法并不支持抽象基类)。
Category可以为已有的类提供额外的接口和具体的实现。
Protocol只能提供一套公用的接口声明,并不能提供具体实现,它的行为是,我只负责声明,而不管谁去实现,去如何实现。这样的话,我定义一套接口,可以使任意的类都用不同的方式去实现接口中的方法,就是为遵守了protocol的类提供了一些额外访问这个类的一些接口,像delegate和dataSource用protocol实现是最好的。
Category是对一个功能完备的类的一种补充、扩展,就像一个东西基本功能都完成了,可以用category为这个类添加不同的组件,使得这个类能够适应不同情况的需求(但是这些不同需求最核心的需求要一致)。当然,当某个类非常大的时候,使用category可以按照不同的功能将类的实现分在不同的模块中。还有,虽然category可以访问已有类的实例变量,但不能创建新的实例变量,如果要创建新的实例变量,请使用继承。
继承,它基于Protocol和Category之间,既可以像protocol一样只提供纯粹的接口,也可以像Category一样提供接口的完整实现,可以自由定义类的实例变量(这一点,Protocol倒是可以声明实例变量,但是也仅仅是声明而已),而且继承还可以对类以后的方法进行改写,所以继承的力量是最强大的。
在iOS开发中,继承是完全可以完成protocol和category的功能的,那么在开发过程中多多使用继承体系可好?
需要注意的是使用继承还有很大的代价问题。使用继承来进行扩展是一种耦合度很高的行为,对父类可以说是完全依赖,如果继承体系太过复杂,会造成难以维护的问题。如果仅仅只是对类进行扩展,并不建议使用继承,毕竟使用protocol和category是很简单、轻松的。除此之外,在开发过程中,我们应该尽量将界面、功能相似的类的代码提取到基类里面,然后各个子类继承自这个基类,实现各自的其他特殊部分。这样可以大大的优化代码,如果需要修改的话,只需要这倒对应子类修改即可。
category是可以被继承的。在某个父类中定义了category,那么他所有的子类都具有该category;
在需要为某个类创建私有成员方法时,也用category的方式来实现。
Category不能完全代替子类,有以下几个最大的缺点:
- 当在Category中覆盖一个继承的方法,在Category中的方法可以通过向super类发送一个消息来调用被继承的方法。但是,如果Category中覆盖的那个方法已经在这个类的其它Category定义过了,则之前定义的方法将没有机会被程序调用
- 在Category中无法确定其能够可靠的覆盖某个方法,而这个方法已经在其它的Category中定义过。这个问题在使用Cocoa框架时尤其 突出。当你想覆盖某个框架已经定义好的方法时,该方法已经在其它Category中实现,这样就无法确定哪个定义和实现会被最先使用,带来很大的不确定性。
此博客参考博客链接:http://bbs.itheima.com/thread-117162-1-1.html
设计模式之开放-封闭原则(引申出Objective-C中继承、Category、Protocol三者的区别,这点面试常问)的更多相关文章
- 北风设计模式课程---开放封闭原则(Open Closed Principle)
北风设计模式课程---开放封闭原则(Open Closed Principle) 一.总结 一句话总结: 抽象是开放封闭原则的关键. 1."所有的成员变量都应该设置为私有(Private)& ...
- (转) 面向对象设计原则(二):开放-封闭原则(OCP)
原文:https://blog.csdn.net/tjiyu/article/details/57079927 面向对象设计原则(二):开放-封闭原则(OCP) 开放-封闭原则(Open-closed ...
- C++ 设计模式 开放封闭原则 简单示例
C++ 设计模式 开放封闭原则 简单示例 开放封闭原则(Open Closed Principle)描述 符合开放封闭原则的模块都有两个主要特性: 1. 它们 "面向扩展开放(Open Fo ...
- [Python设计模式] 第3~5章 单一职责原则/开放-封闭原则/依赖倒转原则
github地址:https://github.com/cheesezh/python_design_patterns 单一职责原则 就一个类而言,应该仅有一个引起它变化的原因. 如果一个类承担的职责 ...
- 《大话设计模式》num03-04-05---单一职责原则、开放封闭原则、依赖倒转原则
2018年03月03日 21:19:19 独行侠的守望 阅读数个人分类: 设计模式 版权声明:本文为博主原创文章,转载请注明文章链接. https://blog.csdn.net/xiaoanzi12 ...
- 设计模式六大原则——开放封闭原则(OCP)
什么是开闭原则? 定义:是说软件实体(类.模块.函数等等)应该可以扩展,但是不可修改. 开闭原则主要体现在两个方面: 1.对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况. ...
- 开放封闭原则(OCP)
开放封闭原则 转:http://baike.baidu.com/view/2493421.htm转:http://dev.csdn.net/article/38/38826.shtm 开放封闭原则(O ...
- Observer观察者模式与OCP开放-封闭原则
目录 场景引入 在联网坦克项目中使用观察者模式 总结 在学习Observer观察者模式时发现它符合敏捷开发中的OCP开放-封闭原则, 本文通过一个场景从差的设计开始, 逐步向Observer模式迈进, ...
- 面向对象设计原则 开放封闭原则(Open Closed Principle)
开放封闭原则(OCP,Open Closed Principle) 开放封闭原则是所有面向对象原则的核心. 软件设计本身所追求的目标就是封装变化.降低耦合,而开放封闭原则正是对这一目标的最直接体现. ...
随机推荐
- zabbix数据库需要多大硬盘?我告诉你
本次案例:100台服务器,每台服务器有30个监控项,每个监控项60秒刷新一次,需要多大的硬盘呢?众所周知,zabbix基本都是通过web配置,这些配置数据也是存放到数据库里的,但是它对硬盘容量的要求基 ...
- Linux中tomcat启动很慢,SessionIdGeneratorBase.createSecureRandom耗时5分钟
通常情况下,tomcat启动只要2~3秒钟,突然有一天,tomcat启动非常慢,要花5~6分钟,查了很久,终于在这篇文章找到了解决方案,博主牛人啊. 原文参见:http://blog.csdn.NET ...
- WebService出错 Maximum message size quota for incoming messages (65536) has been exceeded.已超过传入消息(65536)的最大消息大小配额
WebService应用中如果收到的信息非常大时出错. 1:Maximum message size quota for incoming messages (65536) has been exce ...
- 【Android】播放音频的几种方式介绍
接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...
- 用copy 还是 strong?
NSArray与NSMutableArray用copy修饰还是strong 这个是原文 http://blog.csdn.net/winzlee/article/details/51752354 一 ...
- cron执行service
在Cron的环境下,是没有定义路径的,所以,service xxx start等等要使用绝对路径 => /sbin/service xxx start service的路径可以用whereis ...
- Android adjustresize全屏无效问题
屏模式下,即使将activity的windowSoftInputMode的属性设置为:adjustResize,在键盘显示时它未将Activity的Screen向上推动,所以你Activity的vie ...
- Android中使用IntentService运行后台任务
IntentService提供了一种在后台线程中运行任务的方式,适合处理运行时间较长的后台任务. 长处: (1)IntentService执行在单独的线程中.不会堵塞UI线程 (2)IntentSer ...
- java udp 广播
原文链接: http://blog.csdn.net/yudajun/article/details/8477149 udp 是一种网络通信协议,不需要客户端和服务器端建立连接即可进行通讯功能.相对于 ...
- ekho安装及测试(中文文字转语音)
1. 官网下载源码包 地址:http://www.eguidedog.net/ekho.php 2. 安装 xz -d ekho-7.5.tar.xz tar -xvf ekho-7.5.tar ap ...