增加遗漏的属性,指定属性的类型和可见性:
在面向对象设计阶段,需要对每个类进行详细设计,不全过程中遗漏的属性,并且确定每个属性的数据类型,指定每个属性的可见性;属性的可见性指外部对象对属性的访问权限,一般包括私有,保护和共有几种类型;
在实际开发中,除了那些比较简单且不常发生变化的属性可以直接暴露给客户以外,其他属性最好设置为私有或者保护并且最好都能用GetXXX()和SetXXX()等访问方法封装一下
分配职责,定义执行每个职责的方法:
职责:是一个类或者类型的契约或者义务
面向对象系统中的类所承担的职责可以分为两大类:做型职责,自己要做某事,自己要为其他对象提供某种服务,发送消息给其他对象一要求提供某种伏虎,控制和协调其他对象的服务;知道型职责,知道自己内部封装了哪些数据,知道哪些对象和自己发生了关系
知道型职责是通过类内部封装的属性以及类间关系来体现的,所以,前面对于类的属性和类间关系的讨论分析就是我们在FishiGUI中的类中分配知道型职责的过程
做型职责是通过类的方法来实现的,为了分配做型职责,需要分析每一个类应该为其他类提供哪些服务,类本身包含哪些行为,应该履行那些义务,然后用类中相应的方法来实现这些职责
通用职责分配软件模式(GRASP):
通用职责分配软件模式描述了在面向对象设计过程中把职责分配给系统中不同对象的有效经验和基本原则;GRASP模式主要包括如下9中主要模式:
- 专家模式:应该将职责分配给信息专家,即在分配一个职责时,应该了解履行该职责需要哪些信息,这些信息为哪个类或者哪些类所用够。如果这些信息为一个类所拥有,就把职责分配给它,如果为多个类所拥有,就为每个类分配一个职责,然后通过消息传递和交互,使这些类协同完成该职责
- 创建者模式:按照创建者模式的要求,如果类A和类B满足下列条件中的某一个A聚合了B对象;A包含了B对象;A的一个属性记录了B对象;A要经常使用B对象;B对象被创建时,A要传递初始化数据给B对象那么我们就可以把创建B对象的职责分配给A对象,因为上述关系的存在,增加创建对象的职责不会增加系统的耦合性例在FishiGUI系统中,由于FG_TimerManager聚合了多个FG_Timer,因此定时器对象的创建和销毁工作应该有FG_TimerManager来负责
- 低耦合:这里的低耦合主要是类和类之间的关联程度,即一个类知道其他类,依赖于其他类的强弱程度,类A和类B之间的耦合包括以下几种情况:类A的一个方法的参数引用类B或者方法内定义了类B的一个局部变量;类A的一个属性引用了类B的实例对象;类A的一个属性聚合了类B的多个实例对象;类A是B间接或者直接的派生类。以上几种耦合关系从上到下耦合程度越来越强,继承是最强的一种偶合。
- 高内聚:内聚指的是一个类的各个职责之间的相关程度或集中程度,一般来说内聚度高的类应该只包含很少的方法树,方法之间的关联程度很高,每个方法承担的工作量不是太大,任务也比较单一;当我们发现一个类担负的任务太多,太杂就应该把一些职责分配给其他的类,这样才能保证设计方案的高内聚
- 控制者模式:控制者模式要求把协调处理系统消息的这则分配给不同的控制类
- 多态:当某一个职责在不同的派生类中表现为不同的行为时,我们就可以使用多态模式,即利用一个同名的多态方法把把该职责分配给不同的派生类,让他们履行不同的行为
- 纯虚构:可以虚构出一个人造的类,把一组盖度内聚的职责分配给他,该人造类是虚构出来的事务,不代表现实世界中的任何实体,就是纯虚构模式
- 中介者模式:把一些职责分配一个虚构的中介类,让该中介类来协调多个类的协作关系,使用中介者类可以隔离耦合度过大的多个类,是容易发生变化的对象不会影响其他的对象
- 不要和陌生人讲话:这个模式要求一个类尽量只是和它的直接对象交互,避免和间接对象交互,这样,它就可以和最少的类产生耦合,使整个系统的耦合度保持最低。该准则要求,在一个对象的方法中,只能给下面的这些对象发送消息:该对象自己;该方法的一个参数;该对象的一个属性该对象的一个属性集合中的一个元素;在该方法中创建的一个对象
对消息驱动的系统,明确消息传递方式:
面向对象设计很容易造成对象之间的关系数目日益膨胀,形成复杂的网状结构。关系的复杂性同样会导致类和对象间的耦合度增大,而消息驱动的设计方案可以很好地皮面上述缺陷,特别是对于FishiGUI这样的图形用户界面框架而言,处理键盘鼠标等操作系统传来的消息本来就是FishiGUI的职责之一,在面向对象技术里,这些外部的软硬件消息和FishiGUI系统的内部通信一道被映射为类和对象间的消息传递(方法调用)。为了使用消息驱动的设计方法,我们在FishiGUI中构造一个同一的消息结构,以此来封装操作系统发送给FishiGUI框架以及FishiGUI框架系统内部产生的各种消息。所有这些消息在操作系统适配层,框架层和应用层之间传递,驱动着整个系统正常运转。(图7-15中,层与层间的虚线箭头代表消息从下层想上层的传递,双实线箭头代表框架层通过函数调用的方式使用适配器子系统提供的服务,单实线箭头代表应用层通过继承和函数调用等方式使用框架层提供的服务)
利用设计模式进行局部设计:
在面向对象设计的过程中,应该尽量使用成熟的设计模式来优化模型的局部设计:
- 使用外观模式为适配器子系统添加一个统一的接口;
- 通过实施观察者模式,是适配器子系统向框架层发送消息时,无需依赖于框架层的具体实现;
- 对于系统中存在的只有唯一的对象实例的类,使用单件模式;
- 窗口元素的组织结构是一个典型的复合模式;
- 使用模板来实现聚合结构(如屏幕中包含多个窗口,窗口中包含多个空间..)并且使用迭代器模式来遍历其中的每个字元素;使用创建型模式协助应用层创建控件,使应用层能灵活地改变控件的外观;
- 使用职责链模式把消息从屏幕对象分发到窗口 控件等窗口元素;
- 把消息从屏幕发送到窗口 控件等窗口元素的过程,相当于把消息从框架层传送到了应用层,因此为了消除框架层到应用层的依赖性,首先使用了职责链模式提供的虚函数接受函数来实现多态性,随后又利用模板方法模式提供的控制倒置特性对上述结构进行了优化;
- 在把适配器子系统移植到dos操作系统的过程中,我们使用了适配器模式以适应消息管理机制完全不同的操作系统;
- 在设计应用层的业务逻辑时,我们使用MVC模式