Go常用设计模式简记-创建型模式
创建型模式(Creational Patterns) 提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象
单例模式(Singleton Pattern)
常用场景:全局共享一个实例,且只需要被初始化一次的场景。例如数据库实例、全局配置、全局任务池等。
单例模式有利于减少内存开支、减少系统性能开销、防止多个实例产生冲突等优点。
饿汉模式
饿汉方式指全局的单例实例在包被加载时创建。
因为实例是在包被导入时初始化的,所以如果初始化耗时,会导致程序加载时间比较长。
package singleton
type singleton struct {
}
var ins *singleton= &singleton{}
// 懒汉模式
func GetIns() *singleton {
return ins
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
懒汉模式
懒汉方式指全局的单例实例在第一次被使用时创建。
非线程安全版
缺点:非线程安全。当正在创建时,有线程来访问此时ins = nil就会再创建,单例类就会有多个实例了。
package singleton
type singletona struct {}
var insa *singletona
// 懒汉模式-非线程安全
func GetInsa() *singletona {
if insa == nil {
insa = &singletona{}
}
return insa
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
加锁
虽然解决并发的问题,但每次加锁是要付出代价的,同时使用 defer
将导致锁变成函数级别的锁,其实只锁变量及其初始化就可以了。
package singleton
import "sync"
type singletond struct {
}
var insd *singletond
var mud sync.Mutex
// 懒汉模式加锁
func Getinsd() *singletond {
mud.Lock()
defer mud.Unlock()
if insd == nil {
insd = &singletond{}
}
return insd
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
双重检测
通过双重检测,避免了每次加锁,不用defer
,避免了函数级别的锁, 从而提高代码效率。
package singleton
import "sync"
type singletonb struct {
}
var insb *singletonb
var mu sync.Mutex
// 双重检测实现懒加载
func Getinsb() *singletonb {
if insb == nil {
mu.Lock()
if insb == nil{
insb = &singletonb{}
}
mu.Unlock()
}
return insb
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sync.Once实现
Golang 中特有方式,使用 sync.Once
以确保 ins 实例全局只被创建一次,once.Do
函数还可以确保当同时有多个创建动作时,只有一个创建动作在被执行
package singleton
import "sync"
type singletonc struct {
}
var insc *singletonc
var once sync.Once
// 使用once.Do可以确保 ins 实例全局只被创建一次,once.Do 函数还可以确保当同时有多个创建动作时,只有一个创建动作在被执行。
func GetInsc() *singletonc{
once.Do(func() {
insc = &singletonc{}
})
return insc
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
工厂模式
常用场景:
- 简单工厂模式可以传入参数并返回一个结构体的实例。
- 抽象工厂模式可以返回一个接口,通过返回接口,在不公开内部实现的情况下,让调用者使用你提供的各种功能。
- 工厂方法模式将对象创建从由一个对象负载所有具体类的实例化,变成由一群子类来负责对具体类的实例化,从而将过程解耦。
简单工厂模式
- 在简单工厂模式中,依赖于唯一的工厂对象,如果我们需要实例化一个产品,就要向工厂中传入一个参数,获取对应的对象;
- 如果要增加一种产品,就要在工厂中修改创建产品的函数。这会导致耦合性过高。
package main
import "fmt"
type Drink struct {
name string
size string
}
func (d Drink) DrinkInfo() {
fmt.Println("This drink is a %s - %s",d.size,d.name)
}
// 简单工厂
// 确保创建的实例具有需要的参数。
func NewDrink(name string, size string) *Drink {
return &Drink{
name: name,
size: size,
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
抽象工厂模式
- 抽象工厂,返回类型是接口,而不是具体结构体
- 通过返回接口,可以实现多个工厂函数,来返回不同的接口实现
- 简单工厂和抽象工厂返回实例对象时,都可以返回指针,也可以返回非指针的实例。
- 实际开发中建议返回非指针的实例。因为一般是想通过创建实例调用其提供的方法,而不是对实例做修改。
- 若想修改,可通过设置Setter方法实现.
- 通过返回非指针实例,可确保实例的属性,避免属性被意外/任意修改。
package main
import "fmt"
type Drink2 interface {
DrinkInfo2()
}
// 果汁结构体
type juice struct {
Name string
Size string
}
func (j juice) DrinkInfo2() {
fmt.Println("This drink is a %s - %s",j.Size,j.Name)
}
func NewJuice(name string,size string) Drink2 {
return juice{
Name: name,
Size: size,
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
工厂方法模式
针对简单工厂的实现导致耦合性过高的问题,我们就可以使用工厂方法模式。
- 在工厂方法模式中,依赖工厂函数,
- 可以通过实现工厂函数创建多种工厂,
- 将对象创建由一个对象负责所有具体类的实例化,变成由一群子类来负责对具体对象的实例化,从而将过程解耦。
package main
import "fmt"
type Drink3 struct {
name string
size string
}
func (d Drink3) DrinkInfo3() {
fmt.Printf("This drink is a %s - %s\n",d.size,d.name)
}
func NewDrinkFactory(size string) func(name string) Drink3 {
return func(name string) Drink3 {
return Drink3{
name: name,
size: size,
}
}
}
func main() {
// 大杯
newLarge := NewDrinkFactory("large")
largejuice :=newLarge("apple")
// 中杯
newMedium := NewDrinkFactory("medoim")
mediumJuice := newMedium("apple")
largejuice.DrinkInfo3()
mediumJuice.DrinkInfo3()
}
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
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
参考资料
预览
除特别注明外,本站所有文章均为 windcoder 原创,转载请注明出处来自: gochangyongshejimoshijianji-chuangjianxingmoshi
Loading comments...

预览
暂无数据