Dart之面向对象建模
Dart之面向对象建模

一、前言
面向对象不是一上来就写 class。
真正重要的是:我们怎样把现实世界里的问题,整理成代码能表达的结构。
比如你要写一个宠物管理系统。现实世界里有猫、狗、主人、健康记录。它们有自己的属性,也有自己的行为,还会互相关联。
面向对象建模,就是把这些现实事物一步步转换成对象、类、属性、方法和关系。
这一篇我们重点讲“建模”这件事:先理解面向对象方法,再学会如何从现实问题中提取对象模型。
二、一句话理解
面向对象建模就是把现实世界中的实体、属性、行为和关系,转换成程序里的类、字段、方法和对象关系。
简单说:
- 找名词,识别实体。
- 找特征,定义属性。
- 找动作,确定行为。
- 找关系,建立联系。
- 找共性,抽象分类。
三、面向对象方法 OOM
OOM 是 Object-Oriented Methodology 的缩写,也就是面向对象方法。
它不是单纯的语法技巧,而是一种系统化软件开发方法。
3.1 OOM 是什么
面向对象方法强调:从现实世界出发理解问题。
在 OOM 中,客观世界中的事物、事件、规则、概念,都可以被看成对象。
例如:
- 事物:猫、狗、书籍、汽车。
- 事件:下单、支付、登录。
- 规则:优惠规则、权限规则。
- 概念:用户、订单、账户。
这也是常说的“万物皆对象”。
但这里要注意:万物皆对象不是说所有东西都要硬写成类,而是提醒我们可以从对象的视角分析问题。
3.2 OOM 的四个阶段
面向对象方法通常可以分成四个阶段。
| 阶段 | 作用 |
|---|---|
| OOA 面向对象分析 | 理解需求,识别问题域中的对象、类和关系 |
| OOD 面向对象设计 | 把分析模型转成更具体的软件设计 |
| OOI 面向对象实现 | 使用编程语言实现设计模型 |
| OOT 面向对象测试 | 测试对象行为、对象关系和系统质量 |
可以用盖房子理解:
- 分析:你要建什么房子?
- 设计:房子图纸怎么画?
- 实现:真正开始施工。
- 测试:检查房子能不能正常使用。
软件开发也是一样。不要一开始就敲代码,先把问题理解清楚。
3.3 UML 是什么
UML 是 Unified Modeling Language,也就是统一建模语言。
它提供了一套统一符号,用来描述类、对象、关系、流程等。
初学阶段不需要马上掌握所有 UML 图,但要知道它的意义:让复杂系统的结构能被画出来、讨论清楚、交流一致。
比如类图可以表达:
- 有哪些类。
- 类有哪些属性和方法。
- 类与类之间有什么关系。
四、面向对象建模五步
面向对象建模就是把现实世界中的事物转化为面向对象模型。
4.1 识别实体
第一步是找实体。
实体通常来自需求描述里的名词。
比如宠物管理系统:
- 猫
- 狗
- 主人
- 健康记录
这些都可能成为对象或类。
如果需求里经常出现某个名词,而且它有自己的数据和行为,就值得关注。
4.2 定义属性
属性描述实体的状态或特征。
例如猫和狗可能都有:
- 名字
- 颜色
- 年龄
- 体重
- 健康状态
在 Dart 中,属性通常会变成类中的字段。
class Pet {
String name;
String color;
int age;
String healthStatus;
Pet(this.name, this.color, this.age, this.healthStatus);
}
定义属性时要问:这个对象需要保存哪些信息?
4.3 确定行为
行为描述实体能做什么。
猫和狗可能都有:
- 吃
- 喝
- 睡觉
- 叫
在 Dart 中,行为通常会变成方法。
class Pet {
String name;
Pet(this.name);
void eat() {
print('$name is eating');
}
void sleep() {
print('$name is sleeping');
}
}
确定行为时要问:这个对象需要对外提供哪些能力?
4.4 建立联系
对象之间通常存在关系。
比如:
- 猫和狗都属于宠物。
- 宠物属于某个主人。
- 主人可以拥有多个宠物。
- 健康记录属于某个宠物。
这些关系在代码里可能表现为继承、组合、聚合、关联等。
class Owner {
String name;
List<Pet> pets;
Owner(this.name, this.pets);
}
这里 Owner 拥有一组 Pet,就是一种对象关系。
4.5 抽象与分类
抽象就是提取共同点。
猫和狗都有名字、年龄、吃、睡这些共同特征,所以可以抽象成 Pet 或 Animal。
class Animal {
String name;
Animal(this.name);
void eat() {
print('$name is eating');
}
}
class Cat extends Animal {
Cat(super.name);
void meow() {
print('$name meow');
}
}
class Dog extends Animal {
Dog(super.name);
void bark() {
print('$name bark');
}
}
抽象与分类能减少重复,也能让模型更清楚。
五、猫狗建模案例
现在把五步连起来。
5.1 识别实体
需求:我们要管理猫和狗。
实体:
- 猫
- 狗
- 动物
5.2 定义属性
猫和狗都有一些共同属性:
- 名字
- 颜色
- 年龄
- 健康状态
class Animal {
String name;
String color;
int age;
String healthStatus;
Animal(this.name, this.color, this.age, this.healthStatus);
}
5.3 确定行为
共同行为:
- 吃
- 睡
- 叫
class Animal {
String name;
Animal(this.name);
void eat() {
print('$name is eating');
}
void sleep() {
print('$name is sleeping');
}
void makeSound() {
print('$name makes sound');
}
}
5.4 建立联系
猫和狗都属于动物,可以使用继承表示。
class Cat extends Animal {
Cat(super.name);
@override
void makeSound() {
print('$name 喵喵');
}
}
class Dog extends Animal {
Dog(super.name);
@override
void makeSound() {
print('$name 汪汪');
}
}
5.5 抽象与分类后的使用
void main() {
List<Animal> animals = [
Cat('小猫'),
Dog('小狗'),
];
for (final animal in animals) {
animal.eat();
animal.makeSound();
}
}
这里我们不再分别处理猫和狗,而是先把它们当成 Animal 使用。需要具体叫声时,再由子类自己实现。
这就是建模带来的好处:结构更清楚,扩展也更自然。
六、建模时常见误区
6.1 一上来就写代码
如果需求还没理清,就直接写类,很容易写到一半发现结构不对。
更好的方式是先问:
- 系统里有哪些实体?
- 每个实体有什么属性?
- 每个实体能做什么?
- 实体之间有什么关系?
6.2 把所有名词都建成类
不是所有名词都要变成类。
如果一个概念没有独立状态和行为,可能只是一个字段、枚举或普通值。
建模要服务代码,不是为了把图画复杂。
6.3 只看继承,不看组合
猫和狗是动物,适合继承。
但主人拥有宠物,更适合组合。
继承表达 “is-a”,组合表达 “has-a”。
6.4 忽略业务变化
建模不是一次定死的。
随着需求变化,模型也可能调整。好的模型应该尽量贴近业务,同时保持清晰和可扩展。
七、总结
这一篇我们讲了 Dart 中的面向对象建模。
面向对象方法 OOM 是一种从现实世界出发分析和设计软件的方法。它通常包括分析、设计、实现和测试几个阶段,也可以借助 UML 进行统一表达。
面向对象建模可以按五步走:
- 识别实体。
- 定义属性。
- 确定行为。
- 建立联系。
- 抽象与分类。
真正的重点不是记住术语,而是学会把现实问题拆成代码模型。
当你能从需求中找出实体、属性、行为和关系,就已经开始真正进入面向对象编程的思维方式了。
浙公网安备 33010602011771号