编辑推荐: |
本文主要用PHP来解释UML,希望对您有所帮助。
本文来源于:sunrack的空间,由火龙果软件Linda编辑,推荐。 |
|
一、Class Diagrams
类图描述了系统中的对象以及它们之间的静态关系,同时还描述了类的 properties 和 operations (统称为 feature ) ,以及对象之间的 constraints 。
二、Property
Property 可以看作类的字段(fields),一个单独的概念,有两种不同的标记:attributes 和 associations。标记不同,实际上是完全一样的。
1、Attributes
visibility name: type multiplicity = default {property-string}
例如:
- name: String [1] = "Untitled" {readOnly}
只有 name 是必须的。 |
2、Associations(unidirectional associations)
一个 association 用连接两个类的实线表示,箭头指向 property 的类型,并在箭头处标明 attributes 的名称以及多重性(multiplicity)。
和 attributes 相比,二者表达的信息几乎一样,但 association 可以在实线的两边都显示多重性。
3、如何选择 Attributes 和 Associations
一般用 Attibutes 来表示比较小的对象,比如值类型,而用 Associations 来表示比较重要的对象。
一般用类框来表示类图中比较重要的对象,该对象会使用 Associations ,而用 Attibutes 表示相对不重要的对象。
关键看侧重点在哪里。
三、Multiplicity
Property 的 Multiplicity 指明该属性有多少个对象。
1、常见的有
1 仅有1个
0..1 没有或者仅有1个
* 没有或者任意
2、一般格式:
下边界...上边界 (lower bound...upper bound)
下边界: 0 或者 任意正值
上边界: 任意正值 或者 *
如果 上下边界相等,可以用一个数字,比如 1 可以用 1..1 代替, * 可以用 0..* 代替。
3、对 Attributes 而言,有以下的多重性:
- Optional - implies a lower bound of 0.
- Mandatory - implies a lower bound of 1 or possibly more.
- Single-valued - implies an upper bound of 1.
- Multivalued - implies an upper bound of more than 1: usually *.
4、对于 multivalued property,一般使用复数形式的名称。
5、一般来说, 当多重性为多值时,该属性组合成一个集合,该集合并没有排序。
在 association 的箭头终点 用
{ordered} 表示数据是经过排序的
{nonunique} 表示数据不是唯一的
{unordered}+{unique} 默认值
6、不连续的多重性
UML 1中可以使用不连续的多重性,如 2,4 表示 2或者4
UML 2种已经取消该表示方法,因为使用不多。
7、默认值
association 的多重性默认值是 [1]。
但是如果没有标出多重性的话,不能假设该 association 的多重性就是1,因为有可能隐藏了部分信息。
所以,如果该多重性很重要的话,就明确的用 [1] 标出。
四、Property 和编程语言的对应
支持 Property 的编程语言中,相当于 public properties,
不支持 Property 的编程语言中,相当于 private fields,这些 fields 通过 accessor(getting 和 setting) 公开。
一个 read-only attribute 没有 setting method (with fields) or set action (for properties).
public class OrderLine
public int Quantity;
public Money Price;
public Order Order;
public Product Product; |
使用 private fields 太关注实现细节,另外一种基于接口的方式则关注 getting methods,而不管内部的数据。
public class OrderLine
private int quantity;
private Product product;
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Money getPrice() {
return product.getPrice().multiply(quantity);
} |
这里并没有给price 定义 field, 而是通过计算得出的。
如果 attribute 是 multivalued的,则一般实现为 collection.如果多重性是排序的,则该集合也应该是排序的。比如 .NET 中的 IList。不过,大家一般把没有排序的多重性也实现为 IList。
multivalued properties 实现方式和 single-valued properties 不一样:(java)
class Order {
private Set lineItems = new HashSet();
public Set getLineItems() {
return Collections.unmodifiableSet(lineItems);
}
public void addLineItem (OrderItem arg) {
lineItems.add (arg);
}
public void removeLineItem (OrderItem arg) {
lineItems.remove(arg);
} |
一般不是定义一个集合属性,而是通过 add 和 remove 方法进行集合元素的更新,不让外界的对象直接操作集合对象本身。
因为 multivalued attributes 已经是集合,所以在类图中,一般不使用 collection classes,而只是在底层集合的实现中显示。
应该避免一个类只包含了一个集合field和它的 accessors。根据OO设计规则,类应该具有丰富的功能,而不仅仅只是提供数据。如果你频繁的使用 accessor 来访问数据,那就应该把这些行为移到拥有数据的对象中。
以上的示例表明,UML 和 code 之间并不能完全对应,但是很相似。在一个团队中通过制定规则,可以保持它们的一致。
不管 property 实现为 field 还是计算得出,这个数据都是类可以一直提供的。不能用来实现 transient relationship,例如,只用于函数调用内部使用的传入参数。
五、Bidirectional Associations
1、双向箭头表示方式
The Car class has property owner:Person[1], and the Person class has a property cars:Car[*].
这里使用了复数形式的名称 cars.
反方向的箭头意味着,可以从 从一个属性出发,回到包含出发点的一个集合。比如,从一个car A 找到owner,然后再通过owner的cars得到的集合,包含cae A.
2、动词短语表示方式
另外一种使用动词短语表示方式,特别是数据库建模时:
一般只命名一部分双向联接,以提高易读性。
一般使用有双向箭头的表示方式,可以很直观的看出双向联接关系。
3、编程语言实现
一般是让联接中 single-valued 的对象来控制关联,作为主对象。从对象(Person)需要添加一个很别扭的函数,把自己保存的数据(cars)公开给主对象(car)。
class Car
public Person Owner {
get {return _owner;}
set {
if (_owner != null) _owner.friendCars().Remove(this);
_owner = value;
if (_owner != null) _owner.friendCars().Add(this);
}
}
private Person _owner;
class Person
public IList Cars {
get {return ArrayList.ReadOnly(_cars);}
}
public void AddCar(Car arg) {
arg.Owner = this;
}
private IList _cars = new ArrayList();
internal IList friendCars() {
//should only be used by Car.Owner
return _cars;
} |
六、Operations
1、格式
visibility name (parameter-list) : return-type {property-string}
· This visibility marker is public (+) or private (-); others on page 83.
· The name is a string.
· The parameter-list is the list of parameters for the operation.
· The return-type is the type of the returned value, if there is one.
· The property-string indicates property values that apply to the given operation.
The parameters in the parameter list are notated in a similar way to attributes. The form is:
direction name: type = default value
· The name, type, and default value are the same as for attributes.
· The direction indicates whether the parameter is input (in), output (out) or both (inout).
If no direction is shown, it's assumed to be in. |
2、query 和 modifiers
query 只是获取类的内部数据,不改变内部数据,没有副作用(side effects). 可以用 {query} 表示。因此可以改变queries的执行顺序而不会影响结果。
modifiers 改变类的内部数据,也成为 commands.
严格一点的话,区别的关键在于是否改变了类的 observable state。
3、Command-Query separation principle
一般尽可能地让 query 返回值,而 modifiers 不返回值。
4、Getting 和 Setting methods
A getting method returns a value from a field (and does nothing else).
A setting method puts a value into a field(and does nothing else).
不能认为 getting method 是 query,setting method 是 modifiers,完全取决于类内部如何实现。
5、operation 和 method 的区别
An operation is something that is invoked on an object—the procedure declaration—whereas a method is the body of a procedure.
例如,一个父类,三个子类,都实现了父类的一个 operation ,这里就是一个 operation ,四个 methods 实现了它。
一般二者可以互换使用。
七、Generalization
1、相当于编程语言中的继承 inheritance。
2、Substitutability
可以使用子类实例来替换需要父类实例的参数。
3、继承的缺点
例如,不需要系统提供的string,自己实现一个简单的,只能继承后再实现,结果需要实现很多不需要的属性和功能。
4、interface
可以使用 interface来实现子类型,而不需要通过继承实现。
八、Notes and Comments
Notes 可以单独存在,或者通过 dashed line 联接到被注释的元素上。Notes可以使用在任何图表中。
有时候不能判断虚线的结束位置,可以在虚线的结束位置添加一个很小的半圆(open circle)。
也可以对元素使用内部注释(in-line commnet), 使用 -- 隔开。
九、Dependency
1、A dependency exists between two elements if changes to the definition of one element (the supplier) may cause changes to the other (the client).
2、对类而言,依赖的原因:
One class sends a message to another;
one class has another as part of its data;
one class mentions another as a parameter to an operation.
If a class changes its interface, any message sent to that class may no longer be valid. |
3、必须控制dependencies规模,否则,依赖程度越高,系统变动时需要的改动和风险就越高。
4、UML中可以使用 dependency 描述任意2个元素之间的依赖关系。
5、举例
The Benefits Window class—a user interface, or presentation class—is dependent on the Employee class: a domain object that captures the essential behavior of the system—in this case, business rules.
6、Dependency 是单向的
例如,Employee 的改动会影响 Benefits Window,但是反过来不成立,所以可以自由修改 Employee,而不会影响到 Benefits Window。
区分 presentation 和 domain 的规则:presentation 依赖于 domain。
另外可以看出,Benefits Window 和 两个 Data Gateway 没有直接依赖关系,如果 两个 Data Gateway 只是变动了Employee 相关的内容,那么 Benefits Window 就不需要变动。
最基本的依赖关系不是 transitive relationship,只有子类关系是传递依赖,直接和间接的依赖关系是有很多区别的。
许多UML relationship 实现了一个 dependency ,例如,Order is dependent on Customer,子类依赖于父类,但反过来不成立。
7、Dependency 的种类
不同的 Dependency 有不同的语法和关键词。
8、规则
应尽量减少依赖,特别是环形的依赖,但是也不一定要强制,如果两个类之间确实联系很紧密的话,也是可以使用的。但是在更高的层次,例如packages之间是不应该存在环形的依赖的。
只需要画出特别重要的依赖,而且为了更好的理解和控制,最好不要在packages之间使用依赖。
一般只使用依赖来表示 transient relationship,例如传递参数,使用了?parameter?, ?local?, and ?global? 等关键字。这些在 UML 1 中表示 transient links, not properties,在 UML 2种已经取消了。
可以使用工具软件来分析依赖。
十、Constraint Rules
1、可以使用任何形式来描述约束,只需要放在 {} 中即可。
natural language,。
a programming language。
the UML's formal Object Constraint Language (OCL)
OCL可以避免歧义,但是也有可能对方不懂OCL而无法理解。
也可以给约束命名: {name : text}
例如: {disallow incest: husband and wife must not be siblings}.
2、Design by Contract
Assertion
Post-condition
Pre-condition
Exception
Invariant |
由调用者进行 Pre-condition 的验证。
一个 exception 只能发生在,Post-condition 通过验证,但是无法返回正确结果。
An invariant is an assertion about a class.一直保持为真值。
对类的所有 public operations 的pre-conditions 和 post-conditions 绑定。在执行过程中可以不为真,但是当其它对象访问该对象时,必须恢复为真。
Assertions 在子类中可以发挥重要作用。子类中可能会重新定义操作,变得与父类不一致。使用 Assertions 可以降低这种风险。The invariants 和 post-conditions 所有的子类都必须遵守。子类可以加强 Assertions 但不能弱化。但是对 pre-condition,子类可以进行弱化,但不能加强。
这个规则对动态数据绑定(dynamic binding)很有用。根据可替换规则,子类可以当成是父类的一个实例,如果子类加强了 pre-condition,那可能会导致父类的一个操作(operation)在子类上执行时报错。
|