1. 开放封闭原则(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不能完全代替子类,有以下几个最大的缺点:

    1. 当在Category中覆盖一个继承的方法,在Category中的方法可以通过向super类发送一个消息来调用被继承的方法。但是,如果Category中覆盖的那个方法已经在这个类的其它Category定义过了,则之前定义的方法将没有机会被程序调用
    2. 在Category中无法确定其能够可靠的覆盖某个方法,而这个方法已经在其它的Category中定义过。这个问题在使用Cocoa框架时尤其 突出。当你想覆盖某个框架已经定义好的方法时,该方法已经在其它Category中实现,这样就无法确定哪个定义和实现会被最先使用,带来很大的不确定性。

此博客参考博客链接:http://bbs.itheima.com/thread-117162-1-1.html

设计模式之开放-封闭原则(引申出Objective-C中继承、Category、Protocol三者的区别,这点面试常问)的更多相关文章

  1. 北风设计模式课程---开放封闭原则(Open Closed Principle)

    北风设计模式课程---开放封闭原则(Open Closed Principle) 一.总结 一句话总结: 抽象是开放封闭原则的关键. 1."所有的成员变量都应该设置为私有(Private)& ...

  2. (转) 面向对象设计原则(二):开放-封闭原则(OCP)

    原文:https://blog.csdn.net/tjiyu/article/details/57079927 面向对象设计原则(二):开放-封闭原则(OCP) 开放-封闭原则(Open-closed ...

  3. C++ 设计模式 开放封闭原则 简单示例

    C++ 设计模式 开放封闭原则 简单示例 开放封闭原则(Open Closed Principle)描述 符合开放封闭原则的模块都有两个主要特性: 1. 它们 "面向扩展开放(Open Fo ...

  4. [Python设计模式] 第3~5章 单一职责原则/开放-封闭原则/依赖倒转原则

    github地址:https://github.com/cheesezh/python_design_patterns 单一职责原则 就一个类而言,应该仅有一个引起它变化的原因. 如果一个类承担的职责 ...

  5. 《大话设计模式》num03-04-05---单一职责原则、开放封闭原则、依赖倒转原则

    2018年03月03日 21:19:19 独行侠的守望 阅读数个人分类: 设计模式 版权声明:本文为博主原创文章,转载请注明文章链接. https://blog.csdn.net/xiaoanzi12 ...

  6. 设计模式六大原则——开放封闭原则(OCP)

    什么是开闭原则? 定义:是说软件实体(类.模块.函数等等)应该可以扩展,但是不可修改. 开闭原则主要体现在两个方面: 1.对扩展开放,意味着有新的需求或变化时,可以对现有代码进行扩展,以适应新的情况. ...

  7. 开放封闭原则(OCP)

    开放封闭原则 转:http://baike.baidu.com/view/2493421.htm转:http://dev.csdn.net/article/38/38826.shtm 开放封闭原则(O ...

  8. Observer观察者模式与OCP开放-封闭原则

    目录 场景引入 在联网坦克项目中使用观察者模式 总结 在学习Observer观察者模式时发现它符合敏捷开发中的OCP开放-封闭原则, 本文通过一个场景从差的设计开始, 逐步向Observer模式迈进, ...

  9. 面向对象设计原则 开放封闭原则(Open Closed Principle)

    开放封闭原则(OCP,Open Closed Principle) 开放封闭原则是所有面向对象原则的核心. 软件设计本身所追求的目标就是封装变化.降低耦合,而开放封闭原则正是对这一目标的最直接体现. ...

随机推荐

  1. [转] mysql --prompt介绍

    mysql --prompt修改命令行链接mysql时的提示符,shell脚本示例如下 #!/bin/bash case $1 in crm) cmd='mysql -h192.168.1.2 -ur ...

  2. Redis 学习之路 (010) - redis命令手册

    Redis 键(key) 命令 命令 描述 Redis DEL 命令 该命令用于在 key 存在是删除 key. Redis Dump 命令 序列化给定 key ,并返回被序列化的值. Redis E ...

  3. SpringBoot中Redis的set、map、list、value、实体类等基本操作介绍

    今天给大家介绍一下SpringBoot中Redis的set.map.list.value等基本操作的具体使用方法 上一节中给大家介绍了如何在SpringBoot中搭建Redis缓存数据库,这一节就针对 ...

  4. Entity Framework中实体模型命名空间的问题

    在添加一个实体数据模型的时候(就是扩展名为edmx那位)属性里明明设置了自己的命名空间,但是后台的Designer.cs命名空间生成规则却是项目的默认命名空间加edmx文件所在文件夹的名称, 是BUG ...

  5. java 发送post请求参数中含有+会转化为空格的问题

    如题 原因分析:参数在传递过程中经历的几次编码和解码标准不同,导致加号.空格等字符的错误. 解决方案:将post请求的参数中 ,含有+号的,统统采用%2B 去替换,这是URL的协议问题.

  6. 【AaronYang风格】第一篇 CodeFirst 初恋

             原著:Prorgamming Entity Framework Entitywork Code First 大家好! 我是AaronYang,这本书我也挺喜欢的,看了一半了,今晚也没 ...

  7. SharePoint 2013 启用 以其他用户身份登陆(Sign in as different user)

    习惯于SharePoint 2010的用户会发现,SharePoint 2013默认把  以其他用户身份登陆(Sign in as different user)的选项去掉了,这对于开发人员来说很麻烦 ...

  8. Jmeter 线程组、运行次数参数化

    Jmeter的jmx文件保存了线程数和运行次数等参数,这个参数可以在命令行中传入参数的方式来修改数值 步骤如下 1.生成线程和运行次数的参数 Jmeter选项中函数助手对话框,选中__P参数,这个参数 ...

  9. Google Mesa概览

    Google Mesa的文章:https://research.google.com/pubs/pub42851.html  https://gigaom.com/2014/08/07/google- ...

  10. metaspolit 命令大全

    一.msfconsole相关命令 二.database 三.autopwn自动化攻击工具 四.metaspolit常见渗透命令大全