go面向对象和设计模式

2023-03-17  本文已影响0人  mafa1993
  1. go没有类型继承
  2. go的继承不存在is-a关系
type parent struct {
    a int
}
type sub struct {
    p parent
    a int
}

func NewPeople(p *parent) *parent{
    return &p;
}

func (p *parent)dump(){
    fmt.Printf("p %s",p.a)
}

func(s *sub)dump(){
    fmt.Printf("s %s",s.p.a)
}

func main(){
    
    a := NewPeople(&people{a:1})

    // b := NewPeople(&sub{p:p,a:2})  // 会报错,

    b:= sub{parent{a:1},a:2}
    b.dump()  // 打印不出父类的a值
}

interface的特点

  1. 不需要显示声明关系,只要两者方法集有包含关系,则看做同一类型

solid原则

  1. SRP 单一职责, 一个模块只有一个功能,一个文件也要只有一个功能
  2. OCP 开闭原则,软件实体(类、模块、函数)应该是可扩展的,但不可修改,对扩展是开放的,对修改是关闭的
  3. 里氏替换原则LSP,可以用子类替换父类,实现interface和function type时,不能破坏其对外的契约,要做到宽进严出,即:入参宽泛,出参严格控制,子类的校验要比父类更宽泛
  4. ISP 接口隔离原则,功能相互隔离
  5. DIP 依赖倒置原则,高层不应该依赖底层,底层应该依赖于接口,例如A要依赖B,可以把A的依赖改成一个接口,B去实现这个接口

常用设计模式

  1. 工厂方法,创建相关对象的时候,根据传参决定创建哪个对象
package main 
import "fmt"

type cni interface {
    createNet()
}

type canai struct {}
func(c canai) createNet(){
    fmt.Println("c create net")
}

type calico struct{}
func(c calico) createNet(){
    fmt.Println("ca create")
}

func cniFactory(name string)cni {
    switch name {
        case "canai":
            return canai{};
        case "calico":
            return calico{}
    }
}


func main() {
    canai := cniFactory("canai")
    canai.createNet()

    calico := cniFactory("calico")
    calico.createNet()

}
  1. 抽象工厂,创建一组对象
  2. 生成器
package main 
import "fmt"

type req interface{
    send()
}

type cniReq struct {
    network string 
    qos interface{}
    multiIP bool
    fixIP bool
}

func (c *cniReq) send(){
    fmt.Println("send req ")
}

// 用于生成builder
type cniReqBuilder interface {
    withNetwork(network string)cniReqBuilder
    withQos(qos interfacd) cniReqBuilder
    withMultiIP() cniReqBuilder
    withFixIP() cniReqBuilder
    build() req  // 用于生成req
}

type builder struct {
    network string 
    qos interface{}
    multiIP bool
    fixIP bool
}

// 用于builder对象属性的设置
func (b *builder)withNerwork(network string) cniReqBuilder{
    b.network=network
    return b
}
func (b *builder)withQos(network interface{}) cniReqBuilder{
    b.network=network
    return b
}

func (b *builder)withMultiIP() cniReqBuilder{
    return b
}
func (b *builder)withFixIP() cniReqBuilder{
    return b
}

func(b *builder) build() req {
    return &cniReq{
        network:b.network,
        qos:b.qos,
        multiIP:b.multiIP,
        fixIP:b.fixIP,
    }
}

func NewBuilder() cniReqBuilder {
    return builder{}
}

func main() {
    // 利用builder创建req
    cniReq := NewBuilder().withNetWork("x").
    withQos(nil).
    withFixIP().
    build()
    cni.send();
}
  1. 原型
package main
import "fmt"
type machineTemp struct {
    name string 
    disk int
    network string
    os string
    runtime string
}

func (m *machineTemp) deepCopy() *machineTemp{
    return &machineTemp{
        name: m.name,
        disk:m.disk,
        network:m.network,
        os:m.os,
        runtime:m.runtime
    }
}

// 从数据库等获取一个模板,模板不能进行修改,所以开始要deepcopy,然后修改copy的对象
func getMachineTemp()*matchineTemp{
    template := getMachineTemp()

    t := template.deepCopy()

    t.os = "xx"
    
}
  1. 单例模式,创建的对象比较大,又经常使用
package main
import (
    "fmt"
    "sync"
)

var (
    globalConf * conf
    once = &sync.Once{}
)

type conf struct {
    ip string
    port int
}

func (c config)getIP() string{
    return c.ip
}

func getInstance() *config {
    once.Do(func(){
        // 这里可能需要解析配置文件,会比较耗费资源,使用单例,只执行一次
        globalConf = &conf{
            ip:"x",
            port:1
        }
    })
    return globalConf
}

func main(){
    ip:=getInstance().getIP()
    port := getInstance().port
}
上一篇下一篇

猜你喜欢

热点阅读