iOS 面向对象六大设计原则(四)依赖倒置原则

怀疑是最强大的敌人。

iOS 面向对象设计原则全集

前言

接上篇 iOS 面向对象六大设计原则(三)里式替换原则

Demo传送门

如果说开闭原则是面向对象设计的目标的话,那么依赖倒转原则就是面向对象设计的主要实现机制之一,它是系统抽象化的具体实现。依赖倒转原则是Robert C. Martin在1996年为“C++Reporter”所写的专栏Engineering Notebook的第三篇,后来加入到他在2002年出版的经典著作“Agile Software Development, Principles, Patterns, and Practices”一书中。依赖倒转原则定义如下:

依赖倒转原则(Dependency Inversion Principle, DIP):抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。

依赖倒转原则要求我们在程序代码中传递参数时或在关联关系中,尽量引用层次高的抽象层类,即使用接口和抽象类进行变量类型声明、参数类型声明、方法返回类型声明,以及数据类型的转换等,而不要用具体类来做这些事情。为了确保该原则的应用,一个具体类应当只实现接口或抽象类中声明过的方法,而不要给出多余的方法,否则将无法调用到在子类中增加的新方法。

在引入抽象层后,系统将具有很好的灵活性,在程序中尽量使用抽象层进行编程,而将具体类写在配置文件中,这样一来,如果系统行为发生变化,只需要对抽象层进行扩展,并修改配置文件,而无须修改原有系统的源代码,在不修改的情况下来扩展系统的功能,满足开闭原则的要求。

在实现依赖倒转原则时,我们需要针对抽象层编程,而将具体类的对象通过依赖注入(DependencyInjection, DI)的方式注入到其他对象中,依赖注入是指当一个对象要与其他对象发生依赖关系时,通过抽象来注入所依赖的对象。常用的注入方式有三种,分别是:构造注入,设值注入(Setter注入)和接口注入。构造注入是指通过构造函数来传入具体类的对象,设值注入是指通过Setter方法来传入具体类的对象,而接口注入是指通过在接口中声明的业务方法来传入具体类的对象。这些方法在定义时使用的是抽象类型,在运行时再传入具体类型的对象,由子类对象来覆盖父类对象。

什么是依赖注入?

举例

都是概念性的东西不能深入理解,举个大家都喜欢的栗子:老司机开车

司机开车要有司机要有车,司机会驾驶,车会跑。于是整了2个类,司机类和汽车类,这2个类就是【细节】。
开始条件不好买个小奔开开。一切从简,代码如下:

奔驰类

  • Benzee.h
@interface Benzee : NSObject

- (void)run;

@end
  • Benzee.m
- (void)run {
    NSLog(@">>>%@ running", NSStringFromClass([self class]));
}

司机类

  • Driver.h
@interface Driver : NSObject

- (void)drive:(Benzee *)car;

@end
  • Driver.m
@implementation Driver

- (void)drive:(Benzee *)car {
    [car run];
}

@end

使用

Driver *mq = [Driver new];
Benzee *car = [Benzee new];
[mq drive:car];

log

>>>Benzee running

可以看出这是对象级耦合,司机和奔驰类是基础模块,使用者可以看成用户模块也即是高级模块。乍一看好像没有问题,司机只管开车就好。但是如果有一天条件好了,想开宾利怎么办呢?我们大可以创建一个【宾利车类】,问题来了,车是有了,但是司机不会“开”,司机类里面没有宾利车类的依赖。

可以发现,上面这种设计模块与模块之间耦合度太高,生产力很低,没有细节和抽象之分,只要需求一变就要大面积改动。这就是没有使用依赖倒置原则:抽象不应该依赖于细节,细节应当依赖于抽象。换言之,要针对接口编程,而不是针对实现编程。


在OC中,针对接口编程,可以用协议实现。抽象这个就不拓展了,系统中就有很多抽象类,其特点是,不能直接使用,只能使用其子类,是不是一下子就想到了很多?不多说,用协议可以做一下修改:

  • 声明车协议。
@protocol ICar <NSObject>

- (void)run;

@end

  • 注册以及实现协议

车类

@interface DIPBentley : NSObject<ICar>

@end

@implementation DIPBentley

- (void)run {
    NSLog(@">>>DIP %@ running", NSStringFromClass([self class]));
}

@end

司机类

@interface DIPDriver : NSObject

- (void)drive:(id<ICar>)car;

@end

@implementation DIPDriver

- (void)drive:(id<ICar>)car {
    [car run];
}

@end
  • 高层级模块调用
//司机
DIPDriver *ty = [DIPDriver new];
//宾利车
DIPBentley *bentley = [DIPBentley new];
[ty drive:bentley];
//奔驰车
DIPBenzee *benzee = [DIPBenzee new];
[ty drive:benzee];

log

>>>DIP DIPBentley running
>>>DIP DIPBenzee running

总结

就上面工程代码而言,是满足开闭原则的:对扩展开放,对修改关闭。司机类不用修改,骑车类随便扩展,只要注册ICar协议就行。

如果用抽象类来代替协议,汽车类作为抽象类的子类,那么该工程还满足里式替换原则:任何基类的出现的地方,都可以用子类替换,且不引入错误。

分享

开闭原则、里式替换原则、依赖倒置原则同时出现在一个场景中,开闭原则是目标,里氏代换原则是基础,依赖倒转原则是手段。

感谢 -- 面向对象六大原则——依赖倒置原则

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,717评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,501评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,311评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,417评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,500评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,538评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,557评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,310评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,759评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,065评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,233评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,909评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,548评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,172评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,420评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,103评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,098评论 2 352

推荐阅读更多精彩内容