[架构师训练营第 1 期] 第二周命题作业
一、题目
请描述什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?
请用接口隔离原则优化 Cache 类的设计,画出优化后的类图。
提示:
cache 实现类中有四个方法。
其中 put get delete 方法是需要暴露给应用程序的,rebuild 方法是需要暴露给系统进行远程调用的。
如果将 rebuild 暴露给应用程序,应用程序可能会错误调用 rebuild 方法,导致 cache 服务失效。
按照接口隔离原则:不应该强迫客户程序依赖它们不需要的方法。也就是说,应该使 cache 类实现两个接口,一个接口包含 get put delete 暴露给应用程序,一个接口包含 rebuild 暴露给系统远程调用。从而实现接口隔离,使应用程序看不到 rebuild 方法。
二、成果
请描述什么是依赖倒置原则,为什么有时候依赖倒置原则又被称为好莱坞原则?
什么是依赖倒置原则:
高层模块不应该依赖低层模块,而是二者都应该依赖一个属于高层模块的抽象。
这个抽象不应该去依赖实现,而是实现来依赖这个抽象。
所谓的“抽象”,指的就是“规范”,比如“接口”或“配置”等。
注意这个抽象的接口或配置应该是属于高层模块的,而由低层模块去实现它。
为什么需要这个原则:
为了解决高层模块的可复用问题。
因为高层模块依赖低层模块的开发模式要求:
低层应该先被开发出来,高层模块才能使用它,从而完成高层模块的开发。
而这样高层依赖低层的缺点是:会导致高层模块不易被复用,因为它依赖了各种低层模块。
因此在软件设计,特别是框架设计,都要求遵循依赖倒置这一核心原则。
它可以让高层模块按自己的使用场景进行抽象(定义接口等),而不必依赖低层模块。
举个例子:(在课堂中的“按钮控制等软件”之外的另一个例子)
要设计一个温度控制空调的软件,温度高于阈值(limit)打开空调,温度低于阈值关闭空调。
不采用依赖倒置原则的类图为:
这样的设计存在僵化的特性,即 Sensor 直接依赖 AirConditioner,难以复用到其它场合。
当需求发生变化需要扩展时,这样的设计将不得不对修改开放,于是就会违背“开闭原则”。
而遵循依赖倒置原则后,类图为:
通过依赖倒置,Sensor 将得以直接复用于除空调控制外的场景,如大棚遮罩控制、屏幕亮度控制等。
这里面,运用依赖倒置原则的关键在于:洞悉传感器的本质是“采集外部数据,并传递给目标对象”。
而其中,“采集机制”是怎样实现的、“目标对象”又是谁,对架构而言都不重要。
不过,作为“依赖倒置”的题外话,上面的依赖倒置后的设计还需要改进。
因为 AirConditioner 被要求实现 SensorServer 的两个方法后,它变得僵化了,缺乏复用性。
要使 AirConditioner 更具备复用性,可以做如下改进:
说明:通过适配器将 onOverLimit() 适配成 turnOn() 或 turnOff(),onUnderLimit() 同理。
为什么“依赖倒置原则”又叫“好莱坞原则”?
在遵循依赖倒置原则的系统中,框架通过调用已抽象的接口去调用代码,代码实现该接口从而被框架调用。
所以是“框架调用代码,而非代码调用框架”。
这和一句好莱坞名言“Don't call me, I will call you”有异曲同工之妙。
因此依赖倒置原则也被称为“好莱坞原则”。
请用接口隔离原则优化 Cache 类的设计(见题目图),画出优化后的类图。
优化后的类图如下:
说明:将 Cache 类的四个方法分离到两个独立的接口。其中:
get()、put()、delete() 方法放到 Client 接口
rebuild() 方法放到 Maintainer 接口
从而避免了实现 Client 接口的 CacheClient 类被迫依赖 rebuild 方法带来的错误调用隐患。
版权声明: 本文为 InfoQ 作者【猫切切切切切】的原创文章。
原文链接:【http://xie.infoq.cn/article/389e52687de334e1d4c9c06c4】。文章转载请联系作者。
评论