美文网首页Go语言
Go 常用的设计模式

Go 常用的设计模式

作者: 潘晓华Michael | 来源:发表于2022-04-24 11:31 被阅读0次
    常用设计模式

    1. 单例模式:

    
    package singleton
    
    import (
        "sync"
    )
    
    type singleton struct {
    }
    
    var ins *singleton
    var once sync.Once
    
    func GetInsOr() *singleton {
        once.Do(func() {
            ins = &singleton{}
        })
        return ins
    }
    

    2. 简单工厂模式

    
    type Person struct {
      Name string
      Age int
    }
    
    func (p Person) Greet() {
      fmt.Printf("Hi! My name is %s", p.Name)
    }
    
    func NewPerson(name string, age int) *Person {
      return &Person{
        Name: name,
        Age: age,
      }
    }
    

    3. 抽象工厂模式

    它返回的是接口而不是结构体。

    
    type Person interface {
      Greet()
    }
    
    type person struct {
      name string
      age int
    }
    
    func (p person) Greet() {
      fmt.Printf("Hi! My name is %s", p.name)
    }
    
    // Here, NewPerson returns an interface, and not the person struct itself
    func NewPerson(name string, age int) Person {
      return person{
        name: name,
        age: age,
      }
    }
    

    4. 工厂方法模式

    
    type Person struct {
      name string
      age int
    }
    
    func NewPersonFactory(age int) func(name string) Person {
      return func(name string) Person {
        return Person{
          name: name,
          age: age,
        }
      }
    }
    

    5. 策略模式

    在项目开发中,我们经常要根据不同的场景,采取不同的措施,也就是不同的策略。比如,假设我们需要对 a、b 这两个整数进行计算,根据条件的不同,需要执行不同的计算方式。为了解耦,需要使用策略模式,定义一些独立的类来封装不同的算法,每一个类封装一个具体的算法(即策略)。

    
    package strategy
    
    // 策略模式
    
    // 定义一个策略类
    type IStrategy interface {
      do(int, int) int
    }
    
    // 策略实现:加
    type add struct{}
    
    func (*add) do(a, b int) int {
      return a + b
    }
    
    // 策略实现:减
    type reduce struct{}
    
    func (*reduce) do(a, b int) int {
      return a - b
    }
    
    // 具体策略的执行者
    type Operator struct {
      strategy IStrategy
    }
    
    // 设置策略
    func (operator *Operator) setStrategy(strategy IStrategy) {
      operator.strategy = strategy
    }
    
    // 调用策略中的方法
    func (operator *Operator) calculate(a, b int) int {
      return operator.strategy.do(a, b)
    }
    

    6. 模板模式

    模板模式就是将一个类中能够公共使用的方法放置在抽象类中实现,将不能公共使用的方法作为抽象方法,强制子类去实现,这样就做到了将一个类作为一个模板,让开发者去填充需要填充的地方。

    
    package template
    
    import "fmt"
    
    type Cooker interface {
      fire()
      cooke()
      outfire()
    }
    
    // 类似于一个抽象类
    type CookMenu struct {
    }
    
    func (CookMenu) fire() {
      fmt.Println("开火")
    }
    
    // 做菜,交给具体的子类实现
    func (CookMenu) cooke() {
    }
    
    func (CookMenu) outfire() {
      fmt.Println("关火")
    }
    
    // 封装具体步骤
    func doCook(cook Cooker) {
      cook.fire()
      cook.cooke()
      cook.outfire()
    }
    
    type XiHongShi struct {
      CookMenu
    }
    
    func (*XiHongShi) cooke() {
      fmt.Println("做西红柿")
    }
    
    type ChaoJiDan struct {
      CookMenu
    }
    
    func (ChaoJiDan) cooke() {
      fmt.Println("做炒鸡蛋")
    }
    

    7. 代理模式

    可以为另一个对象提供一个替身或者占位符,以控制对这个对象的访问。

    
    package proxy
    
    import "fmt"
    
    type Seller interface {
      sell(name string)
    }
    
    // 火车站
    type Station struct {
      stock int //库存
    }
    
    func (station *Station) sell(name string) {
      if station.stock > 0 {
        station.stock--
        fmt.Printf("代理点中:%s买了一张票,剩余:%d \n", name, station.stock)
      } else {
        fmt.Println("票已售空")
      }
    
    }
    
    // 火车代理点
    type StationProxy struct {
      station *Station // 持有一个火车站对象
    }
    
    func (proxy *StationProxy) sell(name string) {
      if proxy.station.stock > 0 {
        proxy.station.stock--
        fmt.Printf("代理点中:%s买了一张票,剩余:%d \n", name, proxy.station.stock)
      } else {
        fmt.Println("票已售空")
      }
    }
    

    8. 选项模式

    
    package options
    
    import (
      "time"
    )
    
    type Connection struct {
      addr    string
      cache   bool
      timeout time.Duration
    }
    
    const (
      defaultTimeout = 10
      defaultCaching = false
    )
    
    type options struct {
      timeout time.Duration
      caching bool
    }
    
    // Option overrides behavior of Connect.
    type Option interface {
      apply(*options)
    }
    
    type optionFunc func(*options)
    
    func (f optionFunc) apply(o *options) {
      f(o)
    }
    
    func WithTimeout(t time.Duration) Option {
      return optionFunc(func(o *options) {
        o.timeout = t
      })
    }
    
    func WithCaching(cache bool) Option {
      return optionFunc(func(o *options) {
        o.caching = cache
      })
    }
    
    // Connect creates a connection.
    func NewConnect(addr string, opts ...Option) (*Connection, error) {
      options := options{
        timeout: defaultTimeout,
        caching: defaultCaching,
      }
    
      for _, o := range opts {
        o.apply(&options)
      }
    
      return &Connection{
        addr:    addr,
        cache:   options.caching,
        timeout: options.timeout,
      }, nil
    }
    

    选项模式通常适用于以下场景:

    • 结构体参数很多,创建结构体时,我们期望创建一个携带默认值的结构体变量,并选择性修改其中一些参数的值。
    • 结构体参数经常变动,变动时我们又不想修改创建实例的函数。例如:结构体新增一个 retry 参数,但是又不想在 NewConnect 入参列表中添加retry int这样的参数声明。

    参考文章

    • Go 语言项目开发实战/设计模式

    相关文章

      网友评论

        本文标题:Go 常用的设计模式

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