设计模式 Golang实现-《研磨设计模式》读书笔记
MIT License
7017
196
1804

Hi,我想 pr 设计模式中部分示例,新的示例有

  • 结合现实的例子。
  • 简洁明确的命名。
  • 注释中预输出结果。
  • Readme.md 中说明示例。

举一个例子,工厂方法模式。它将存在 IGun.go \ gun.go \ ak47.go \ musket.go \ gunFactory.go \ output.txt \ factorymethod_test.go
🎉 没错,这是一个兵工厂。如果认为不错,那我将开始这个计划,当然!如果您希望维持现状,这也没关系~

作者您好,您这个repo似乎只有《研磨设计模式》中提到的设计模式,我是否能增加一些其他设计模式的go实现并提交pull request呢?还是说在自己的repo中引用您的repo?

给出的demo代码的确能跑通,但是利用sync.Once.Do()方法实现线程安全的话,会导致整个go进程中只能创建这一种单例
如果我想创建多个用处不同的单例的话,会导致后面的都没法成功

想了两种优化的方案

  1. 每次都先加线程锁,再判断实例
package singleton

import (
	"sync"
)

// Singleton 是单例模式接口,导出的
// 通过该接口可以避免 GetInstance 返回一个包私有类型的指针
type Singleton interface {
	foo()
}

// singleton 是单例模式类,包私有的
type singleton struct{}

func (s singleton) foo() {}

var (
	instance  *singleton
	instance2 *singleton2
	mu        sync.Mutex
)

//GetInstance 用于获取单例模式对象
func GetInstance() Singleton {
	mu.Lock()
	defer mu.Unlock()
	if instance == nil {
		instance = &singleton{}
	}

	return instance
}

type singleton2 struct {
}

func (s2 singleton2) foo() {}
func GetInstance2() Singleton {
	mu.Lock()
	defer mu.Unlock()
	if instance2 == nil {
		instance2 = &singleton2{}
	}
	return instance2
}

  1. 每次先用sync/atomic判断,再加锁判断实例
package singleton

import (
	"sync"
	"sync/atomic"
)

// Singleton 是单例模式接口,导出的
// 通过该接口可以避免 GetInstance 返回一个包私有类型的指针
type Singleton2 interface {
	foo()
}

// singleton 是单例模式类,包私有的
type singleton21 struct{}

func (s singleton21) foo() {}

var (
	instance21       *singleton21
	instance22       *singleton22
	initInstanceCnt  uint32
	initInstanceCnt2 uint32
	mu               sync.Mutex
)

//GetInstance 用于获取单例模式对象
func GetInstance21() Singleton2 {
	if atomic.LoadUint32(&initInstanceCnt) == 1 {
		return instance21
	}

	mu.Lock()
	defer mu.Unlock()

	if initInstanceCnt == 0 {
		instance21 = &singleton21{}
		atomic.StoreUint32(&initInstanceCnt, 1)
	}
	return instance21
}

type singleton22 struct {
}

func (s2 singleton22) foo() {}
func GetInstance22() Singleton {
	if atomic.LoadUint32(&initInstanceCnt2) == 1 {
		return instance22
	}

	mu.Lock()
	defer mu.Unlock()

	if initInstanceCnt2 == 0 {
		instance22 = &singleton22{}
		atomic.StoreUint32(&initInstanceCnt2, 1)
	}
	return instance22
}

package singleton

import "sync"

//Singleton 是单例模式类
type Singleton struct{}

var singleton *Singleton
var once sync.Once

//GetInstance 用于获取单例模式对象
func GetInstance() *Singleton {
	once.Do(func() {
		singleton = &Singleton{}
	})

	return singleton
}

=>

package singleton

import "sync"

//Singleton 是单例模式类
type singleton struct{}

var singleton *singleton
var once sync.Once

//GetInstance 用于获取单例模式对象
func GetInstance() *singleton {
	once.Do(func() {
		singleton = &singleton{}
	})

	return singleton
}

观察者模式中,observe.go手误拼错了

golang-design-pattern/10_observer/obserser.go
观察者模式的文件名打错了~

比方说我们已经有了一个fib函数
https://play.golang.org/p/hYerZ2fv0dT

现在我想要在不修改源代码的前提下, 增加一个counter 装饰器

目的是统计fib调用了多少次. 因为里面有递归, 看起来go就解决不了了.

//facade implement type apiImpl struct { a AModuleAPI b BModuleAPI }
为什么在这里包含接口而不是struct?

design pattern 21 chain_of_responsibility, implements is not right at all

func GetInstance() *Singleton {
	if singletonInst == nil {
		// 多个线程进入这里会造成死锁
		singletonInstLock.Lock()
		if singletonInst == nil {
			singletonInst = &Singleton{}
		}
		// 应该在此处UnLock
	}
	return singletonInst
}

`
type InterA interface {
DoA()
}

type classA struct{}

func (a classA) DoA() {
fmt.Println("do a thing")
}

func OutDoDo(a InterA) {
a.DoA()
}

// code above is original function. now you want OutDoDO do what classB do, so adapter works

type classB struct{}

func (b classB) DoB() {
fmt.Println("do b thing")
}

type adapter1 struct{}

func (ad adapter1) DoA() {
b := classB{}
b.DoB()
}

// test
func TestAdapterOutDoDo(t *testing.T) {
ad := adapter1{}
OutDoDo(ad)
}
`