用例图、类图、顺序图、状态图、活动图
1.UML类图的结构
类名
类属性:访问权限-属性名-数据类型
类方法:访问权限-方法名-(参数名:参数类型):返回值类型
2.类之间的关系
继承关系:is-a,kind of子类到父类的空心三角
如果两个类有继承关系,一个类自动拥有另一个类的所有数据和操作;
子类可以在继承的基础上进行拓展,添加自己新的操作;子类也可以覆写父类中的操作,使得其操作的行为有别于父类;
关联关系:has-a, for, of
[1]单向——包含到被包含的单箭头实线
关联方向、数量关系、关联属性(对象引用变量,哪个类的私有属性?数据类型是什么?);
如果两个类有关联关系,则可通过关联属性+点运算符,通过调用某个对象的方法(即给对象发消息的过程)实现;
[2]双向——一条无箭头实线
数量关系、容器类型属性(s);
n、*、0...*、0...1、1...*;
区别类与类数量关系中的“1对1”和“1对多”:“1对1”中的关联属性是单数,数据类型就是紧挨着的类的类类型;
“1对多”中关联属性是复数,数据类型是容器/数组类型,而容器中的每个对象类型是紧挨着的类的类类型;
3.常用类结构
[1]集合:“1对多”、“多对多”
设计包含关联属性的类时常常提供,建立在容器属性之上的、常用操作容器数据类型的4个方法:add();remove();getName(index/String);getNumberOf()常用于遍历终止的条件;
[2]自包含:如Person类与getFather();getMother();
对于单数的属性,设计类时一般要提供访问这些属性的get();和/或 set();方法
[3]关系环:
如果发现类A和类B存在相同的代码,可以设计一个类C,用于存放通用的代码,使得类A和类B继承类C,通过继承类A和类B可以复用类C的代码;
类A如果需要与类C的所有子类关联,则类A仅需与基类C关联即可,将类中的属性变量/方法参数类型设为基类,属性变量/方法形参可以接受从这个基类导出的任何子类对象;(即多态,所有的子类型都可以当作基类型来使用)
4.类图设计
[1]识别及筛选类:都很多遍标记所有的名词和名词短语→列在一个excel表中;
复数名词转单数名词(除非本身就表达集合概念)→删减具体的对象名转抽象类名→删减具体的取值转属性名→删减“含混不清”的名词(没有具体描述这个名词具体的属性更谈不上什么方法)→删减仅作为另外一个实体属性的名词并标记便于第[3]步使用→删减用于描述整个大系统的名词→再读需求,归类同义词;
[2]判断类之间的关系:主要是关联关系和继承关系;当同一句话中出现了两个筛选出的类名时,就思考两类间的关系;
在excel表中建立一个N阶矩阵→判断行索引与列索引之间Specialization/Generalization的关系(明确的关键词,或判断子类是否包含了父类所有的属性);
→无关联关系标记“X”→“一对多”关联关系标记“关联属性(单数/复数)”;
[3]定义类的属性:of,for;
将第[1]步筛检时标记的捡回来→将第[2]步判断出的关联关系中的关联属性捡出来→自行添加属性
注:不用担心继承类之间的继承属性,需要思考判断是否存在重复,因为本身就是通过没有重复的需求描述,才判断出二者之间为继承关系;
[4]定义类的方法:类有责任和义务在属性之上提供方法操作的,否则无法实现任何功能;
需求中明确出现的动词/动词词组→类都应提供对于类本身属性单数属性的get();和/或set();(set的有无需要判断属性值能否修改)方法→考虑输出字符串的方法→考虑需要计算的方法;
如果类之间为“1对1”关系,那么类之间就是“Collection”的类结构→只需为关联属性的单数属性一样提供get();和/或set();(set的有无需要判断属性值能否修改)方法;
注:注意区分关联的类本身就是一个集合类,即“1对1”的关联属性本身就是一个集合类与“1对多”关系中创建集合类之间,添加方法上的区别;
如果类之间为“1对多”关系,那么类之间也是“Collection”的类结构→包含项有责任和义务为关联属性的复数属性提供add();remove();get(Index:int/Name:String);(一般两种get();都提供)getNumerOf();的操作;
注:如果某属性类型为布尔型,则为它添加get();方法时,可以改起名为is开头,如isAvailable();
[5]实现及测试:实现UML绘图:eclipseUML、Violet.jar、Microsoft Visio、IBM RSA(Rational Rose);
根据需求中的具体应用场景,发掘要求给用户提供的功能→在上述完成的核心类(Core Class)的基础上再添加测试/驱动类,封装用户需要的功能,这些核心类构成的结构是可以在不同的场景中复用的→即第[1]步中最后删除的用于描述整个大系统的名词→只需要和关联关系的起始端变量关联即可,与其他类之间就可实现间接的关联关系了;
注:类名开头常用大写,属性名、方法名开头常用小写;
将点运算符考虑成现实世界中的“发消息”;