一、UML 通用机制:给模型“加细节、做扩展”的工具🔧
UML 的通用机制,就像你画画时的“全能辅助工具包”🧰——光有基础画笔(构造块里的事物、关系、图)不够,还得用橡皮(调整逻辑)、彩笔(加细节标注)、贴纸(自定义扩展),才能让画出来的模型“精准、好懂、能落地”!
课本里明确的 4 种通用机制,核心作用就是解决“基础元素不够用、细节表达不清楚”的问题:
- 📝 规格说明:给图形“写说明书”,补全背后的隐藏逻辑;
- 🎨 修饰:给图形“加装饰标记”,一眼看懂关键属性;
- 🗂️ 通用划分:给元素“做分类”,理清核心逻辑关系;
- 🧩 扩展机制:给 UML“自定义功能”,适配复杂业务场景。
二、规格说明:给模型“写说明书”📝
很多初学者以为 UML“画个图就行”,其实大错特错!❌ UML 的核心价值是“语义明确”——每个图形符号背后,都藏着“详细说明书”,就像你买家电,外观是“图形”,但“额定电压、使用方法、注意事项”这些说明书才是关键。
举个课本里的经典例子:画一个“订单类(Order)”的矩形,表面只写了“属性:amount(金额)”“方法:pay(支付)”,但它的 规格说明 会包含这些细节:
- amount 是“Double 类型”,取值范围“大于 0,小于 100000”;
- pay 方法需要传入“支付方式(String 类型)”和“支付密码(String 类型)”;
- pay 方法返回“支付结果(Boolean 类型)”,true 表示支付成功,false 表示失败;
- 支付失败时会抛出“余额不足”“密码错误”两种异常。
类比成“点外卖”:外卖订单的“图形”是“订单号 + 餐品名称”,但“规格说明”是“配送地址、预计送达时间、支付金额、退款规则”这些核心信息——没有这些,订单就没法执行!
实践关键点:增量式建模(不用一次写全!)
初学者不用怕“规格说明太复杂”——它是 “慢慢补充” 的:
- 需求阶段:只画类的名称和核心属性(比如 Order 类先写 amount),不用想太细;
- 设计阶段:补充属性类型、方法参数和返回值(比如 amount 是 Double,pay 方法要传支付方式);
- 开发阶段:完善异常处理、取值约束(比如 amount 不能为负)。
三、修饰:给模型“加装饰细节”🎨
修饰就像给 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` 关键字(前面构造块部分已举例,这里补充复杂场景)。
五、UML 扩展机制:给模型“自定义功能”🧩
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:订单所属用户的余额
“`