面向对象设计步骤二-------指定属性的类型和可见性,分配职责(GRASP),消息驱动,设计模式进行局部设计

增加遗漏的属性,指定属性的类型和可见性:

在面向对象设计阶段,需要对每个类进行详细设计,不全过程中遗漏的属性,并且确定每个属性的数据类型,指定每个属性的可见性;属性的可见性指外部对象对属性的访问权限,一般包括私有,保护和共有几种类型;

在实际开发中,除了那些比较简单且不常发生变化的属性可以直接暴露给客户以外,其他属性最好设置为私有或者保护并且最好都能用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模式
时间: 2024-10-06 06:53:08

面向对象设计步骤二-------指定属性的类型和可见性,分配职责(GRASP),消息驱动,设计模式进行局部设计的相关文章

JavaScript面向对象(二)——成员属性、静态属性、原型属性与JS原型链

前  言 上一篇博客(https://www.cnblogs.com/qdjianghao/p/10177360.html )中,我们介绍了JS中的面向对象,并详细的解释了this的指向问题.本篇博客,我们继续来学习JS的面向对象.来深入理解一下JavaScript OOP中的成员属性/方法.静态属性/方法.原型属性/方法,并且一起来探讨一下JS中的原型与原型链. 一 成员属性与成员方法 在构造函数中,通过this.属性声明.或者实例化出对象后,通过"对象.属性"追加的.都属于成员属性

神奇的描述符(二):使用描述符实现实例属性的类型检查

因为描述符本身可以接管实例属性的访问,利用这个特点,可以使用描述符来实现一些实例属性的类型检查工作. 先定义一个描述符 Point,用于管理坐标信息. class Point: def __init__(self, name): self.name = name def __get__(self, instance, owner): # 通常情况下,通过类属性访问描述符时,返回描述符自身 if instance is None: return self # 通过实例属性访问描述符时,返回实例 e

采用[ICONIX] 方法实践分析和设计之二 [用例建模](转)

在上一篇文章中我们了解并进行了域建模,换言之我们有了一个好的开始,起码开发人员对自己要开发的软件已有了初步的认识,且也得到了进行交流时可以使用的术语表. 本章将会在前一篇的基本上进一步阐述使用ICONIX方法实践用例建模,同样在文章的最后还会有在这个阶段最容易犯的10个错误,以给大家提醒或在分析过程中进行参照.     本文在ICONIX方法中所处的位置如下图(红圈标记的地方)     在开始进行用例建模之前,我们需要对这一过程有一些粗线条的认识,如果您以前做过或学习过这方面的知识,可以把下面的

浅谈MES的通用设计之二:工艺参数的下载

MES是计划和执行层之间的桥梁,除了将工单下发到车间外,还有一个重要功能是将工艺参数下载到设备,从而起到指导现场作业的作用. 本文试以实例说明常见的两种设计思路,以及一种更为通用的设计方法. 业务场景及设计实例1 某发动机工厂支持混线生产,有两种发动机,排量分别为2L.3L.当发动机到达加油机工位时,PLC需要判断发动机的排量,从而进行对应的加油作业,如2L发动机加20L油,3L发动机加30L油. 实现方法如下: 为此工位专门写一个程序,逻辑步骤为: 1.发动机到达时,PLC读取RFID存储的发

JAVA学习--面向对象的特征二:继承性

* 一.面向对象的特征二:继承性 * 1.为什么要设计继承性?  *  * 2.通过"class A extends B"类实现类的继承.  *   子类:A  父类(或基类 SuperClass):B  *     * 3.子类继承父类以后,父类中声明的属性.方法,子类就可以获取到.  *    明确:当父类中有私有的属性或方法时,子类同样可以获取得到,只是由于封装性的设计,使得子类不可以直接  *        调用罢了.  *   子类除了通过继承,获取父类的结构之外,还可以定义

web服务器分析与设计(二)

面向对象分析与设计第二步:寻找对象,建立问题域模型 1,用例场景描述 接上一篇中的用例,编写用例场景 U1: 上网者:打开网站(www.xxx.com) 浏览器:连接网站 目标系统:接受连接 检查连接合法性(主要是因为服务端是容易受攻击的,所以需要加入安全检查) 合法,接入连接,等待HTTP请求(不合法看备选流程) 浏览器: 发送GET请求 等待回复 目标系统:收到GET请求 处理GET请求 向浏览器发回请求回复 回复完成,断开连接 备选流程:连接不合法,断开连接. U2 上网者:点击提交按钮

二、对象和类型(第四部分)

二.对象和类型(第四部分) 四.匿名类型 var关键字,它用于表示隐式类型化的变量.var与new关键字一起使用时,可以创建匿名类型.匿名类型只是继承自Object且没有名称的类.该类的定义从初始化器中推断,类似于隐式类型化的变量. 五.结构 结构是值类型,而不是引用类型.它们存储在栈中或存储为内联(inline)(如果它们是存储在堆中的另一个对象的一部分),其生存周期的限制与简单的数据类性一样. *.结构不支持继承. *.对于结构,构造函数的工作有一些区别.尤其是在编译器总是提供了一个无参数的

Python 二、Python对象类型及其运算

一.Python对象的相关术语 Python中一切皆对象,python程序中保存的所有数据都是围绕对象这个概念展开的:所有的对象都是由类实例化而来的,只不过这些类有些是python内置的类:例如,整数和浮点数,字符串都是由python内置的类实例化而来的.除此之外用户还可以自定义类型,就是类. python程序中存储的所有数据都是对象 每个对象都有一个身份.一个类型和一个值 例如,school="MaGe Linux"会以"MaGe Linux"创建一个字符串对象,

js面对对象编程(二):属性和闭包

上篇博客中讲解了一些js对象的基本概念和用法,这篇博客讲解一下js属性方面的:公有属性,私有属性,特权方法. 如果学过java,公有属性,私有属性,特权方法(即可以访问和设置私有属性的方法)一定很熟悉,那么让我们来看看在js里如何实现呢? 1.公有属性 首先看公有的第一层意思是可以被大家所访问的,对外开放的属性,是相对于私有属性而言的: function Person(name,age){ this.name=name; this.age=age; this.getName=function()