UML的“通用工具箱

395次阅读

一、UML 通用机制:给模型“加细节、做扩展”的工具🔧

关键字:规格说明、修饰、通用划分、扩展机制

UML 的通用机制,就像你画画时的“全能辅助工具包”🧰——光有基础画笔(构造块里的事物、关系、图)不够,还得用橡皮(调整逻辑)、彩笔(加细节标注)、贴纸(自定义扩展),才能让画出来的模型“精准、好懂、能落地”!

课本里明确的 4 种通用机制,核心作用就是解决“基础元素不够用、细节表达不清楚”的问题:

  • 📝 规格说明:给图形“写说明书”,补全背后的隐藏逻辑;
  • 🎨 修饰:给图形“加装饰标记”,一眼看懂关键属性;
  • 🗂️ 通用划分:给元素“做分类”,理清核心逻辑关系;
  • 🧩 扩展机制:给 UML“自定义功能”,适配复杂业务场景。
💡 初学者小贴士:通用机制是 UML 的“进阶技巧”——基础构造块是“骨架”,通用机制是“血肉”,学会这些,你的 UML 图才不会“只画个样子,没实际意义”!

二、规格说明:给模型“写说明书”📝

关键字:图形背后的语义、增量建模、详细约束

很多初学者以为 UML“画个图就行”,其实大错特错!❌ UML 的核心价值是“语义明确”——每个图形符号背后,都藏着“详细说明书”,就像你买家电,外观是“图形”,但“额定电压、使用方法、注意事项”这些说明书才是关键。

举个课本里的经典例子:画一个“订单类(Order)”的矩形,表面只写了“属性:amount(金额)”“方法:pay(支付)”,但它的 规格说明 会包含这些细节:

  • amount 是“Double 类型”,取值范围“大于 0,小于 100000”;
  • pay 方法需要传入“支付方式(String 类型)”和“支付密码(String 类型)”;
  • pay 方法返回“支付结果(Boolean 类型)”,true 表示支付成功,false 表示失败;
  • 支付失败时会抛出“余额不足”“密码错误”两种异常。

类比成“点外卖”:外卖订单的“图形”是“订单号 + 餐品名称”,但“规格说明”是“配送地址、预计送达时间、支付金额、退款规则”这些核心信息——没有这些,订单就没法执行!

实践关键点:增量式建模(不用一次写全!)

初学者不用怕“规格说明太复杂”——它是 “慢慢补充” 的:

  1. 需求阶段:只画类的名称和核心属性(比如 Order 类先写 amount),不用想太细;
  2. 设计阶段:补充属性类型、方法参数和返回值(比如 amount 是 Double,pay 方法要传支付方式);
  3. 开发阶段:完善异常处理、取值约束(比如 amount 不能为负)。
🌐 复杂场景应用:比如银行转账系统的“转账类(Transfer)”,规格说明会写清“转账金额≤账户余额”“单日转账上限 5 万元”“跨行转账要收 0.1% 手续费”——这些约束能在建模阶段就避免开发时出现逻辑漏洞!

三、修饰:给模型“加装饰细节”🎨

关键字:图形附加信息、可见性、抽象类、静态成员

修饰就像给 UML 元素“贴标签、做标记”——比如给笔记本贴“重要”贴纸、给文件夹标“待处理”,让别人一眼就能抓住核心信息,不用翻说明书。

课本里重点讲了 3 类常用修饰,直接对应代码细节,初学者一定要会!

1. 可见性修饰:告诉别人“这个属性 / 方法能不能用”

UML 用 3 个符号表示“访问权限”,就像给房间装不同的门:

  • public(公开):像“客厅的门”,所有人都能进——其他类可以直接访问这个属性 / 方法;
  • private(私有):像“卧室的门”,只有自己能进——只有当前类能访问,其他类不能碰;
  • # protected(保护):像“书房的门”,家人能进——当前类和子类能访问,其他类不能。

对应代码里的访问修饰符,一看就懂👇(Java 示例,Python 用下划线表示私有):

// UML“修饰”对应的 Java 代码
public abstract class Animal { // 抽象类(类名斜体修饰)+ String name; // ➕表示 public:公开属性,所有类能访问
    # int age;    // #表示 protected:保护属性,子类能访问
    - String gender; // ➖表示 private:私有属性,只有 Animal 类能访问

    + abstract void eat(); // ➕+ 斜体:公开抽象方法,子类必须实现
    # void sleep() { // #表示 protected 方法
        System.out.println(name + "在睡觉~");
    }
    - void breath() { // ➖表示 private 方法
        System.out.println(name + "在呼吸~");
    }
}

2. 抽象类 / 抽象方法修饰:类名 / 方法名加斜体

抽象类就像“玩具说明书”——只能看不能直接用,必须“照着做”(被继承)才能用。比如“Animal(动物)”是抽象类,不能直接创建“动物”对象,但能创建它的子类“Dog(狗)”“Cat(猫)”对象。

💡 代码逻辑:抽象方法没有具体实现(没有 {} 里的代码),子类必须重写这个方法——比如 Animal 的 eat()是抽象方法,Dog 要写“吃骨头”,Cat 要写“吃鱼”。

3. 静态成员修饰:属性 / 方法下加横线

静态成员就像“公共工具”——比如公司的打印机,所有人都能用,不用每个人都买一台。UML 里用“下划线”表示,对应代码里的 `static` 关键字:

// 静态成员的代码示例
public class MathUtil {
    + static final double PI = 3.14159; // 静态常量(下划线修饰)+ static int add(int a, int b) { // 静态方法(下划线修饰)return a + b;
    }
}

// 调用静态成员不用创建对象,直接用类名调用
public class Test {public static void main(String[] args) {
        double pi = MathUtil.PI; // 直接用类名访问静态属性
        int sum = MathUtil.add(10, 20); // 直接用类名调用静态方法
        System.out.println(pi); // 输出 3.14159
        System.out.println(sum); // 输出 30
    }
}
🤖 实践价值:看类图时,不用翻代码就知道——加斜体的类不能直接用,加下划线的方法不用创建对象,加➕的属性能直接访问,大大提高团队协作效率!

四、通用划分:给模型“做分类”🗂️

关键字:类型 - 实例、接口 - 实现、分类逻辑

通用划分是 UML 里“最基础的分类思维”——就像把世界上的东西分成“模板和成品”“约定和兑现”,帮你理清元素之间的核心关系,避免逻辑混乱。

1. 类型 - 实例:“模板”和“具体成品”的关系

类型是“通用模板”,实例是“模板造出来的具体东西”——比如“手机(类型)”是模板,“你的苹果 15(实例)”“我的华为 Mate60(实例)”是具体成品。

UML 里实例的表示方法:实例名 : 类型名,实例名加下划线,比如 ` 张三 : User`(张三是 User 类的实例)、` 订单 20250520 : Order`(订单 20250520 是 Order 类的实例)。

对应代码里的“创建对象”,超级直观👇:

// 类型(类)→ 实例(对象)的代码转换
public class User { // 类型:User 类(模板)String name;
    int age;
}

// 创建实例:用模板造具体对象
User zhangsan = new User(); // 张三 : User(实例)zhangsan.name = "张三";
zhangsan.age = 25;

User lisi = new User(); // 李四 : User(另一个实例)lisi.name = "李四";
lisi.age = 30;

💡 初学者类比:类型是“蛋糕模具”,实例是“烤出来的具体蛋糕”——一个模具能烤多个蛋糕,一个类型能创建多个实例!

2. 接口 - 实现:“约定”和“兑现约定”的关系

接口是“行为约定”,就像“租房合同”——约定了“租客要交房租”“房东要修家电”,但没说“租客怎么交房租”“房东怎么修家电”;实现是“兑现约定”,比如租客用微信交房租、房东找维修师傅修家电。

UML 里的表示:接口用“圆圈 + 接口名”表示,实现用“虚线 + 空心三角”(三角指向接口),对应代码里的 `interface` 和 `implements` 关键字(前面构造块部分已举例,这里补充复杂场景)。

🌐 复杂场景应用:电商系统的“支付接口(IPay)”约定了“pay()支付方法”,实现类可以有“微信支付(WeChatPay)”“支付宝支付(Alipay)”“银联支付(UnionPay)”——后续要加“数字人民币支付”,只需要加一个新的实现类,不用改接口和其他实现类,这就是“开闭原则”(对扩展开放,对修改关闭),大项目里超级重要!

五、UML 扩展机制:给模型“自定义功能”🧩

关键字:构造型、标记值、约束、OCL 语言

UML 自带的元素不够用怎么办?扩展机制就是“自定义工具”——像乐高的 MOC(My Own Creation),你可以自己设计新零件、加新标记,适配特殊业务场景。课本里重点讲了 3 种扩展方式,初学者先掌握前两种就行!

1. 构造型:给现有元素“改身份、加含义”

构造型是“给现有元素贴‘特殊标签’”,表示它是“某类特殊角色”,UML 里用 `<< 构造型名 >>` 表示(双尖括号包裹)。

举个实践例子:做 JavaWeb 项目时,你可以给“类”加这些构造型:

  • `<>`:业务实体类(比如 User、Order),对应数据库表;
  • `<>`:服务类(比如 UserService、OrderService),处理业务逻辑;
  • `<>`:数据访问类(比如 UserDao、OrderDao),操作数据库;
  • `<>`:控制器类(比如 UserController、OrderController),接收前端请求。

💡 价值:类图里一眼就能区分“这个类是干嘛的”——比如看到 `<> OrderService`,就知道它是处理订单业务的,不用看代码逻辑!

2. 标记值:给元素“加自定义属性”

标记值是“给元素加额外的描述信息”,比如给类加“作者”“创建日期”“版本号”,UML 里用“name=value”表示。

例子:给 User 类加标记值:

  • `author= 张三 `(这个类是张三写的);
  • `createDate=2025-05-01`(创建日期);
  • `version=1.0`(版本号)。

这些信息不会出现在代码里,但建模时很有用——比如团队协作时,别人看类图就知道这个类是谁负责的、有没有更新到最新版本。

3. 约束:给元素“加规则限制”(进阶但实用)

约束是“给元素加必须遵守的条件”,UML 里用 `{约束内容}` 表示,简单约束可以用自然语言写,复杂约束用 OCL(对象约束语言)写。

简单约束例子:

  • User 类的年龄:`{age >= 18}`(年龄必须≥18);
  • Order 类的金额:`{amount > 0}`(金额必须大于 0)。

复杂约束(OCL 语言示例,初学者了解即可):

// 约束“订单金额必须小于用户余额”context Order inv:
    self.amount < self.user.balance

// 解释:// context Order:约束的是 Order 类
// inv:表示“不变式”(永远成立的规则)// self:指当前 Order 实例
// self.amount:订单金额
// self.user.balance:订单所属用户的余额
🤖 现实复杂场景:比如共享单车系统的“骑行订单(RideOrder)”,约束可以是 `{骑行时间≤24 小时}`(单次骑行不超过 1 天)、`{未支付订单数≤1}`(一个用户不能有多个未支付订单)——这些约束能在建模阶段就规避业务风险,比如不会出现“用户同时有 3 个未支付订单”的情况!

“`

正文完
 0