GoF

98fb0ecb8ba65bc83f25bb2504e51d20

创建型模式

提供一种在创建对象的同时隐藏创建逻辑的方式,而不是直接使用 new 运算符直接实例化对象

单例模式

分为饿汉方式(包被加载时创建)和懒汉方式(第一次使用时创建)

饿汉方式

1
2
3
4
5
6
7
8
9
10
11
package hunger

type singleton struct {
}

// 实例是在包被导入时被初始化的
var ins *singleton = &singleton{}

func GetIns() *singleton {
return ins
}

懒汉方式

非并发安全,需要加锁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package singleton

import "sync"

type singleton struct {
}

var ins *singleton
var lock sync.Mutex

func GetIns() *singleton {
if ins == nil {
lock.Lock()
defer lock.Unlock()
if ins == nil {
ins = &singleton{}
}
}
return ins
}

once

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package singleton

import "sync"

type singleton struct {
}

var ins *singleton
var once sync.Once

func GetIns() *singleton {
once.Do(func() {
ins = &singleton{}
})
return ins
}

工厂模式

简单工厂模式

接受参数,然后返回实例(结构体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package factory

import "fmt"

type Person struct {
Name string
Age int
}

func (p Person) Greet() {
fmt.Printf("Hi! My name is %s\n", p.Name)
}

func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
}
}

抽象工厂模式

与简单工厂模式的区别:返回的是接口(不必公开内部实现细节),而不是结构体

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
package factory

import (
"fmt"
)

type Person interface {
Greet()
}

type person struct {
name string
age int
}

func (receiver *person) Greet() {
fmt.Printf("Hi! My name is %s\n", receiver.name)
}

// NewPerson returns an interface, and not the person struct itself
func NewPerson(name string, age int) Person {
return &person{
name: name,
age: age,
}
}

工厂方法模式

在简单工厂模式,依赖于唯一的工厂对象;在工厂模式中,依赖于工厂接口(通过子工厂解耦

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
package main

import "fmt"

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,
}
}
}

func main() {
babyFactory := NewPersonFactory(1)
baby := babyFactory("john")
fmt.Println(baby)

teenagerFactory := NewPersonFactory(16)
teenager := teenagerFactory("jill")
fmt.Println(teenager)
}

结构性模式

关注类和对象的组合

策略模式

定义了一组算法,并将每个算法都封装起来,并且使它们之间可以互换

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
package strategy

type Strategy interface {
do(int, int) int
}

type add struct {
}

func (receiver *add) do(a, b int) int {
return a + b
}

type reduce struct {
}

func (receiver *reduce) do(a, b int) int {
return a - b
}

type Operator struct {
strategy Strategy
}

func (receiver *Operator) setStrategy(strategy Strategy) {
receiver.strategy = strategy
}

func (receiver *Operator) calculate(a, b int) int {
return receiver.strategy.do(a, b)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package strategy

import (
"fmt"
"testing"
)

func TestStrategy(t *testing.T) {
operator := Operator{}

operator.setStrategy(&add{})
add := operator.calculate(1, 2)
fmt.Println("add: ", add)

operator.setStrategy(&reduce{})
reduce := operator.calculate(1, 2)
fmt.Println("reduce: ", reduce)
}

模板模式

定义了算法的骨架,然后将一些步骤延迟到子类

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
package template

import "fmt"

// Template
func programming(programmer Programmer) {
programmer.coding()
programmer.compile()
programmer.run()
}

type Programmer interface {
coding()
compile()
run()
}

type AbstractProgrammer struct {
}

func (AbstractProgrammer) compile() {
fmt.Println("compile")
}

func (AbstractProgrammer) run() {
fmt.Println("run")
}

type JavaProgrammer struct {
AbstractProgrammer // 通过匿名字段实现继承(类似)
}

func (*JavaProgrammer) coding() {
fmt.Println("coding java")
}

type GoProgrammer struct {
AbstractProgrammer
}

func (GoProgrammer) coding() {
fmt.Println("coding go")
}
1
2
3
4
5
6
7
8
9
10
11
package template

import "testing"

func TestTemplate(t *testing.T) {
javaProgrammer := &JavaProgrammer{}
programming(javaProgrammer)

goProgrammer := &GoProgrammer{}
programming(goProgrammer)
}

行为型模式

关注对象之间的通信

代理模式

为另一个对象提供替身,以控制对这个对象的访问;代理类中持有被代理类对象,并且与被代理类对象实现同一接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package proxy

import "fmt"

type Seller interface {
sell()
}

type Station struct {
}

func (*Station) sell() {
fmt.Println("Station sell")
}

type StationProxy struct {
station *Station
}

func (proxy *StationProxy) sell() {
proxy.station.sell()
}

选项模式

创建一个带有默认值struct 变量,并选择性地修改其中一些参数的值 – Go 不支持参数默认值

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
package option

import "time"

const (
defaultCaching = false
defaultTimeout = 10
)

type Connection struct {
addr string
cache bool
timeout time.Duration
}

type options struct {
caching bool
timeout time.Duration
}

// 实现很巧妙!
type Option interface {
apply(*options)
}

type optionFunc func(*options)

func (f optionFunc) apply(opts *options) {
f(opts)
}

func WithCaching(cache bool) Option {
return optionFunc(func(o *options) {
o.caching = cache
})
}

func WithTimeout(t time.Duration) Option {
return optionFunc(func(o *options) {
o.timeout = t
})
}

func Connect(addr string, opts ...Option) (*Connection, error) {
options := options{
caching: defaultCaching,
timeout: defaultTimeout,
}

// 动态修改 options
for _, option := range opts {
option.apply(&options)
}

return &Connection{
addr: addr,
cache: options.caching,
timeout: options.timeout,
}, nil
}