iOS设计模式之基本规范
序言
本来是打算写一个系列的文章的,结果名字没起好,就变成这样了。设计模式和写文章一样并没有什么特别的地方,只是思维方式不一样而已。这里给大家介绍下设计模式的基本规范
前文提要:
iOS设计模式、架构模式、框架简介之《设计模式简介》
相关更新:
iOS设计模式之单例模式
设计模式的基本规范
规范这个东西其实只是为了让使用者能更方便的理解创建者定义的这个东西是什么意思而已。就和我们通常见的街边路牌一样,通俗易懂。那么我们码农的基本规范是什么样呢?我们参考下苹果在实现各种方法时的规范就好了。
一.命名规范
在为我们自己设计的方法提供API和命名的时候,使用者并不知道我们的内部实现,所以我们就必须给我们的API提供一个简单易懂的名字和必要的注释。让使用者能了解基本的用途。
我们通常在设计类工厂方法的时候会使用类名。我们再来参考下苹果的TableViewDelegate
// this represents the display and behaviour of the cells.
@protocol UITableViewDelegate<NSObject, UIScrollViewDelegate>
@optional
// Display customization
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
// If these methods are implemented, the above -tableView:heightForXXX calls will be deferred until views are ready to be displayed, so more expensive logic can be placed there.
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(7_0);
所以在命名的时候尽量使用简洁的单词或业内默认的模式让使用者明白你是干什么的,有什么功能,解决什么问题。同时增加必要的注释。命名的格式参考苹果在相关模式下的命名方式即可。这也是我们通常写API的规范。
二.设计的基本原则
设计原则和规矩一样,是用来规范也是用来打破的。并非所有的时候我们都需要完全准守设计原则,准守设计原则可以减少遇到不必要的麻烦,但是有时候如果完全准守原则,你可能寸步难行。灵活变通,才是王道。
1.单一职责原则:
也就是我们常说的一个类负责一个职责,虽然这个对于程序猿们是一个常识,但是事件经常会发展到我们无法控制的地步。
比如刚开始的时候类T只负责一个职责P。后来由于某种原因,也许是需求变更了,需要将职责P细分为粒度更细的职责P1,P2,这时如果要使程序遵循单一职责原则,需要将类T也分解为两个类T1和T2,分别负责P1、P2两个职责。但是在程序已经写好的情况下,这样做简直太费时间了。所以,简单的修改类T,用它来负责两个职责是一个比较不错的选择,虽然这样做有悖于单一职责原则。(这样做的风险在于职责扩散的不确定性,因为我们不会想到这个职责P,在未来可能会扩散为P1,P2,P3,P4……Pn。所以记住,在职责扩散到我们无法控制的程度之前,立刻对代码进行重构。)
2.里氏替换原则:
这项原则最早是在1988年,由麻省理工学院的Barbara Liskov女士提出来的。
定义1:如果对每一个类型为 T1的对象 o1,都有类型为 T2 的对象o2,使得以 T1定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 T2 是类型 T1 的子类型。
定义2:所有引用基类的地方必须能透明地使用其子类的对象。
看完定义大致也知道这个是个和继承相关的定义。其实就是我们通常使用继承时子类尽量不要去修改父类的功能。这也是为什么我们在继承父类方法进行扩展的时候通常都会代用super的原因。
3.依赖倒置原则:
定义:高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。(抽象指的是接口或者抽象类,细节就是具体的实现。)
在面向过程的开发,上层调用下层,上层依赖于下层,当下层剧烈变动时上层也要跟着变动,这就会导致模块的复用性降低而且大大提高了开发的成本。
而我们iOS是面向对象的开发,很好的解决了这个问题,一般情况下抽象的变化概率很小,让用户程序依赖于抽象,实现的细节也依赖于抽象。即使实现细节不断变动,只要抽象不变,客户程序就不需要变化。这大大降低了客户程序与实现细节的耦合度。
简而言之就是某些可能改变的参数不要在底层的模块进行实现,而是通过传递参数,block块等方式进行传递。
4.接口隔离原则:
定义:客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。
还是以苹果的UITableViewDelegate为例,在设计时定义了部分必须实现的基本方法(最小接口)。那么其他的接口只需要在必要时才实现。而不是需要实现所有接口才能使用某个功能。
5.迪米特法则:
定义:一个对象应该对其他对象保持最少的了解。
问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
解决方案:尽量降低类与类之间的耦合。
软件编程的总的原则:低耦合,高内聚。无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。低耦合的优点不言而喻,但是怎么样编程才能做到低耦合呢?那正是迪米特法则要去完成的。
迪米特法则又叫最少知道原则,最早是在1987年由美国Northeastern University的Ian Holland提出。通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的public方法,不对外泄漏任何信息。迪米特法则还有一个更简单的定义:只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
6.开闭原则:
开闭原则中“开”,是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的;开闭原则中“闭”,是指对于原有代码的修改是封闭的,即修改原有的代码对外部的使用是透明的。
-----------我是分割线-----------
之前有简友说我说的只是一些概念,没错。这些只是一些基本的概念,如果想要深入学习,当然还是必须通过买书和实践进行系统的学习。这里只是为了给刚接触编程的朋友提供一些基本的概念,以便找到学习的方向而已。