面向对象之类图
发表于|更新于
|阅读量:
最近在绘制类图的时候,发现图时不能按照准确的描述类之间的关系,遂整理类图与面向对象的关系
类图:描述类及其内部结构和操作,以及类间的静态关系
对象图:描述运行时特定对象结构的示意图
交互图:展示对象间请求流程的一种示意图
描述面向对象关系:面向对象编程是基于类实现的,类体现了对对象的总结,包含事物的数据和行为。类与类之间的协作或者关系有如下六种:
- 依赖关系
- 关联关系
- 聚合关系
- 组合关系
- 继承关系
- 实现关系
1.依赖关系
1.1 依赖关系的定义
依赖关系表示一个元素(类、接口)等的变化可能会影响另外一个元素。它是临时性的、较弱的关系。通常出现在方法参数、返回值、局部变量或方法调用上。
1.2 uml表达依赖关系
在UML类图中,用虚线箭头“—>”表示依赖关系,由依赖方指向被依赖方
在uml中用..>描述依赖,如果是 A依赖B, 则记作 A ..> B
在关系之间使用标签来说明时, 使用 :后接 标签文字。
语义:
- A依赖B意味着A在某处使用了B,B的变化会影响A
- B不是A的成员变量
1.3 依赖关系示例代码
- 方法参数依赖
1 2 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 依赖关系示例类图
1 2 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 单向关联示例代码
1 2 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 单向关联示例类图
1 2 3 4 5 6 7 8
| class Blog { +Title string +Author *User } class User { +Name string } Blog --> User : 关联
|
2.4.1 双向关联示例代码
学生和课程相互持有,形成双向关联
通常在orm多对多的关系中出现
1 2 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 双向关联示例类图
1 2 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 聚合关系示例代码
1 2 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 聚合关系示例类图
对应的建模表达为:
1 2 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 组合关系示例代码
创建汽车时,出场必须自带发动机;报废销毁时,也必须将发动机销毁
1 2 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 组合关系示例类图
1 2 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中推崇 组合代替继承的设计模式,通常采用结构体嵌入的方式实现继承,以此访问父类属性、方法等
1 2 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 继承关系示例类图
1 2 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 实现关系代码示例
1 2 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 实现关系示例类图
1 2 3 4 5 6 7 8
| interface Speaker { +Speak() string } class Dog { +Name string +Speak() string } Dog ..|> Speaker : 实现
|
引用
1. plantuml类图