美文网首页go
类图的6种关系和golang应用

类图的6种关系和golang应用

作者: 玄德公笔记 | 来源:发表于2023-08-06 18:53 被阅读0次

    @[toc]

    1. 依赖和关联

    1.1 依赖(Dependency)

    概念

    • 体现为局部变量、方法的形参,或者对静态方法的调用。
      • 如:出行使用汽车,下雨打伞等
      • 是一种弱关联关系,也是一种临时关系

    类图示例

    classDiagram
      Person ..> Car
      class Person{
      +Travel(car Car)
      }
      class Car{
      }
    

    代码示例

    package main
    
    import "fmt"
    //定义人的类
    type Person struct {
        Name string
    }
    //该类有旅行方法,需要车作为参数
    func (p *Person) Travel(car Car) {
        fmt.Printf("%q 坐着 %q 去旅行", p.Name, car.Name)
    }
    //定义一个汽车类,它是人的依赖
    type Car struct {
        Name string
    }
    
    func main() {
        //实例化一个人
        guanYu := &Person{
            Name: "关羽",
        }
        //实例化一辆车
        chiTu := &Car{
            Name: "赤兔",
        }
        //执行人的旅行方法,车的实例作为参数
        guanYu.Travel(*chiTu)
    }
    
    • 输出
    "关羽"坐着"赤兔"取旅行
    

    1.2 关联(Association)

    概念

    • 体现为类的属性,golang中可以表现为结构体的成员
      • 如:我的朋友(聚合),人和身体部位(组合),汽车和轮子(组合)
      • 是一种强关联关系,也是一种长期关系

    类图示例

    classDiagram
      Person ..> Head
      class Person{
      +Head:Head
      +Hand:String
      }
      class Head{
      }
    

    代码示例

    参考下文 聚合、组合

    2. 组合和聚合(特殊的关联关系)

    2.1 聚合(Aggregation)

    概念

    • 是关联关系的一种,表示一种弱的“拥有”关系。
      • 如人之于人群,苹果之于苹果堆
      • 体现了群体和个体的关系

    类图示例

    主角朋友们成员是由配角聚合而成的一群人,他们和主角不要求有相同的生命周期

    classDiagram
      Protagonist o-- SupportingRole
      class Protagonist{
      +Name:string 
       +Friends:List<SupportingRole>
      }
      class SupportingRole{
      }
    

    因为聚合也是一种特殊的关联关系,因此可以画成:

    classDiagram
      Protagonist o--> SupportingRole
      class Protagonist{
      +Name:string 
       +Friends:List<SupportingRole>
      }
      class SupportingRole{
      }
    

    代码示例

    package main
    
    import "fmt"
    
    // 定义主角类
    type Protagonist struct {
        Name    string
        //它的一个成员是配角的切片
        Friends []SupportingRole
    }
    //定义一个方法让配角加入主角的朋友(此处为了演示方便,和聚合关系无关)
    func (p *Protagonist) AddFriend(supportingRoleList ...SupportingRole) {
        p.Friends = append(p.Friends, supportingRoleList...)
    }
    //定义一个方法查看主角(此处为了演示方便,和聚合关系无关)
    func (p *Protagonist) Get() {
        fmt.Printf("%+v\n", p)
    }
    //定义配角类
    type SupportingRole struct {
        Name string
    }
    
    func main() {
        //实例化一个主角——刘备
        liuBei := &Protagonist{
            Name: "刘备",
        }
        //实例化两个配角——关羽、张飞
        guanYu := SupportingRole{
            Name: "关羽",
        }
        zhangFei := SupportingRole{
            Name: "张飞",
        }
        //将关羽、张飞加入刘备的朋友
        liuBei.AddFriend(guanYu, zhangFei)
        //查看刘备的信息
        liuBei.Get()
    }
    
    
    • 输出
    &{Name:刘备 Friends:[{Name:关羽} {Name:张飞}]}
    

    2.2 组合(Composition)

    概念

    • 是关联关系的一种,表示一种强的“拥有”关系。
      • 如:人之于头、脚;汽车之于驾驶室、发动机
      • 体现了严格的部分和整体的关系
      • 部分和整体的生命周期一样

    类图示例

    的组成部分包括,它们的实例有相同的生命周期

    classDiagram
      Person *-- Head
      class Person{
      +Head:Head
      +Hand:String
      }
      class Head{
      }
    

    因为他也是一种特殊的关联关系,因此可以画成

    classDiagram
      Person *--> Head
      class Person{
      +Head:Head
      +Hand:String
      }
      class Head{
      }
    

    代码示例

    package main
    
    import "fmt"
    //定义一个类——人
    type Person struct {
        Name string
        //他有一个成员是头
        Head Head
    }
    //定义一个类——头
    type Head struct {
        weight float64
    }
    //写一个函数,用来实例化一个具体的人,这样保证了人和头的生命周期一致。(实际操作中可以写一个工厂)
    func CreatePerson(name string, headWeight float64) (person *Person) {
        person = &Person{
            Name: name,
            Head: Head{
                weight: headWeight,
            },
        }
        return person
    }
    
    func main() {
        //实例化一个人——颜良(八斤半的头留给关羽摘吧)
        yanLiang := CreatePerson("颜良", 8.5)
        fmt.Printf("%+v", yanLiang)
    }
    
    
    • 输出
    &{Name:颜良 Head:{weight:8.5}}
    

    3. 实现和泛化(代码的重用)

    3.1 实现(Realization)

    概念

    • 体现为类对接口的实现
      • 比如接口工作方法,其泛化类男人女人都可以实现该接口的工作方法

    类图示例

    如概念中所述,男人女人都实现了接口工作方法

    classDiagram
      Person <|.. Man
      Person <|.. Woman
      class Person{
      <<interface>>
      +Work()
      }
      class Man{
      +Work()
      }
      class Woman{
      +Work()
      }
    

    因为是一种弱关系,因此我们可以看到是虚线链接

    代码示例

    package main
    
    import (
        "fmt"
    )
    //定义一个人的接口
    type Person interface {
        Work()
    }
    //定义男人类是接口人的实现
    type Man struct {
        Name string
    }
    
    func (m *Man) Work() {
        fmt.Println("男人", m.Name, "开心的工作中")
    }
    //定义女人类是接口人的实现
    type Woman struct {
        Name string
    }
    
    func (w *Woman) Work() {
        fmt.Println("女人", w.Name, "开心的工作中")
    }
    //定义一个函数实例化具体的人(实际代码中我们可以写成一个工厂)
    func CreatePerson(name string, sex string) Person {
        switch sex {
        case "man":
            return &Man{
                Name: name,
            }
        case "woman":
            return &Woman{
                Name: name,
            }
        default:
            return nil
        }
    }
    
    func main() {
        CreatePerson("周瑜", "man").Work()
        CreatePerson("小乔", "woman").Work()
    
    }
    
    • 输出
    男人 周瑜 开心的工作中
    女人 小乔 开心的工作中
    

    3.2 泛化(Generalization)

    概念

    • 是继承的逆向关系,子类是父类的泛化。
      • 男人和女人也可以抽象出人类,此时男人和女人是人类的泛化。

    类图示例

    男人的泛化,不但继承了的还拥有胡子

    classDiagram
      Person <|-- Man
      class Person{
      +Name:String
      +Head:String
      }
      class Man{
      +Person:Person
      +Beard:String
      }
     
    

    代码示例

    package main
    
    import "fmt"
    //定义一个类——人
    type Person struct {
        Head string
        Body string
    }
    //定义人的方法,用来设置人的属性
    func (p *Person) SetPerson(head string, body string) {
        p.Head = head
        p.Body = body
    }
    //定义一个男人类,它是人的泛化(即它继承了人)
    type Man struct {
        Person
        Bear string
    }
    //定义一个男人的方法,用来设置男人的属性
    func (m *Man) SetMan(bear string) {
        m.Bear = bear
    }
    
    func main() {
        //实例化一个男人——关羽
        guanYu := &Man{}
        //设置关羽人的属性
        guanYu.SetPerson("大头,红脸", "身高九尺")
        //设置关羽男人的属性
        guanYu.SetMan("长胡子")
        //查看结果
        fmt.Printf("%+v", guanYu)
    }
    
    • 结果输出
    &{Person:{Head:大头,红脸 Body:身高九尺} Bear:长胡子}
    

    image.png

    相关文章

      网友评论

        本文标题:类图的6种关系和golang应用

        本文链接:https://www.haomeiwen.com/subject/kvjwpdtx.html