软件设计原则(一): 依赖倒置原则

如何不依赖代码却可以复用它的功能

在软件设计中为了建立清晰的软件分层关系,引入了软件分层设计,也是便于高层业务模块依赖低层模块。在一般的应用软件中,策略层会依赖方法层,业务逻辑层会依赖数据存储层。

dip_1.png

图1

这是我们正常的软件设计。

但是这样的设计会带来一些问题。

策略层对方程层和工具层是传递依赖的,如果下面两层的改动,都会对策略层产生影响,这样导致的级联改动非常不利用软件的维护。

出现了上述问题,可能会想到定义策略层和工具层的接口,毕竟接口比实现更问题。

所以,会变成下面的设计关系。

dip_2.png

图2

Policy layer 层依赖的是方法层的 MechanismService 接口,而方法层会依赖工具层的 UtilityService 接口。这是通常的编程习惯,底层模块有自己的接口,高层模块依赖低层模块提供的接口。

但是我们下面不是用这种方式,而是用依赖倒置设计原则去重构。

依赖倒置的设计原则

按照依赖倒置原则,接口的所有权是被倒置的,也就是说,接口被定义在高层模块,高层模块拥有接口,低层模块实现接口。不是高层模块依赖低层模块的接口,而是低层模块依赖高层模块的接口,从而实现依赖关系的倒置。

dip_3.png

图3

在上面的依赖层次中,每一层的接口都被高层模块定义,由低层模块实现,高层模块完全不依赖底层模块。这样低层模块的改动不会影响高层模块,高层模块的复用也不会完全依赖低层模块。

使用依赖倒置实现高层模块复用

依赖倒置原则也适用于一个类向另一个类发送消息的场景

Button 控制灯泡,按钮按下的时候,灯泡点亮或关闭。常规的设计是,Button 类直接依赖 Lamp 灯泡类

dip_4.png

图4

这样会导致问题,Button 依赖 Lamp, Lamp 的任何改动都会牵扯到 Button, 变成联级的改动。另外,如果想要 Button 控制另外一种电器,Button 变难以重用, 以为 Button 依赖着 Lamp.

解决办法是将依赖中的具体实现,改成为依赖抽象。

重构后的设计


dip_5.png

图5

抽象接口 ButtonServer 是属于高层模块 Button 的,不属于低层模块 Lamp。这样就形成了依赖倒置。

Button 不会再依赖 Lamp,而是依赖抽象的 ButtonServer, 而 Lamp 是
ButtonServer 的具体实现,这样 Lamp 的改动基本上就不会牵扯 Button。另外,如果想要重用 Button 控制其他设备, 只需要这些设备实现 ButtonServer 接口即可。

抽象工厂模式

在创建对象是,一般都会是具体实现,这样就会形成一个依赖。这时,可以选择用抽象工厂模式来解决代码依赖的问题。

dip_6.png

图6

Application 通过调用 ServiceFactory接口的 makeService 方法。这个方法由 ServiceFactoryImpl 类具体提供,该方法初始化一个 ConcreteImpl 类的实例,并且将其返回 Service 类型返回。

图6中间的虚线代表着软件架构中的抽象层与具体实现层的边界。所有跨越这条边界源码级别的依赖关系都应该是单向的,即具体实现层依赖抽象层。

抽象接口层包含了应用的所有高阶业务规则,具体实现层则包括了这些业务规则需要做的具体操作及其相关的细节信息。

图6中控制流跨越边界(虚线)的方向与源代码依赖关系跨越该边界的反向相反,源代码依赖用于是控制流方向反向,这就是依赖倒置。

依赖导致原则

  • 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口
  • 抽象接口不应该依赖于具体实现,而具体实现则应该依赖于抽象接口

高层:业务逻辑
底层:UI,底层配置(数据库等)

高层模块不依赖低层模块,而是依赖抽象接口,这个接口是由高层模块定义,低层模块实现

应用规则:

    1. 应用代码多使用抽象接口,尽量避免使用多变的具体实现类
    1. 不要继承具体类,除非是抽象类
    1. 不要重写 override, 包含具体实现的函数

参考

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

推荐阅读更多精彩内容