go

类图的6种关系和golang应用

2023-08-06  本文已影响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)

概念

类图示例

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
上一篇 下一篇

猜你喜欢

热点阅读