抽象是一种以简化的形式来看待复杂操作的能力,类的接口为隐藏在其后的具体实现提供了一种抽象,类的接口应能提供一组明显相关的子程序。
如果类的接口不能展现出一直的抽象,那么它的内聚性就很弱,应该考虑把一些子程序重新组织到只能更专一的类里去,在这些类的接口中提供更好的抽象。
对创建类的抽象接口的指导建议:
(1)类的接口应该展现一致的抽象层次:在考虑类的时候有一种很好的方法,就是把类安坐一种用来实现ADT的机制。每个类应该实现一个ADT,并且仅实现这个ADT,如果你发现某个类实现了不止一个ADT,或者你不能确定究竟它实现了何种ADT,就应该把这个类重新组织为了一个或多个更加明确的ADT。
(2)一定要理解类所实现的抽象是什么。
(3)提供成对的服务:大多数操作都有和其对应的、相等的以及相反的操作,如果有一个操作用来把灯打开,那么很可能也需要另一个操作来把灯关闭。在设计一个类的时候,要检查每一个公用子程序,决定是否需要另一个与其互补的操作。不要盲目的创建相反操作,一定要考虑,看看是否需要它。
(4)尽可能让接口可编程,而不是表达语义:每个接口都有一个可编程的部分和一个语义部分组成,可编程的部分由接口中的数据类型和其他属性构成,编译器能强制性的在编译时检查错误,而语义部分则是由“本接口将会被怎样使用”的假定组成,而这些是如法通过编译器来强制实施的。
(5)谨防在修改时破坏接口的抽象性。
(6)不要添加与接口抽象不一致的公用成员:每次向类添加子程序时,问问“这个子程序与现有接口所提供的抽象一直吗?”如果发现不一致,就要换另一种方法来进行修改,以便能够保持抽象的完整性。
(7)同时考虑抽象性和内聚性:一个呈现出很好的抽象的类接口通常也有很高的内聚性【如果一个类表现出很好的抽象性,那么接口一定是朝着一致的方向努力的,从而会具有很好的内聚性】。而具有很强的内聚性的类往往也会呈现为很好的抽象,但是关系不如前者强烈。一般关注类的抽象性比关注类的内聚性更有助于理解类的设计。
封装是一个比抽象更强的概念,抽象通过提供可以让你忽略实现细节的模型来管理复杂度,而封装则强制阻止你看到细节。抽象和封装是紧密相关的,没有封装,则抽象就容易被打破。一般而言,要么封装与抽象两者皆有,要么就是两者皆失。
(1)尽可能的限制类和成员的可访问性:让可访问性尽可能低是促成封装的原则之一。
(2)不要公开暴露成员数据:暴露成员数据会破坏封装性,从而限制你对这个抽象的控制能力。【如果暴露了成员数据,就不知道何时数据被修改了】
(3)避免把私用的实现细节放入类的接口中。
(4)不要对类的使用者做出任何假设:类的设计和实现应该符合在类的接口中所隐含的契约。不应该对接口会被如果使用或不会被如何使用做出任何假设。
(5)避免使用友元类:一般情况下,友元类会破坏封装,因为它让你在同一时刻需要考虑更多的代码量,从而增加复杂度。
(6)不要因为一个子程序里仅使用了公用子程序,就把它归入公开接口:一个子程序仅仅使用公用的子程序这一事实并不是十分重要的考虑因素。相反,应该问的问题是,把这个子程序暴露给外界后,接口所展示的抽象是否还是一致的。
(7)让阅读代码比编写代码更方便:阅读代码的次数要比编写代码的次数多的多,即使在开发的初期。
(8)要警惕从语义上破坏封装性:每当你发现自己是通过查看那类的内部实现来得知如何使用这个类的时候,你就不是在针对接口编程了,而是在透过接口针对内部实现编程了,如果你透过接口来编程的话,封装性就被破坏了,而一旦封装性开始遭到破坏,抽象能力就快遭殃了。
(9)留意过于紧密的耦合关系。
耦合性与抽象和封装性有着非常紧密的联系,紧密的额耦合性是发生在抽象不严禁或者封装性遭到破坏的时候,如一个类提供了一套不完整的服务,其他的子程序就可能要去直接读写该类的内部数据,这样一来,就把类给拆开了,把他从一个黑合盒子变成了一个玻璃合资,从而事实上消除了类的封装性。
posted on 2007-09-26 09:16
探丫头 阅读(929)
评论(3) 编辑 收藏 引用 所属分类:
《代码大全》读书笔记