面向对象设计原则
面向对象设计(OOD:Object Oriented Design)的六大设计原则
前五个设计原则就是通常所说的
SOLID
(上方表格缩写的首字母,从上到下)
开闭原则(Open Close Principle)
定义
📌 Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
即:一个软件实体如类、模块和函数等应该对扩展开放,对修改关闭。
不需要修改软件实体(类、模块、函数等),就应该能实现功能的扩展
优点
可以在不改动原有代码的前提下给程序扩展功能。增加了程序的可扩展性,同时也降低了程序的维护成本。
实现的方法
关键是抽象,通过实现预先设置好的抽象的接口(抽象类)来实现新的功能。
策略模式(Strategy Pattern)
定义
该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。
优点
使用策略模式可以避免使用多重条件语句
策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码
策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的
策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法
策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离
缺点
客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类
策略模式造成很多的策略类
实现
继承实现
定义一个抽象类,强制子类实现该方法
这种实现,对父类对子类不一定是透明的,如果父类提供了默认的实现,子类需要了解实现的细节,再决定是否重写
组合实现
这种实现是透明的,只需要改变对象的引用就可以改变其行为。
最后通过工厂类,根据运行的参数选择出对应的实现
只有在策略选择里有条件选择语句,其他地方不出现。
如上述的
createAction()
方法
适配器模式(Adapter Pattern)
定义
将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。分为两种模式:
类适配器模式:适配器与适配者之间是继承(或实现)关系
对象适配器模式:适配器与适配者之间是关联关系
前者的耦合度比后者高,且要求开发了解现有组件库中的相关组件的内部结构,应用相对较少些。
优点
将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。
类适配器模式优点:
由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强。
对象适配器模式优点:
同一个适配器可以把适配者类和它的子类都适配到目标接口。
缺点
类适配器模式缺点:
对于 Java 等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。
对象适配器模式缺点:
与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂。
实现
角色
Target(目标抽象类):目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对 Adaptee 和 Target 进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承 Target 并关联一个 Adaptee 对象使二者产生联系。
Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
类适配器
首先有一个已存在的将被适配的类:
定义一个目标接口:
如果通过一个适配器类,实现 Target
接口,同时继承了 Adaptee
类,然后在实现的 request()
方法中调用父类的 adapteeRequest()
即可实现
对象适配器
对象适配器与类适配器不同之处在于,类适配器通过继承来完成适配,对象适配器则是通过关联来完成,这里稍微修改一下 Adapter
类即可将转变为对象适配器
观察者模式(Observer Pattern)
依赖倒置原则(Dependency Inversion Principle)
定义
📌High level modules should not depend upon low level modules, Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions
翻译过来:
高层模块不依赖低层模块,两者都应该依赖其抽象
抽象不应该依赖细节
细节应该依赖抽象
按照Java的理解,是面向接口编程
作用
降低类间的耦合性
类间的依赖都是通过接口完成的,某个类的实现变了,也不影响上游代码。
减少并行开发引起的风险
各层级,模块间都是通过接口定义的约束,只要都遵循这些约束,能相应减少了并行开发的冲突。
实现方法
构造函数传递依赖对象
Setter方法传递依赖对象
接口声明依赖
好莱坞原则
don't call us, we'll call you
因为在好莱坞,把简历递交给演艺公司后就只有回家等待。由演艺公司对整个娱乐项的完全控制,演员只能被动式的接受公司的差使,在需要的环节中,完成自己的演出。
为什么有时候依赖倒置原则又被称为好莱坞原则
好莱坞有一个角色,找演员来演
好莱坞相当于高层,演员们相当于低层,他们间的联系是通过某个角色,
这个角色由哪个演员来演都可以,并不依赖于具体某个演员,
整个流程有点像面向接口编程。
📌两个原则强调的点应该是不一样的,查到的资料给我的感觉是:
好莱坞原则:强调的是高层对底层的主动调用
依赖倒置原则:强调的是面向接口编程
有点类似,但又不全是。
里氏替换原则(Liskov Substitution Principle)
单一职责原则(Single Responsibility Principle)
接口隔离原则(Interface Segregation Principle)
版权声明: 本文为 InfoQ 作者【leo】的原创文章。
原文链接:【http://xie.infoq.cn/article/34343860ad5ca4044e6fde1ba】。
本文遵守【CC BY-NC】协议,转载请保留原文出处及本版权声明。
评论