1. 单例模式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
package singleton import ( "sync" ) type singleton struct { } var ins *singleton var once sync.Once func GetInsOr() *singleton { once.Do(func() { ins = &singleton{} }) return ins } |
sync.Once 是 Golang package 中使方法只执行一次的对象实现,作用与 init 函数类似。但也有所不同。
init 函数是在文件包首次被加载的时候执行,且只执行一次
sync.Onc 是在代码运行中需要的时候执行,且只执行一次
当一个函数不希望程序在一开始的时候就被执行的时候,我们可以使用 sync.Once 。
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. 抽象工厂模式
它返回的是接口而不是结构体。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
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 这两个整数进行计算,根据条件的不同,需要执行不同的计算方式。为了解耦,需要使用策略模式,定义一些独立的类来封装不同的算法,每一个类封装一个具体的算法(即策略)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
|
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. 模板模式
模板模式就是将一个类中能够公共使用的方法放置在抽象类中实现,将不能公共使用的方法作为抽象方法,强制子类去实现,这样就做到了将一个类作为一个模板,让开发者去填充需要填充的地方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
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. 代理模式
可以为另一个对象提供一个替身或者占位符,以控制对这个对象的访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
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. 选项模式
选项模式通常适用于以下场景:
- 结构体参数很多,创建结构体时,我们期望创建一个携带默认值的结构体变量,并选择性修改其中一些参数的值。
- 结构体参数经常变动,变动时我们又不想修改创建实例的函数。例如:结构体新增一个 retry 参数,但是又不想在 NewConnect 入参列表中添加retry int这样的参数声明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
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 } |
注意选项模式代码,WithTimeout 和 WithCaching 函数的返回类型是 Option 接口,而不是 optionFunc 类型。这不是一个错误,因为 Option 接口是用于描述修改选项的方式,而不是具体的函数类型。通过返回 Option 接口类型,我们可以在 NewConnect 函数中以统一的方式应用这些选项。所以,尽管 WithTimeout 和 WithCaching 返回的是 optionFunc 类型的函数,实际上它们是 Option 接口的实现。这使得我们可以将它们作为 Option 类型的参数传递给 NewConnect 函数,并在其中应用相应的选项。
不只是结构体类型,任何自定义类型都可以实现接口。
在 Go 语言中,接口是一种描述对象行为的类型。接口定义了一组方法的集合,任何类型只要实现了接口中定义的所有方法,就被认为是该接口的实现。
选项模式AI给出更简便的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
|
package main import ( "fmt" ) // Config 是我们的配置结构体 type Config struct { Host string Port int UseSSL bool } // Option 是一个函数类型,用于设置 Config 的选项 type Option func(*Config) // WithHost 设置主机名 func WithHost(host string) Option { return func(c *Config) { c.Host = host } } // WithPort 设置端口 func WithPort(port int) Option { return func(c *Config) { c.Port = port } } // WithSSL 设置是否使用 SSL func WithSSL(useSSL bool) Option { return func(c *Config) { c.UseSSL = useSSL } } // NewConfig 创建一个新的 Config 实例,接受多个选项 func NewConfig(options ...Option) *Config { // 创建一个默认配置 config := &Config{ Host: "localhost", Port: 8080, UseSSL: false, } // 应用所有选项 for _, option := range options { option(config) } return config } func main() { // 使用选项模式创建配置 config := NewConfig( WithHost("example.com"), WithPort(443), WithSSL(true), ) fmt.Printf("Config: %+v\n", config) } |
作者:潘晓华Michael
链接:https://www.jianshu.com/p/6eb74bfbd331
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
在go语言中,type可以定义任何自定义的类型
比如熟悉的:type dog struct{},type myInt int 等等
所以func也是可以作为类型自定义的,type myFunc func(int) int,意思是自定义了一个叫myFunc的函数类型,这个函数的签名必须符合输入为int,输出为int...把为什么自定义类型的原因也详细说明了一下。链接:https://blog.csdn.net/hjxisking/article/details/107469429
111111
「三年博客,如果觉得我的文章对您有用,请帮助本站成长」
共有 0 - Go 常用的设计模式