设计模式一般遵守 “开放封闭” 原则,即对拓展开放,对修改封闭。
单例模式 Singleton Pattern
保证一个类只有一个实例,并提供全局调用。它是最简单的设计模式,也是少有的违反 “开放封闭” 的模式。常用实例:数据库读写工具类、配置文件读取
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
|
type SingleTon struct{}
var mu sync.Mutex
var instance *SingleTon
func getInstance() *SingleTon {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &SingleTon{}
}
return instance
}
func getInstance2() *SingleTon {
if instance == nil {
mu.Lock()
if instance == nil {
instance = &SingleTon{}
}
mu.Unlock()
}
return instance
}
var once sync.Once
func getInstance3() *SingleTon {
once.Do(func() {
instance = &SingleTon{}
})
return instance
}
|
Adapter模式
Adapter模式 是将一个类的接口转换成另一个类所期待的接口,使两个因为接口不兼容而不能一起工作的两个类能够一起工作。一言蔽之:使新的类重用旧的类使用的接口。其实就是用adapter类代理新的类工作。
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
|
func main() {
duck := &MallardDuck{} // 接口方法集
turkey := &WildTurkey{}
turkeyAdapter := &TurkeyAdatper{turkey: turkey}
fmt.Println("The Turkey says...")
turkey.gobble()
turkey.fly()
fmt.Println("The Duck says...")
testDuck(duck)
fmt.Println("The Turkey dapter says...")
testDuck(turkeyAdapter)
}
// turkey通过adapter代理也可以使用testDuck接口
func testDuck(duck Duck) {
duck.quack()
duck.fly()
}
type Duck interface {
quack()
fly()
}
type MallardDuck struct {
}
func (d *MallardDuck) quack() {
fmt.Println("Quack")
}
func (d *MallardDuck) fly() {
fmt.Println("I am flying")
}
type Turkey interface {
gobble()
fly()
}
type WildTurkey struct {
}
func (t *WildTurkey) gobble() {
fmt.Println("Gobble gobble")
}
func (t *WildTurkey) fly() {
fmt.Println("I am flying a short distance")
}
type TurkeyAdatper struct {
turkey Turkey
}
func (a *TurkeyAdatper) quack() {
a.turkey.gobble()
}
func (a *TurkeyAdatper) fly() {
a.turkey.fly()
}
|
当然adapter也可以使功能更容易扩展,如Adapter模式在android里有一个最典型的用例是 RecycleView或Listview的adapter,有了adapter模式,android开发者可以自定义各种list view。哈哈,这不就是遵守了"开放"原则吗。
Decorator模式
Decorator模式允许往一个对象里增加功能,提供了灵活拓展功能
实例:打印咖啡订单
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
|
func decorate(beverage Beverage, ds ...Decorator) Beverage {
for _, decorate := range ds {
beverage = decorate(beverage)
}
return beverage
}
type Decorator func(Beverage) Beverage
type Beverage func() (string, float64)
func main() {
beverage := func() (name string, cost float64) {
name = "Soy"
cost = 1.44
return
}
mocha := func(beverage Beverage) Beverage {
return func() (string, float64) {
name, cost := beverage()
return name + " Mocha", cost + 1.19
}
}
whip := func(beverage Beverage) Beverage {
return func() (string, float64) {
name, cost := beverage()
return name + " Whip", cost + 0.99
}
}
beverage = decorate(beverage, mocha, mocha, whip)
fmt.Println(beverage())
}
|
运行结果
1
2
|
$ go run decorator.go
Soy Mocha Mocha Whip 4.81
|
Decorator模式使得增加中间件功能更加容易灵活,如 NSQ 的 http_api,
1
2
3
4
5
6
7
8
9
10
11
12
|
router.Handle("POST", "/topic/create", http_api.Decorate(s.doCreateTopic, log, http_api.V1))
func Decorate(f APIHandler, ds ...Decorator) httprouter.Handle {
decorated := f
for _, decorate := range ds {
decorated = decorate(decorated)
}
return func(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
decorated(w, req, ps)
}
}
type Decorator func(APIHandler) APIHandler
type APIHandler func(http.ResponseWriter, *http.Request, httprouter.Params) (interface{}, error)
|
观察者模式 Observer Pattern
Publishers + Subscribers = Observer Pattern
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
65
66
|
func main() {
weatherData := &WeatherData{
observers: []Observer{},
}
currentConditionsDisplay := &CurrentConditionsDisplay{}
weatherData.registerObserver(currentConditionsDisplay)
weatherData.set(80, 65, 30.4)
weatherData.set(82, 70, 29.2)
weatherData.set(78, 90, 29.2)
}
type Observer interface {
update(temperature float64, humidity float64, pressure float64)
}
type Subject interface {
registerObserver(Observer)
removeObserver(Observer)
notifyObservers()
}
type WeatherData struct {
temperature float64
humidity float64
pressure float64
observers []Observer
}
func (w *WeatherData) registerObserver(o Observer) {
w.observers = append(w.observers, o)
}
func (w *WeatherData) removeObserver(o Observer) {
for i, observer := range w.observers {
if observer == o {
lastIndex := len(w.observers) - 1
w.observers[i], w.observers[lastIndex] = w.observers[lastIndex], w.observers[i]
w.observers = w.observers[:lastIndex]
break
}
}
}
func (w *WeatherData) set(temperature float64, humidity float64, pressure float64) {
w.temperature = temperature
w.humidity = humidity
w.pressure = pressure
w.notifyObservers()
}
func (w *WeatherData) notifyObservers() {
for _, o := range w.observers {
o.update(w.temperature, w.humidity, w.pressure)
}
}
type CurrentConditionsDisplay struct {
temperature float64
humidity float64
pressure float64
}
func (d *CurrentConditionsDisplay) update(temperature float64, humidity float64, pressure float64) {
d.temperature = temperature
d.humidity = humidity
d.pressure = pressure
fmt.Println("Current conditions: ", d.temperature, "F degrees ", d.humidity, "% humidity")
}
|
运行结果
1
2
3
4
|
$ go run observer.go
Current conditions: 80 F degrees 65 % humidity
Current conditions: 82 F degrees 70 % humidity
Current conditions: 78 F degrees 90 % humidity
|
参考
《head first design patterns》