软件设计中的几点设计原则(下)
以下大部分内容摘抄自阎宏博士的《JAVA与模式》一书的第二部分,部分加入了本人的一些理解。
设计原则
上篇说道了“开闭原则”和“里氏替换原则”,下面继续:
3.依赖倒转原则(Dependence Inversion Principle)
要依赖于抽象,不要依赖于具体。
或者说:要针对接口编程,而不要针对实现编程。
这条原则主要是判断具体类有变化的需求,所以依赖抽象可以让具体类去变化。
当然这里也有一个度的把握,当某些特殊类是相当稳定的、不会发生辩护的,则客户端也可以依赖于此具体类,而不必故意去发明一个抽象类型。
4.接口隔离原则(Interface Segregation Principle)
多个专门的接口比使用单一的接口要好,从客户端类的角度来讲,一个类对另一个类的依赖性应该建立在最小接口上的。
反过来说:过于臃肿的接口设计是对接口的污染(Interface Contamination).
5.合成/聚合复用原则
要尽量使用合成/聚合,尽量不要使用继承。
首先区分下聚合和合成的关系:
a)聚合关系(Aggregation):关联的一种,是整体和个体之间的关系,无法通过语法分别,是逻辑判断得出的。
b)合成关系(Composition)也是关联的一种,但比聚合关系更强。具体有2点:一是要求整体对象负责部分对象的生命周期;二是要求不分对象不能共享(即合成关系不能被共享)
使用合成/聚合关系有如下优点:(缺点是有较多的对象需要管理)
a)隐藏了成分对象的细节
b)可以在运行时,改变成分对象。
c)这种复用支持包装,这里我(马背)的理解是对成分对象的方法进行调用时候,可以加入一些逻辑。
d)所需依赖较少,指类之间的依赖关系,因为没有继承无关的方法,所以无需依赖这些方法所依赖的二类
f)新对象存取成分对象的唯一方法是通过成分对象的接口。
老实说,这点我(马背)没有理解很好,估计是这样的意思:一是成分对象可以要求成抽象的接口,这样能够依赖于抽象而不是具体实现。
相对的,滥用继承关系有如下缺点:
a)将父类的内容细节暴露给子类
b)如果超类发生改变,子类也被强制改变
c)关系是静态的,运行时候能改变,缺乏灵活性。
这条原则的掌握需要我们明确分析对象之间是“has-A”还是"Is-A"的关系。
6.迪米特法则(Law of Demeter) 或者叫做最少知识原则(Least Knowledge Principle)
一个对象应该对其他对象有尽可能少的了解。可以从狭义和广义两个角度来理解。
狭义的迪米特法则:要求一个对象如果不必与其他对象直接通讯,最好能通过其他对象将调用转发(call forwarding),典型的模式:门面模式(Facade)和调停者模式(Mediator),这二者都通过中间对象降低了调用者和其他对象的耦合度。
广义的迪米特法则:主要体现在对象之间、包之间、模块之间,将本身的数据和实现隐藏起来
1)优先考虑将一个类设置为不变类
2)尽量降低一个类的访问权限
3)谨慎使用Serializable
4)降低成员的访问权限
5)限制局部变量的有效范围