uml精粹——5.类图(高级概念)

来源:互联网 发布:希尔薇 知乎 编辑:程序博客网 时间:2024/06/05 11:38
【关键字keyword】  
  uml接口interface是一个只有公共操作public operations没有方法体method body的类。他用类图标class icon和关键字<<interface>>表示。
  <<interface>>简写为<<I>>,{abstract}简写为{A}。
  uml1中引号guillemets主要用于原型stereotype。
  原型被用作概况profile的一部分。


【分类和一般化classification and generalization】
  语法:
Shep is a Border Collie
A Border Collie is a Dog
Dogs are Animals
A Border Collie is a Breed
Dog is a species  
 
classification分类——object Shep是type Border Collie的一个实例
generalization一般化——type Border Collie是type Dog的子类型
  一般化是可传递的transitive,而分类不可以。我可以组合一个分类,后面接一个一般化,但反过来不可以。
  uml用一般化标识symbol来表示一般化。如果你需要显示分类,使用一个依赖dependency(使用关键字<<instantiate>>)。
  
【多重、动态分类Multiple and dynamic classification】
  分类指一个对象object和它类型type间的关系。
  在单类single classification中,一个对象属于一个单个类型(可能从父类型supertype继承)。在多类中,一个对象被几个类型描述(且不是必要的用继承来联系)。
  多类和多继承不同。多继承指一个类型可能有多个父类型,但一单个类型必须为每个对象定义。多类允许有多个类型给一个对象,而不用为此定义一个特殊的类型。

  见图5.11.


  如果你使用多类,你需要确定哪些组合是合法的。uml2为此将哪些一般化的关系放到一个一般化集合去generalization set。在类图中,你用这个一般化集合的名字 标注这一般化的箭头,在uml1中它叫discriminator辨别物。单类对应一个单个无名的一般化集合。
  一般化集合是默认解体的(disjoint):父类型的任何实例只能是该集合中某一个父类型的实例。
  说明,图表中合法的子类型组合:
(female, patient, nurse); (male, physiotherapist); (female, patient); (female, doctor, surgeon).而(patient, doctor, nurse)是不合法的,因为它包含两个来自role一般化集合的类型。
  动态类dynamic classification允许对象用子类型结构改变类change class within the subtyping structure,而静态类static不能。使用静态类,类型type和状态state被分开。而动态类结合了他们。


【关联类association class】
  它允许你添加属性、操作和其他特性到关联association去。
  见图5.12.
  从图可看出一个人person可能参加很多会议meeting,我们需要掌握他有多清醒的信息keep information about how awake that person was。我们可添加属性attentiveness注意力到这个关联去。

  见图5.13。


  图中将attendance出勤变成了一个完整的类full class,注意多重性的移动。
  关联类添加一个附加的限制extra constraint——在任两个参与的对象间的关联类 只能有一个实例there can be only one instance of the association class between any 2 participanting objects.

  见图5.14.


  在uml中只有后者合法,对于每个person和skill的组合,你只能有一个competency。而前者不允许一个company有超过一个role在一个contract里面。如果你需要允许这个,你需要将role变成一个完整的类。
  实现关联类不明显。我建议实现一个关联类就像一个完整的类,提供获取信息的方法给关联类链接link的类。(My advice is to implement an association class as if it where a full class but to provide methods that get information to the classes linked by the association class)。所以对于5.12,我会看到person有下面的方法:
class Person
List getAttendances()
List getMeetings()
  这样一个person的客户可掌握参加会议的人。如果想要详细,他们可自己获取Attendances。如果你这样做,要记得加强限制——对任何person和meeting的组合只能有一个attendance对象。你需要在任何创建attendance的方法里放一个check。
  如果有临时的关系,我用关键字<<temporal>>来表示关联。


【模板类(参数化parameterized)】
  这个概念在使用强类型语言的集合collections时非常有用。用它,你可为一个集合set定义行为(通过定义一个模板类Set):
class Set<T> {
void insert(T newElem);
void remove(T anElem);

  之后就可以为更多特殊的元素制造类:Set<Employee> employeeSet;  见图5.17.


  一个参数化类的使用,比如
Set<Employee> employeeSet,叫做衍生derivation。这可通过两种方式展示:
·<parameter-name::parameter-value>,如果只用一个参数可以省略参数名
·另一种方法加强了和模板之间的联系,并允许你重命名绑定的元素bound element。

  见图5.18.


  bind关键字是refinement关系上的一个原型stereotype。这暗示EmployeeSet会遵循Set的接口。你可以把EmployeeSet想成Se的一个子类型。
  衍生跟子类型subtyping不同。你不允许添加特性到绑定元素去,它是完全被模板指定的。


【枚举enumerations】
  枚举用来显示一个固定值的集合,没有任何属性除了他们有意义的值。他们是用enumeration关键字的类。
  见图5.20


【活跃类active class】
  一个活跃类有实例instances,他们各自执行、控制自己的控制线程。方法调用会在一个客户的线程或在一个活跃对象的线程里执行。一个好的例子是一个命令处理器command processor,从外部接受命令对象,然后在他自己的控制线程里执行命令。

  见图5.21.


  
【可见性visibility】
  任何类都有public和private元素,public元素可被其他任何类使用,private元素只能被它拥有owning的类使用。
  uml中,你可用一个可见性的指示符标记任何属性和操作,而它的意义是依赖语言的。uml提供4种简写:+public -private ~package #protected。
  大多数时间,我不绘制可视化标记。我只在需要高亮某些元素可见性上区别的时候才使用。


【消息message】

  见图5.22


  标准的uml没有显示消息调用message calls的任何信息,但有时会见到这样的。
  上面添加箭头到关联两边。这些箭头被标记为从一个对象发送到另一个对象的消息。


【职责responsibility】

  见图5.1




【静态操作和属性】
  静态特性在类图中用下划线表示。见图5.2



【聚合和组合aggregation and composition】
  聚合aggregation是部分的关系part-of relationship。就像一辆车有一个引擎和轮子作为其组成部分。

  见图5.3



  见图5.4



  一个Point的实例,可能是一个多边形polygon的部分,或者一个circle的中心,但不能两个都是。
  一般规则是,尽管一个类可以是很多其他类的组件component,但任何实例都必须只是一个拥有者owner的一个组件。类图显示潜在的拥有者的多类,但任何实例只有单个对象作为其拥有者。
  “不共享”no sharing的规则是组合的关键。另一个假设是 如果你删除polygon,你需要自动的确保他拥有的points也都被删掉了。
  
【派生的属性derived properties】
  派生的属性可基于其他值计算出来。比如date range,他的length是通过start和end计算出来的。所以可认为length是从另外两个值得来的derived。
  你可用derivation来指出一个计算的值和以存储的值的区别。比如上面就表示start和end是存储的,而length是计算的。
  这个是用/来标记的。虽然这是一个普遍的使用,但我不强烈,因为他太关心DateRange的内部了。
  见图5.5


【接口和抽象类abstract class】
  一个抽象类是不能直接被实例化的类。你可以实例化其子类。一般一个抽象类有一些抽象的操作operations。一个抽象的操作abstract operation没有实现implementation。只是单纯的声明,那样客户端就能绑定这个抽象类。
  在uml中更普遍的方法来展示一个抽象类或操作,是将其名字用斜体。也可用标签:{abstract}。
  接口是一个没有实现的类,它所有的特性都是抽象的。关键字是<<interface>>。
  类和接口有两种关系:提供provide和需求require。
  一个类提供一个接口如果他可以替换接口。比如一个类通过实现接口或实现接口的一个子类型。
  一个类需要一个接口如果他需要该接口的一个实例来工作。这里是对于接口有一个依赖。
  通过使用接口,我允许自己 之后如果需要可以很容易的改变的实现。

  见图5.6



  例子:
private List lineItems = new ArrayList();
  lineItems被声明为List,且Order的其他地方都没有依赖ArrayList。很普遍的是在创建的时候使用其具体类,之后使用接口。
  任何类是一个接口和一个实现的混合。因此严格讲,给一个父类使用上面的标记是不合法的,因为不是一个纯接口。
  见图5.7


【只读read-only和冻结frozen】
  {readOnly}
  {frozen} 在一个对象的整个生命周期中不能改变,经常叫做immutable不易变的。


【引用对象reference和值对象value】
  引用对象:比如Customer,区分对象需要用id。
  值对象:比如Date,新的对象很频繁的创建和摧毁。如果想看他们是否相同,你不看id,而是看他们代表的值是否相同。这意味着你需要些相等测试的操作符。
  值对象应该是不易变的immutable。你不能将1-Jan-04改成2-Jan-04。而应该创建一个新的2-Jan-04对象来用。
  uml使用数据类型data type的概念。数据类型和值对象不一样,不会有id,值对象有id(但不在相等的时候使用)。
  当和一个值对象关联的时候我使用组合composition。你也可在一个值类型上用关键字:<<value>>或<<struct>>


【限制的关联qualified association】

  见图5.10


0 0
原创粉丝点击