Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
colinrs committed Nov 17, 2019
0 parents commit d5646c8
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 0 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# go-patterns-cn

|名称|是否实现|
|-----|-----|
|观察者模式|是|
|策略模式||
|模板方法模式||


112 changes: 112 additions & 0 deletions observer_pattern.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# 观察者模式

## 概念

观察者模式允许类型实例将事件“发布”到希望在发生特定事件时进行更新通知其他类型实例(“观察者”)

## 使用观察者模式的场景和优缺点

### 使用场景

关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
事件多级触发场景。
跨系统的消息交换场景,如消息队列、事件总线的处理机制。

#### 优点

- 解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。

#### 缺点

- 在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,如果一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

## 代码实现

```golang

package main

import (
"fmt"
"time"
)

// Event 消息
type Event struct {
Data int64
}

// Observer 观察者,观察特定的消息
type Observer interface {
// 消息变动通知观察者
OnNotify(Event)
}

// Notifier 被观察的对象
type Notifier interface {

// Register 注册观察者
Register(Observer)
// Deregister 删除观察者
Deregister(Observer)
// Notify 消息通知
Notify(Event)
}

// eventObserver Observer 实现
type eventObserver struct {
id int
}

// eventNotifier Notifier 实现
type eventNotifier struct {
// 用map来存放Observer
observers map[Observer]struct{}
}

// OnNotify 收到消息变动
func (o *eventObserver) OnNotify(e Event) {
fmt.Printf("*** 观察者 %d 接受到变动的消息: %d\n", o.id, e.Data)
}

// Register ...
func (o *eventNotifier) Register(l Observer) {
o.observers[l] = struct{}{}
}

// Deregister ...
func (o *eventNotifier) Deregister(l Observer) {
delete(o.observers, l)
}

// Notify 把变化的消息发送给所有的观察者
func (o *eventNotifier) Notify(e Event) {
for i := range o.observers {
i.OnNotify(e)
}
}

func main() {
// 初始化
n := eventNotifier{
observers: map[Observer]struct{}{},
}

// 注册两个观察者
n.Register(&eventObserver{id: 1})
n.Register(&eventObserver{id: 2})

// 消息通知
stop := time.NewTimer(10 * time.Second).C
tick := time.NewTicker(time.Second).C
for {
select {
case <-stop:
return
case t := <-tick:
n.Notify(Event{Data: t.Unix()})
}
}
}

```
86 changes: 86 additions & 0 deletions strategy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# 策略模式

## 概念

- 定义一系列算法,让这些算法在运行时可以互换,使得分离算法,符合开闭原则

## 模式的场景和优缺点

### 使用场景

- 在有多种算法相似的情况下,使用 ```if...else``` 所带来的复杂和难以维护。
- 一个系统有许多许多类,而区分它们的只是他们直接的行为。


#### 策略模式优点

- 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。
- 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
- 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
- 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
- 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

#### 策略模式缺点

- 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
- 策略模式造成很多的策略类。

## 代码实现

```golang

package main

import "fmt"

// Operator ...
type Operator interface {
Apply(int, int) int
}

// Operation 包装器
type Operation struct {
Operator Operator
}

// Addition ...
type Addition struct{}

// Apply ...
func (add *Addition) Apply(left, right int) int {
return left + right
}

// Multiplication ...
type Multiplication struct{}

// Apply ...
func (mu *Multiplication) Apply(left, right int) int {
return left * right
}

// Operate ...
func (o *Operation) Operate(leftValue, rightValue int) int {
return o.Operator.Apply(leftValue, rightValue)
}

// CreateOpration ...
func CreateOpration(operator Operator) Operation {
return Operation{operator}
}

func main() {
var operationes []Operation
operatorAdd := CreateOpration(new(Addition))
operatorMul := CreateOpration(new(Multiplication))
operationes = append(operationes, operatorAdd)
operationes = append(operationes, operatorMul)
for _, operator := range operationes {
value := operator.Operate(1, 2)
fmt.Printf("%d\n", value)
}
}



```
92 changes: 92 additions & 0 deletions template_method.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# 模板方法模式模式

## 概念

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

## 模板方法模式模式的场景和优缺点

### 使用场景

- 有多个子类共有的方法,且逻辑相同
- 重要的、复杂的方法,可以考虑作为模板方法

#### 优点

- 封装不变部分,扩展可变部分
- 提取公共代码,便于维护
- 行为由父类控制,子类实现

#### 缺点

- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大

## 代码实现

```golang
package main

import "fmt"

// Thing 定义接口
type Thing interface {
SetName(name string)
BeforeAction()
Exit()
}

// Person ...
type Person struct {
name string
Concrete Thing
}

// SetName ...
func (p *Person) SetName(name string) {
p.name = name
}

// BeforeAction ...
func (p *Person) BeforeAction() {
//
p.Concrete.BeforeAction()
}

// Exit ...
func (p *Person) Exit() {
p.BeforeAction()
fmt.Println(p.name + "exit")
}

// Boy ...
type Boy struct {
Person //匿名组合实现继承
}

// BeforeAction ...
func (b *Boy) BeforeAction() {
fmt.Println(b.name)
}

// Girl ...
type Girl struct {
Person //匿名组合实现继承
}

// BeforeAction ...
func (g *Girl) BeforeAction() {
fmt.Println(g.name)
}

func main() {
boy := &Boy{}
person := new(Person)
person.SetName("boy")
person.Concrete = boy
//赋值boy的内容, 注意要在设定了person具体值之后赋值,否则为空
boy.Person = *person
person.Exit()
}


```

0 comments on commit d5646c8

Please sign in to comment.