1 封装
没有经过封装的原始代码规定为0级封装,而面向过程的子程序可以称为一级封装。而类则封装了众多的子程序,集合在一起形成一个高级别的封装,因此类是二级封装。组合类的包,则可以称为三级封装,而构件则可以看作更四级封装。
2 共生性
在两个元素A和B之间,共生性意味着:
1 如果在A中进行了一些变化,那么为了保持全面的正确性,同样需要对B进行改变,或者至少要仔细进行校验。
2 或者为了保持正确性,需要在A和B中同时进行一些变化
2.1 共生的性质
为了实现共生性,两个元素A和B之间不能相互通信
一些共生性的形式具有方向性,例如名称共生性,存在着单向的共生,也存在着双向的共生
一些形式的共生性是没有方向的,如果A和B之间没有显式的引用。如A和B使用的运算过程。
2.2 共生性的种类
类型共生
A: int i;
B: i=7
如果A处i声明为char,则B处自然需要变化
名称共生
上例中,如果A处声明变为j,则B处也需要进行变化。在派生类中如果使用了基类的某个名称,如果基类发生变化,则派生类也需要变化。
显式共生
像上面这两个例子,共生是显而易见的,通过阅读程序就可以快速找到。
隐式共生
然而,有时共生性的显现却并不是那么明显,需要花费大量的时间和精力去检测它,除非在显著的位置具有详细的文档说明。下面举一个隐式共生的例子,在古老的汇编语言中,我们经常可以看到的一种位置共生性。由于代码位置而存在的共生性。
A: jump Y+38
B: clear R1
…//38字节代码
clear R2
位置共生性
比如A和B的必须以一定顺序、必须相邻,比如形参与实参的对应。
常量共生
当在系统中使用一个常量来定义一个属性时,这个变量和常量便发生了共生
算法共生性
比如hash表中的插入和查找使用了相同的hash算法
上面的大部分共生性都是静态共生性,这些共生性是体现在静态的代码中。而动态共生性,则依赖于运行代码的执行模式或对象的交互模式。下面列出一些动态共生的类型。
执行共生性
执行共生性是位置共生性的动态表现形式。它有几种类型,包括顺序和相邻。
时间约束共生性
实现系统中经常出现,为了完成某个操作,而此操作必须在规定时限内完成。
数值共生性
存在一些约束,在数值之间存在着协变性。比如三角形的三条边的数值。
标识共生性
id共生性,两个指针指向同一个内存,当一个指针修改了内存的内容后,另一个指针指向的内容也发生了变化。
差异共生性
为了保证正确性,A和B必须保持不同,这称之为差异共生性。这种共生非常常,比如同一局部的多个变量不能重名。导入不同命名空间存在的命名冲突等都是共生性的体现。在多重继承下,多个基类中的同名操作也是同样的情况。
2.3 共生性和封装边界
封装是对共生性,特别是差异共生性的一种检验。如果系统没有任务封装,在大量代码中,如果改动一个地方,则你需要检查所有的代码以查看是否有共生性需要解决。一个没有封装单元的系统会存在两个问题:共生性泛滥和混淆真正的共生性。
面向对象方法至少可以驯服在传统模型系统中仅仅处于1级封装的不太好使用的共生性,即基于类的2级封装可以更容易限制共生的存在范围。
为了提高系统的可维护性,共生性提供了三个指导原则:
通过将系统拆分为封装的元素使得整个共生性达到最小化。
将任何超越封装边界的共生性最小化。
在封装边界范围内将共生性最大化
因此任何穿越了封装的边界而发生的共生说明这上封装将不合理,或者违反了面向对象的设计原则。