UML基础系列:类图

 

  类图描述系统中类的静态结构,它不仅定义系统中的类,描述类之间的联系,如关联、依赖、聚合等,还包括类的内部结构(类的属性和操作)。类图描述的是静态关系,在系统的整个生命周期中都是有效的。对象图是类图的实例,它们的不同之处在于对象图显示类图的多个对象实例,而不是实际的类。由于对象存在生命周期,所以对象图只能在系统某一时间存在。

1. 类图概述

  类图(Class Diagram)是描述类、接口、协作以及它们之间关系的图,用来显示系统中各个类的静态结构。类图是一种模型类型,一种静态模型类型。一个类图根据系统中的类以及各个类之间的关系描述系统的静态结构。

  类图是面向对象系统建模中最常用的图,它是定义其他图的基础,在类图的基础上,可以使用状态图、协作图、组件图和配置图等进一步描述系统其他方面的特性。

  类图包含7个元素:类(Class)、接口(Interface)、协作(Collaboration)、依赖关系(Dependency)、泛化关系(Generalization)、关联关系(Association)以及实现关系(Realization)。

2. 类(Class)

  类是对一组具有相同属性、操作、关系和语义的对象的描述。类定义聊了一组有着状态和行为的对象。其中,属性和关联用来描述状态。属性通常用没有身份的数据值表示。关联则用有身份的对象之间的关系表示。行为由操作来描述,方法是操作的实现。

  在UML中,类用矩形来表示,并且该矩形被划分为3个部分:名称部分(Name)、属性部分(Attribute)和操作部分(Operation)。其中顶端的部分存放类的名称,中间的部分存放类的属性、属性类型及其值,底部的部分存放类的操作、操作的参数和返回类型。

  类的属性格式:

name : attribute type

  UML规范允许在属性列表节中设置默认值的标识。

name : attribute type = default value

  类的操作格式:

name (parameter list) : type of value returned

  当一个操作有参数时,参数被放在操作的括号内,参数格式:

parameter name : parameter type

  当文档化操作参数时,可以使用一个可选择的指示器,以显示参数到操作的输入参数或输出参数。in 表示输入参数,out 表示输出参数。按照UML规范, in 是参数的默认类型。

  UML基础系列:类图_依赖关系

3. 类之间的关系

  类之间的关系最常用的有4种,分别是表示类之间使用关系的依赖关系(Dependency)、表示类之间一般和特殊关系的泛化关系(Generalization)、表示对象之间结构关系的关联关系(Association)、表示类中规格说明和实现之间关系的实现关系(Realization)。

3.1 依赖关系(Dependency)

  依赖关系用于表示类之间的使用关系,UML定义了4种基本依赖类型:使用依赖、抽象依赖、授权依赖和绑定依赖。

  使用依赖是最常用的依赖,使用依赖关系图:

  UML基础系列:类图_依赖关系_02

  表示客户使用提供者提供的服务以实现它的行为。可以简单的理解,就是一个类A使用到了另一个类B,而这种使用关系是具有偶然性的、临时性的、非常弱的,但是B类的变化会影响到A。客户使用产品需要提供者,但一个客户需要的产品可以有多个提供者。

  场景:Driver与Car,Driver驾驶之前需要Car能够开动。

  依赖关系图:

  UML基础系列:类图_ide_03

  C#实现:

public class Driver
{
     pulic void Drive(Car car)
     {
          car.Move();
     }
}
public class Car
{
     pulic void Move()
     {
          // 省略代码
     }
}

3.2 泛化关系(Generalization)

  泛化关系是一种存在于一般元素和特殊元素之间的分类元素。泛化关系主要表现为类与类之间的继承关系、类与接口之间的实现关系。

  场景:形状类(Shape)为基类,圆形类(Circle)、矩形类(Rectangle)和三角形类(Triangle)均继承形状类。

  类之间的泛化关系图:

  UML基础系列:类图_依赖关系_04

  C#实现:

  Shape.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public abstract class Shape
{
    protected string _name;

    public Shape(string name)
    {
        this._name = name;
    }

    /// <summary>
    /// 面积
    /// </summary>
    /// <returns></returns>
    public abstract double Area();

    /// <summary>
    /// 显示
    /// </summary>
    public abstract void Display();
}

  Circle.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/// <summary>
/// 圆形
/// </summary>
public class Circle : Shape
{
    private double _radius;

    public Circle(string name, double radius)
        : base(name)
    {
        this._radius = radius;
    }

    public override double Area()
    {
        return Math.Round(Math.PI * _radius * _radius, 2);
    }

    public override void Display()
    {
        Console.WriteLine("{0} 半径:{1},面积:{2}", _name, _radius, this.Area());
    }
}

  Rectangle.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/// <summary>
/// 矩形
/// </summary>
public class Rectangle : Shape
{
    private double _width;
    private double _height;

    public Rectangle(string name, double width, double height)
        : base(name)
    {
        this._width = width;
        this._height = height;
    }

    public override double Area()
    {
        return _width * _height;
    }

    public override void Display()
    {
        Console.WriteLine("{0} 长:{1},宽:{2},面积:{3}", _name, _width, _height, this.Area());
    }
}

  Triangle.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

/// <summary>
/// 三角形
/// </summary>
public class Triangle : Shape
{
    private double _a;
    private double _b;
    private double _c;

    /// <summary>
    /// 三角形构造函数
    /// 参数:三角形名称和三条边长
    /// </summary>
    /// <param name="name">三角形名称</param>
    /// <param name="a">第一条边长</param>
    /// <param name="b">第二条边长</param>
    /// <param name="c">第三条边长</param>
    public Triangle(string name, double a, double b, double c)
        : base(name)
    {
        _a = a;
        _b = b;
        _c = c;
    }

    public override double Area()
    {
        double p = (_a + _b + _c) / 2;
        return Math.Sqrt(p * (p - _a) * (p - _b) * (p - _c));
    }

    public override void Display()
    {
        Console.WriteLine("{0} 三条边长:{1},{2},{3},面积:{3}", _name, _a, _b, _c, this.Area());
    }
}

3.3 关联关系(Association)

  关联关系是一种结构关系,它指明一个事物的对象与另一个事物的对象之间的联系。关联关系比依赖关系更强,不存在依赖关系的偶然性,关系也不是临时性的,而一般是长期性的。

3.3.1 单向关联(DirectedAssociation)

  场景:商品和订单,订单中包含商品信息,但商品中不包含订单信息。

  类之间单向关联图:

  UML基础系列:类图_泛化关系_05

  C#实现:

  Product.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Product
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }

    public void Add() { }

    public void Remove() { }

    protected void Find() { }
}

  Order.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Order
{
    public int OrderID { get; set; }

    public List<Product> GetProductsByOrderID(int orderID)
    {
        List<Product> products = new List<Product>();
        // 省略代码
        return products;
    }
}

3.3.2 双向关联(Association)

  场景:用户与角色,一个用户可以属于多个角色,同时一个角色也可以拥有多个用户。

  类之间的双向关联图:

 UML基础系列:类图_依赖关系_06

  C#实现:

  User.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class User
{
    public int UserID { get; set; }
    public string UserName { get; set; }

    public List<Role> GetRolesByUserID(int userID)
    {
        return new List<Role>();
    }
}

  Role.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class Role
{
    public int RoleID { get; set; }
    public string RoleName { get; set; }

    public List<User> GetUsersByRoleID(int roleID)
    {
        return new List<User>();
    }
}

3.3.3 聚合关系(Aggregation)

  聚合表示的是一种has-a的关系,是一种整体-部分关系,同时整体与部分之间又可以相互分离。整体与部分拥有相互独立的生命周期,部分的生命周期并不由整体来管理决定。当整体这个对象已经不存在的时候,部分的对象还是可能继续存在的。整体可以包含多个部分,部分可以属于多个整体对象,也可以为多个整体对象共享。

  场景:汽车与车轮,汽车有多个车轮。车轮使用周期结束,可以为汽车安装新的车轮。同时汽车使用周期结束,可再用的车轮也可以卸下安装到其他的汽车上。

  聚合关系图:

  UML基础系列:类图_生命周期_07

  C#实现:

Wheel wheel = new Wheel();
Car car = new Car(wheel);

  或者

Car car = new Car(new Wheel());

  Car与Wheel的生命周期相互独立。

3.3.4 组合关系(Composition)

  组合关系是聚合关系的另一种形式,体现的是一种contains-a的关系,但是整体与部分拥有共同是生命周期,整体与部分不可分,一旦整体对象不存在,部分对象也将不存在。子类对象的生命周期依赖于父类的生命周期。

  场景:公司(Company)与公司内部设置的部门(Department),一个Company对象至少有一个Department对象,当Company对象被销毁时,Department对象也将同时被销毁。

  组合关系图:

  UML基础系列:类图_依赖关系_08

  C#实现:

public class Department ()
{
        // 省略代码
}
pulic class Company ()
{
        Department d = new Department ();
        // 省略代码
}

  Department对象在Company对象中创建,当Company对象的生命周期结束的时候,Department对象的生命周期同时也结束。

3.4 实现关系(Realization)

  实现是规格说明和其实现之间的关系,实现关系通常在两种情况下被使用:在接口与实现该接口的类之间;在用例以及实现该用例的协作之间。

  实现关系图:

  UML基础系列:类图_依赖关系_09