面向对象分析与设计——类与对象

3           类与对象

OOAD的基本构建块就是类和对象。

 

3.1   对象的本质

3.1.1   什么是对象,什么不是对象

     一个对象是一个具有状态、行为和标识符的实体。
      结构和行为类似的对象定义在他们共同的类中。
      “实例”和“对象”这两个术语可以互换使用。

3.1.2   状态 

      对象的状态包括这个对象的所有属性(通常是静态的)以及每个属性当前的值(通常是动态的)。(自动售货机的例子)
      相对于数字,对象是有存在时间的、可以变化的、有状态的、可以实例化的,可以被创建、销毁和共享。

3.1.3   行为 

      行为是对象在状态改变和消息传递方面的动作和反应的方式。
      对象的行为代表了它外部可见的活动。

      一个对象的所有方法è它的协议è对象允许行为的封装
      一个对象的状态和行为共同决定了这个对象可以扮演的角色。
      角色动态且互斥。 

      对象像自动机è主动对象VS被动对象

3.1.4   标识符

     一个对象的属性,来区分这个对象与其他所有对象。


3.2   对象之间的关系 

3.2.1   链接 

     端到端的关系或客户/服务提供者的关系

     控制器:操作别人,箭头向外
      服务器:被操作,箭头向内
      代理:双向(或无箭头)    

      引发问题:可见性,同步(顺序、守卫(客户互斥使用)、并发(服务保证互斥))

3.2.2   聚合    

     部分/整体的关系


3.3   类的本质 

3.3.1   什么是类,什么不是类 

      类是一组对象,它们拥有共同的结构、行为和语义。

      一个对象就是类的一个实例。 

3.3.2   接口和实现 

      类的接口提供了它的外部视图。类的实现是它的内部视图。
      根据可见性,再将接口区分为:公,保,私,包
      接口(即声明)主要为所有的操作声明(适用于该类的所有对象),也可能包含其他类、常量、变量和异常的声明。

3.3.3   类的生命周期

      某些类在每个实例生命周期的不同阶段涉及不同操作è时间次序、事件次序 


3.4   类之间的关系 

3.4.1   关联 

      语义上的依赖关系
      多重性:一对一、一对多、多对多 

3.4.2   继承 

      一般/特殊的关系
      继承的替代方法是委托      

      单继承:     扩展继承、限制继承;子类从父类中继承结构和行为
      多态:重载运算符/函数为初级形态;延迟绑定
      多继承:     名字冲突è加限定符;重复继承è虚继承;混入类(仅用于多继承的抽象类)

3.4.3   聚合

      整体/部分关系。      

      【聚合 VS组合】

      聚合弱,空心箭头,生存期不同,按引用包容
      组合强,实心箭头,生存期相同,按值包容

     【聚合 VS关联】

      关联关系所涉及的两个类是处于同一层次上的
      而在聚合关系中,两个类处在不平等的层次上的,一个代表整体,一个代表部分。

      (关联与聚合仅仅从语法上是区分不开的,需要察所涉及的类之间的逻辑关系。)

3.4.4   依赖关系

      依赖是类与类之间的连接,一般是以下几种情况之一:

      aClassA中某个方法的参数类型是ClassB;这种情况成为耦合;
      bClassA中某个方法的参数类型是ClassB的一个属性;这种情况成为紧耦合;
      cClassA中某个方法的实现实例化ClassB
      dClassA中某个方法的返回值的类型是ClassB

      如果出现了上述四种情况之一,两个类很有可能就是“依赖”关系。

      关联是一种结构关系,说明一个事物的对象与另一个事物的对象相联系;
      关联在代码中一般表示为属性(成员变量)     

      【关联和依赖的区别】

      从类之间关系的强弱程度来分,关联强,依赖较弱;
      从类之间关系的时间角度来分,关联表示类之间的“持久”关系,需要保存;
      依赖表示类之间的是一种“临时、短暂”关系,不需要保存;

 

3.5   类与对象的互动

3.5.1   类与对象的关系 

3.5.2   类与对象在分析和设计中的角色

      在分析阶段和设计早期:

      任务1:从问题与的词汇表中确定出类
      任务2:创建一些结构,让多组对象一起工作,提供满足需求的行为    

      将这样的类和对象统称为问题的“关键抽象”,把这些协作结构称为实现的“机制”
      设计前期,关注外部视图;设计后期和实现阶段,关注内部视图和物理实现 

3.6   创建高品质的类与对象 

3.6.1   评判一种抽象的品质 

     耦合(高扇入、低扇出)
      内聚
      充分性(够用,最小接口)
      完整性(所有方面,通用)
      基础性(访问底层才能实现的)

3.6.2   选择操作

1)功能语义

将一个行为提取为一个方法:简单接口,大方法     è无法管理的大模块
将一个行为分散到多个方法:复杂接口,简单方法   è片段化

判定是否将一个操作/方法加入到一个类的条件:

  • 可复用性:   在多种上下文中使用
  • 复杂性:     实现难度
  • 适用性:     与类之间的相关度
  • 实现知识:   是否依赖类的内部细节 

2)时间和空间语义

     时间消耗和存储空间
      同步方式的考虑 

3.6.3   选择关系 

1) 迪米特法则

     类的方法不应该以任何方式依赖于任何类的结构,除了它自己累的当前(顶层)结构之外。而且,每个方法只能够对一个非常有限的类集的对象发出消息。

法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle简写LKP

talk only to your immediate friends
法则的核心观念就是类间解耦,弱耦合,只有弱耦合了以后,类的复用性才可以提高。

还有如下一些关于应用法则的注意事项:
① 在类的划分上,应该创建有弱耦合的类;
② 在类的结构设计上,每一个类都应当尽量降低成员的访问权限;
③ 在类的设计上,只要有可能,一个类应当设计成不变类;
④ 在对其他类的引用上,一个对象对其它对象的引用应当降到最低;
⑤ 尽量降低类的访问权限;
⑥ 谨慎使用序列化功能;
⑦ 不要暴露类成员,而应该提供相应的访问器(属性)

法则不希望类直接建立直接的接触。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。

2) 机制和可见性

     如何协作?谁和谁需要可见?

3.6.4   选择实现

     外部视图稳定下来后,才转向内部视图。
      为类和对象选择表示形式,以及将类和对象放入一个模块。
      表示形式的例:圆锥类的体积方法,是存储体积变量,还是每次调用时计算
      打包:在模块中声明类和对象。可见性和信息隐藏

 

你可能感兴趣的:(读书随笔)