面向对象之类图
发表于|更新于
|阅读量:
最近在绘制类图的时候,发现图时不能按照准确的描述类之间的关系,遂整理类图与面向对象的关系
类图:描述类及其内部结构和操作,以及类间的静态关系
对象图:描述运行时特定对象结构的示意图
交互图:展示对象间请求流程的一种示意图
描述面向对象关系:面向对象编程是基于类实现的,类体现了对对象的总结,包含事物的数据和行为。类与类之间的协作或者关系有如下六种:
- 依赖关系
- 关联关系
- 聚合关系
- 组合关系
- 继承关系
- 实现关系
1.依赖关系
1.1 依赖关系的定义
依赖关系表示一个元素(类、接口)等的变化可能会影响另外一个元素。它是临时性的、较弱的关系。通常出现在方法参数、返回值、局部变量或方法调用上。
1.2 uml表达依赖关系
在UML类图中,用虚线箭头“—>”表示依赖关系,由依赖方指向被依赖方
在uml中用..>描述依赖,如果是 A依赖B, 则记作  A ..> B
在关系之间使用标签来说明时, 使用 :后接 标签文字。
语义: 
- A依赖B意味着A在某处使用了B,B的变化会影响A
- B不是A的成员变量
1.3 依赖关系示例代码
- 方法参数依赖| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | type PaymentGateway interface {Charge(amount float64) error
 }
 
 type OrderService struct{}
 
 
 func (s *OrderService) Process(order Order, gateway PaymentGateway) error {
 return gateway.Charge(order.Amount)
 }
 
 |  
 
1.4 依赖关系示例类图
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | class OrderService {+Process(Order, PaymentGateway) error
 }
 interface PaymentGateway {
 +Charge(float64) error
 }
 class Order {
 +Amount float64
 }
 
 OrderService ..> PaymentGateway : 依赖
 OrderService ..> Order : 依赖
 
 | 
2 关联关系
2.1 关联关系的定义
关联关系描述的是两个结构体或着类之间的长期关系,通常表现为:
- 结构体a持有另一个结构体的引用作为字段
- 关系可以是单向关系或双向关系
- 比依赖关系跟强,比组合/聚合关系弱
2.2 uml表达
在UML类图中,以实线箭头表示,箭头指向被关联的类
对应的uml表达为 -->
2.3.1 单向关联示例代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | type User struct {Name string
 }
 
 type Blog struct {
 Title  string
 Author *User
 }
 
 func main() {
 user := &User{Name: "Alice"}
 blog := &Blog{Title: "Go Tips", Author: user}
 fmt.Println(blog.Author.Name)
 }
 
 | 
2.3.2 单向关联示例类图
| 12
 3
 4
 5
 6
 7
 8
 
 | class Blog {+Title string
 +Author *User
 }
 class User {
 +Name string
 }
 Blog --> User : 关联
 
 | 
2.4.1 双向关联示例代码
学生和课程相互持有,形成双向关联
通常在orm多对多的关系中出现
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | type Student struct {Name    string
 Courses []*Course
 }
 
 type Course struct {
 Name     string
 Students []*Student
 }
 
 func main() {
 alice := &Student{Name: "Alice"}
 math := &Course{Name: "Math"}
 
 alice.Courses = append(alice.Courses, math)
 math.Students = append(math.Students, alice)
 }
 
 | 
2.4.2 双向关联示例类图
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | class Student {
 +Name string
 +Courses []*Course
 }
 class Course {
 +Name string
 +Students []*Student
 }
 Student "1" --> "*" Course : 选课
 Course "1" --> "*" Student : 学生
 
 | 
3 聚合关系
3.1 聚合关系的定义
聚合关系是一种特殊的关联关系,表示整体-部分的关系,其特点是:
- 部分可以独立存在,整体并不控制部分的生命周期
- 弱于组合,强于普通关联关系
3.2 uml表达
在UML类图中, 用带实线的空心菱形 <>-->表达聚合关系
对应的uml表达是 o-->, 菱形指向整体,箭头指向部分
3.3 聚合关系示例代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | type Player struct {Name string
 }
 
 type Team struct {
 Name    string
 Players []*Player
 }
 
 func main() {
 player1 := &Player{Name: "Messi"}
 player2 := &Player{Name: "Ronaldo"}
 
 team := &Team{
 Name:    "Dream Team",
 Players: []*Player{player1, player2},
 }
 
 fmt.Println(team.Players[0].Name)
 }
 
 | 
3.4 聚合关系示例类图
对应的建模表达为:
| 12
 3
 4
 5
 6
 7
 8
 
 | class Team {+Name string
 +Players []*Player
 }
 class Player {
 +Name string
 }
 Team o--> Player : 聚合
 
 | 
4 组合关系
4.1 组合关系的定义
组合关系是一种强整体-部分关系,特点为:
- 部分不能独立存在,其生命周期由整体控制
- 比聚合关系更强,整体销毁时部分也会销毁
4.2 uml表达
在UML类图中,使用 带实线的 实心菱形 描述组合关系, 菱形指向整体
对应的uml表达为 *-->,
4.3 组合关系示例代码
创建汽车时,出场必须自带发动机;报废销毁时,也必须将发动机销毁
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | type Engine struct {Model string
 }
 
 type Car struct {
 Engine *Engine
 }
 
 
 func NewCar() *Car {
 return &Car{
 Engine: &Engine{Model: "V8"},
 }
 }
 
 func main() {
 car := NewCar()
 fmt.Println(car.Engine.Model)
 
 
 }
 
 | 
4.4 组合关系示例类图
| 12
 3
 4
 5
 6
 7
 
 | class Car {+Engine *Engine
 }
 class Engine {
 +Model string
 }
 Car "1" *--> "1" Engine : 组合
 
 | 
5. 继承关系
5.1 继承关系定义
继承指一个类的定义可以基于另外一个已经存在的类,即子类基于父类以达到复用代码的目的
Go 语言 没有直接的类继承(Class Inheritance),但可以通过以下两种方式模拟类似功能:
- 结构体嵌入(Embedding):实现 方法复用和字段继承(类似组合)。
- 接口组合(Interface Composition):实现 多态和行为继承
5.2 建模表示
在UML类图中,使用带实线的三角箭头描述,箭头指向父类
在uml中用 --|>表示, A --|> B即为A继承B 
5.3 继承关系示例代码
go中推崇 组合代替继承的设计模式,通常采用结构体嵌入的方式实现继承,以此访问父类属性、方法等
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | type Animal struct {Name string
 }
 
 func (a *Animal) Speak() string {
 return "I'm an animal"
 }
 
 
 type Dog struct {
 Animal
 Breed   string
 }
 
 func main() {
 dog := Dog{
 Animal: Animal{Name: "Buddy"},
 Breed:  "Golden Retriever",
 }
 fmt.Println(dog.Name)
 fmt.Println(dog.Speak())
 }
 
 
 | 
5.4 继承关系示例类图
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | class Animal {
 +Name string
 +Speak() string
 }
 class Dog {
 +Breed string
 }
 Dog --|> Animal : 嵌入(类似继承)
 
 | 
6. 实现关系
6.1 实现关系的定义
实现关系指一个类(或结构体)实现某个接口,即满足接口定义的方法契约。
Go语言中,实现关系是隐式的(无需显式声明),只要类型实现了接口的所有方法,就自动实现了该接口
6.2 uml表达
在UML类图中,以带三角箭头的虚线表示,箭头指向接口
对应的建模语言为 <|.., Dog ..|> Speaker即dog实现了speaker接口
6.3 实现关系代码示例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | type Speaker interface {
 Speak() string
 }
 
 
 type Dog struct {
 Name string
 }
 
 
 func (d Dog) Speak() string {
 return "Woof! My name is " + d.Name
 }
 
 func main() {
 var speaker Speaker = Dog{Name: "Buddy"}
 fmt.Println(speaker.Speak())
 }
 
 | 
6.4 实现关系示例类图
| 12
 3
 4
 5
 6
 7
 8
 
 | interface Speaker {+Speak() string
 }
 class Dog {
 +Name string
 +Speak() string
 }
 Dog ..|> Speaker : 实现
 
 | 
引用
1. plantuml类图