Repository: senghoo/golang-design-pattern
Branch: master
Commit: e9d687a5411f
Files: 75
Total size: 39.2 KB
Directory structure:
gitextract_hshruwzb/
├── .gitignore
├── .travis.yml
├── 00_simple_factory/
│ ├── README.md
│ ├── simple.go
│ └── simple_test.go
├── 01_facade/
│ ├── README.md
│ ├── facade.go
│ └── facade_test.go
├── 02_adapter/
│ ├── README.md
│ ├── adapter.go
│ └── adapter_test.go
├── 03_singleton/
│ ├── README.md
│ ├── singleton.go
│ └── singleton_test.go
├── 04_factory_method/
│ ├── README.md
│ ├── factorymethod.go
│ └── factorymethod_test.go
├── 05_abstract_factory/
│ ├── README.md
│ ├── abstractfactory.go
│ └── abstractfactory_test.go
├── 06_builder/
│ ├── builder.go
│ └── builder_test.go
├── 07_prototype/
│ ├── README.md
│ ├── prototype.go
│ └── prototype_test.go
├── 08_mediator/
│ ├── README.md
│ ├── mediator.go
│ └── mediator_test.go
├── 09_proxy/
│ ├── README.md
│ ├── proxy.go
│ └── proxy_test.go
├── 10_observer/
│ ├── README.md
│ ├── observer.go
│ └── observer_test.go
├── 11_command/
│ ├── README.md
│ ├── command.go
│ └── command_test.go
├── 12_iterator/
│ ├── README.md
│ ├── iterator.go
│ └── iterator_test.go
├── 13_composite/
│ ├── README.md
│ ├── composite.go
│ └── composite_test.go
├── 14_template_method/
│ ├── README.md
│ ├── templatemethod.go
│ └── templatemethod_test.go
├── 15_strategy/
│ ├── README.md
│ ├── strategy.go
│ └── strategy_test.go
├── 16_state/
│ ├── README.md
│ ├── state.go
│ └── state_test.go
├── 17_memento/
│ ├── README.md
│ ├── memento.go
│ └── memento_test.go
├── 18_flyweight/
│ ├── README.md
│ ├── flyweight.go
│ └── flyweight_test.go
├── 19_interpreter/
│ ├── README.md
│ ├── interpreter.go
│ └── interpreter_test.go
├── 20_decorator/
│ ├── README.md
│ ├── decorator.go
│ └── decorator_test.go
├── 21_chain_of_responsibility/
│ ├── README.md
│ ├── chain.go
│ └── chain_test.go
├── 22_bridge/
│ ├── README.md
│ ├── bridge.go
│ └── bridge_test.go
├── 23_visitor/
│ ├── README.md
│ ├── visitor.go
│ └── visitor_test.go
├── LICENSE
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
### https://raw.github.com/github/gitignore/23aad6abc4ed1aafb425f6e09334c4e35ad146ac/Global/Emacs.gitignore
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
### https://raw.github.com/github/gitignore/23aad6abc4ed1aafb425f6e09334c4e35ad146ac/Go.gitignore
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
.idea
================================================
FILE: .travis.yml
================================================
language: go
go:
- 1.x
- 1.11.x
script:
- go test -v ./...
================================================
FILE: 00_simple_factory/README.md
================================================
# 简单工厂模式
`go` 语言没有构造函数一说,所以一般会定义 `NewXXX` 函数来初始化相关类。
`NewXXX` 函数返回接口时就是简单工厂模式,也就是说 `Golang` 的一般推荐做法就是简单工厂。
在这个 `simplefactory` 包中只有API 接口和 `NewAPI` 函数为包外可见,封装了实现细节。
================================================
FILE: 00_simple_factory/simple.go
================================================
package simplefactory
import "fmt"
// API is interface
type API interface {
Say(name string) string
}
// NewAPI return Api instance by type
func NewAPI(t int) API {
if t == 1 {
return &hiAPI{}
} else if t == 2 {
return &helloAPI{}
}
return nil
}
// hiAPI is one of API implement
type hiAPI struct{}
// Say hi to name
func (*hiAPI) Say(name string) string {
return fmt.Sprintf("Hi, %s", name)
}
// helloAPI is another API implement
type helloAPI struct{}
// Say hello to name
func (*helloAPI) Say(name string) string {
return fmt.Sprintf("Hello, %s", name)
}
================================================
FILE: 00_simple_factory/simple_test.go
================================================
package simplefactory
import "testing"
// TestType1 test get hiapi with factory
func TestType1(t *testing.T) {
api := NewAPI(1)
s := api.Say("Tom")
if s != "Hi, Tom" {
t.Fatal("Type1 test fail")
}
}
func TestType2(t *testing.T) {
api := NewAPI(2)
s := api.Say("Tom")
if s != "Hello, Tom" {
t.Fatal("Type2 test fail")
}
}
================================================
FILE: 01_facade/README.md
================================================
# 外观模式
`API` 为 `facade` 模块的外观接口,大部分代码使用此接口简化对 `facade` 类的访问。
`facade` 模块同时暴露了 `a` 和 `b` 两个 `Module` 的 `NewXXX` 和 `interface`,其它代码如果需要使用细节功能时可以直接调用。
================================================
FILE: 01_facade/facade.go
================================================
package facade
import "fmt"
func NewAPI() API {
return &apiImpl{
a: NewAModuleAPI(),
b: NewBModuleAPI(),
}
}
// API is facade interface of facade package
type API interface {
Test() string
}
// apiImpl facade implement
type apiImpl struct {
a AModuleAPI
b BModuleAPI
}
func (a *apiImpl) Test() string {
aRet := a.a.TestA()
bRet := a.b.TestB()
return fmt.Sprintf("%s\n%s", aRet, bRet)
}
// NewAModuleAPI return new AModuleAPI
func NewAModuleAPI() AModuleAPI {
return &aModuleImpl{}
}
// AModuleAPI ...
type AModuleAPI interface {
TestA() string
}
type aModuleImpl struct{}
func (*aModuleImpl) TestA() string {
return "A module running"
}
// NewBModuleAPI return new BModuleAPI
func NewBModuleAPI() BModuleAPI {
return &bModuleImpl{}
}
// BModuleAPI ...
type BModuleAPI interface {
TestB() string
}
type bModuleImpl struct{}
func (*bModuleImpl) TestB() string {
return "B module running"
}
================================================
FILE: 01_facade/facade_test.go
================================================
package facade
import "testing"
var expect = "A module running\nB module running"
// TestFacadeAPI ...
func TestFacadeAPI(t *testing.T) {
api := NewAPI()
ret := api.Test()
if ret != expect {
t.Fatalf("expect %s, return %s", expect, ret)
}
}
================================================
FILE: 02_adapter/README.md
================================================
# 适配器模式
适配器模式用于转换一种接口适配另一种接口。
实际使用中 `Adaptee` 一般为接口,并且使用工厂函数生成实例。
在 `Adapter` 中匿名组合 `Adaptee` 接口,所以 `Adapter` 类也拥有 `SpecificRequest` 实例方法,又因为 `Go` 语言中非入侵式接口特征,其实 `Adapter` 也适配 `Adaptee`
接口。
================================================
FILE: 02_adapter/adapter.go
================================================
package adapter
// Target 是适配的目标接口
type Target interface {
Request() string
}
// Adaptee 是被适配的目标接口
type Adaptee interface {
SpecificRequest() string
}
// NewAdaptee 是被适配接口的工厂函数
func NewAdaptee() Adaptee {
return &adapteeImpl{}
}
// AdapteeImpl 是被适配的目标类
type adapteeImpl struct{}
// SpecificRequest 是目标类的一个方法
func (*adapteeImpl) SpecificRequest() string {
return "adaptee method"
}
// NewAdapter 是Adapter的工厂函数
func NewAdapter(adaptee Adaptee) Target {
return &adapter{
Adaptee: adaptee,
}
}
// Adapter 是转换Adaptee为Target接口的适配器
type adapter struct {
Adaptee
}
// Request 实现Target接口
func (a *adapter) Request() string {
return a.SpecificRequest()
}
================================================
FILE: 02_adapter/adapter_test.go
================================================
package adapter
import "testing"
var expect = "adaptee method"
func TestAdapter(t *testing.T) {
adaptee := NewAdaptee()
target := NewAdapter(adaptee)
res := target.Request()
if res != expect {
t.Fatalf("expect: %s, actual: %s", expect, res)
}
}
================================================
FILE: 03_singleton/README.md
================================================
# 单例模式
使用懒惰模式的单例模式,使用双重检查加锁保证线程安全
================================================
FILE: 03_singleton/singleton.go
================================================
package singleton
import "sync"
// Singleton 是单例模式接口,导出的
// 通过该接口可以避免 GetInstance 返回一个包私有类型的指针
type Singleton interface {
foo()
}
// singleton 是单例模式类,包私有的
type singleton struct{}
func (s singleton) foo() {}
var (
instance *singleton
once sync.Once
)
// GetInstance 用于获取单例模式对象
func GetInstance() Singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}
================================================
FILE: 03_singleton/singleton_test.go
================================================
package singleton
import (
"sync"
"testing"
)
const parCount = 100
func TestSingleton(t *testing.T) {
ins1 := GetInstance()
ins2 := GetInstance()
if ins1 != ins2 {
t.Fatal("instance is not equal")
}
}
func TestParallelSingleton(t *testing.T) {
start := make(chan struct{})
wg := sync.WaitGroup{}
wg.Add(parCount)
instances := [parCount]Singleton{}
for i := 0; i < parCount; i++ {
go func(index int) {
// 协程阻塞,等待channel被关闭才能继续运行
<-start
instances[index] = GetInstance()
wg.Done()
}(i)
}
// 关闭channel,所有协程同时开始运行,实现并行(parallel)
close(start)
wg.Wait()
for i := 1; i < parCount; i++ {
if instances[i] != instances[i-1] {
t.Fatal("instance is not equal")
}
}
}
================================================
FILE: 04_factory_method/README.md
================================================
# 工厂方法模式
工厂方法模式使用子类的方式延迟生成对象到子类中实现。
`Go` 中不存在继承 所以使用匿名组合来实现
================================================
FILE: 04_factory_method/factorymethod.go
================================================
package factorymethod
// Operator 是被封装的实际类接口
type Operator interface {
SetA(int)
SetB(int)
Result() int
}
// OperatorFactory 是工厂接口
type OperatorFactory interface {
Create() Operator
}
// OperatorBase 是Operator 接口实现的基类,封装公用方法
type OperatorBase struct {
a, b int
}
// SetA 设置 A
func (o *OperatorBase) SetA(a int) {
o.a = a
}
// SetB 设置 B
func (o *OperatorBase) SetB(b int) {
o.b = b
}
// PlusOperatorFactory 是 PlusOperator 的工厂类
type PlusOperatorFactory struct{}
func (PlusOperatorFactory) Create() Operator {
return &PlusOperator{
OperatorBase: &OperatorBase{},
}
}
// PlusOperator Operator 的实际加法实现
type PlusOperator struct {
*OperatorBase
}
// Result 获取结果
func (o PlusOperator) Result() int {
return o.a + o.b
}
// MinusOperatorFactory 是 MinusOperator 的工厂类
type MinusOperatorFactory struct{}
func (MinusOperatorFactory) Create() Operator {
return &MinusOperator{
OperatorBase: &OperatorBase{},
}
}
// MinusOperator Operator 的实际减法实现
type MinusOperator struct {
*OperatorBase
}
// Result 获取结果
func (o MinusOperator) Result() int {
return o.a - o.b
}
================================================
FILE: 04_factory_method/factorymethod_test.go
================================================
package factorymethod
import "testing"
func compute(factory OperatorFactory, a, b int) int {
op := factory.Create()
op.SetA(a)
op.SetB(b)
return op.Result()
}
func TestOperator(t *testing.T) {
var (
factory OperatorFactory
)
factory = PlusOperatorFactory{}
if compute(factory, 1, 2) != 3 {
t.Fatal("error with factory method pattern")
}
factory = MinusOperatorFactory{}
if compute(factory, 4, 2) != 2 {
t.Fatal("error with factory method pattern")
}
}
================================================
FILE: 05_abstract_factory/README.md
================================================
# 抽象工厂模式
抽象工厂模式用于生成产品族的工厂,所生成的对象是有关联的。
如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。
比如本例子中使用 `RDB` 和 `XML` 存储订单信息,抽象工厂分别能生成相关的主订单信息和订单详情信息。 如果业务逻辑中需要替换使用的时候只需要改动工厂函数相关的类就能替换使用不同的存储方式了。
================================================
FILE: 05_abstract_factory/abstractfactory.go
================================================
package abstractfactory
import "fmt"
// OrderMainDAO 为订单主记录
type OrderMainDAO interface {
SaveOrderMain()
}
// OrderDetailDAO 为订单详情纪录
type OrderDetailDAO interface {
SaveOrderDetail()
}
// DAOFactory DAO 抽象模式工厂接口
type DAOFactory interface {
CreateOrderMainDAO() OrderMainDAO
CreateOrderDetailDAO() OrderDetailDAO
}
// RDBMainDAO 关系型数据库的OrderMainDAO实现
type RDBMainDAO struct{}
// SaveOrderMain ...
func (*RDBMainDAO) SaveOrderMain() {
fmt.Print("rdb main save\n")
}
// RDBDetailDAO 为关系型数据库的OrderDetailDAO实现
type RDBDetailDAO struct{}
// SaveOrderDetail ...
func (*RDBDetailDAO) SaveOrderDetail() {
fmt.Print("rdb detail save\n")
}
// RDBDAOFactory 是RDB 抽象工厂实现
type RDBDAOFactory struct{}
func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {
return &RDBMainDAO{}
}
func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
return &RDBDetailDAO{}
}
// XMLMainDAO XML存储
type XMLMainDAO struct{}
// SaveOrderMain ...
func (*XMLMainDAO) SaveOrderMain() {
fmt.Print("xml main save\n")
}
// XMLDetailDAO XML存储
type XMLDetailDAO struct{}
// SaveOrderDetail ...
func (*XMLDetailDAO) SaveOrderDetail() {
fmt.Print("xml detail save")
}
// XMLDAOFactory 是XML 抽象工厂实现
type XMLDAOFactory struct{}
func (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO {
return &XMLMainDAO{}
}
func (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
return &XMLDetailDAO{}
}
================================================
FILE: 05_abstract_factory/abstractfactory_test.go
================================================
package abstractfactory
func getMainAndDetail(factory DAOFactory) {
factory.CreateOrderMainDAO().SaveOrderMain()
factory.CreateOrderDetailDAO().SaveOrderDetail()
}
func ExampleRdbFactory() {
var factory DAOFactory
factory = &RDBDAOFactory{}
getMainAndDetail(factory)
// Output:
// rdb main save
// rdb detail save
}
func ExampleXmlFactory() {
var factory DAOFactory
factory = &XMLDAOFactory{}
getMainAndDetail(factory)
// Output:
// xml main save
// xml detail save
}
================================================
FILE: 06_builder/builder.go
================================================
package builder
// Builder 是生成器接口
type Builder interface {
Part1()
Part2()
Part3()
}
type Director struct {
builder Builder
}
// NewDirector ...
func NewDirector(builder Builder) *Director {
return &Director{
builder: builder,
}
}
// Construct Product
func (d *Director) Construct() {
d.builder.Part1()
d.builder.Part2()
d.builder.Part3()
}
type Builder1 struct {
result string
}
func (b *Builder1) Part1() {
b.result += "1"
}
func (b *Builder1) Part2() {
b.result += "2"
}
func (b *Builder1) Part3() {
b.result += "3"
}
func (b *Builder1) GetResult() string {
return b.result
}
type Builder2 struct {
result int
}
func (b *Builder2) Part1() {
b.result += 1
}
func (b *Builder2) Part2() {
b.result += 2
}
func (b *Builder2) Part3() {
b.result += 3
}
func (b *Builder2) GetResult() int {
return b.result
}
================================================
FILE: 06_builder/builder_test.go
================================================
package builder
import "testing"
func TestBuilder1(t *testing.T) {
builder := &Builder1{}
director := NewDirector(builder)
director.Construct()
res := builder.GetResult()
if res != "123" {
t.Fatalf("Builder1 fail expect 123 acture %s", res)
}
}
func TestBuilder2(t *testing.T) {
builder := &Builder2{}
director := NewDirector(builder)
director.Construct()
res := builder.GetResult()
if res != 6 {
t.Fatalf("Builder2 fail expect 6 acture %d", res)
}
}
================================================
FILE: 07_prototype/README.md
================================================
# 原型模式
原型模式使对象能复制自身,并且暴露到接口中,使客户端面向接口编程时,不知道接口实际对象的情况下生成新的对象。
原型模式配合原型管理器使用,使得客户端在不知道具体类的情况下,通过接口管理器得到新的实例,并且包含部分预设定配置。
================================================
FILE: 07_prototype/prototype.go
================================================
package prototype
// Cloneable 是原型对象需要实现的接口
type Cloneable interface {
Clone() Cloneable
}
type PrototypeManager struct {
prototypes map[string]Cloneable
}
func NewPrototypeManager() *PrototypeManager {
return &PrototypeManager{
prototypes: make(map[string]Cloneable),
}
}
func (p *PrototypeManager) Get(name string) Cloneable {
return p.prototypes[name].Clone()
}
func (p *PrototypeManager) Set(name string, prototype Cloneable) {
p.prototypes[name] = prototype
}
================================================
FILE: 07_prototype/prototype_test.go
================================================
package prototype
import "testing"
var manager *PrototypeManager
type Type1 struct {
name string
}
func (t *Type1) Clone() Cloneable {
tc := *t
return &tc
}
type Type2 struct {
name string
}
func (t *Type2) Clone() Cloneable {
tc := *t
return &tc
}
func TestClone(t *testing.T) {
t1 := manager.Get("t1")
t2 := t1.Clone()
if t1 == t2 {
t.Fatal("error! get clone not working")
}
}
func TestCloneFromManager(t *testing.T) {
c := manager.Get("t1").Clone()
t1 := c.(*Type1)
if t1.name != "type1" {
t.Fatal("error")
}
}
func init() {
manager = NewPrototypeManager()
t1 := &Type1{
name: "type1",
}
manager.Set("t1", t1)
}
================================================
FILE: 08_mediator/README.md
================================================
# 中介者模式
中介者模式封装对象之间互交,使依赖变的简单,并且使复杂互交简单化,封装在中介者中。
例子中的中介者使用单例模式生成中介者。
中介者的change使用switch判断类型。
================================================
FILE: 08_mediator/mediator.go
================================================
package mediator
import (
"fmt"
"strings"
)
type CDDriver struct {
Data string
}
func (c *CDDriver) ReadData() {
c.Data = "music,image"
fmt.Printf("CDDriver: reading data %s\n", c.Data)
GetMediatorInstance().changed(c)
}
type CPU struct {
Video string
Sound string
}
func (c *CPU) Process(data string) {
sp := strings.Split(data, ",")
c.Sound = sp[0]
c.Video = sp[1]
fmt.Printf("CPU: split data with Sound %s, Video %s\n", c.Sound, c.Video)
GetMediatorInstance().changed(c)
}
type VideoCard struct {
Data string
}
func (v *VideoCard) Display(data string) {
v.Data = data
fmt.Printf("VideoCard: display %s\n", v.Data)
GetMediatorInstance().changed(v)
}
type SoundCard struct {
Data string
}
func (s *SoundCard) Play(data string) {
s.Data = data
fmt.Printf("SoundCard: play %s\n", s.Data)
GetMediatorInstance().changed(s)
}
type Mediator struct {
CD *CDDriver
CPU *CPU
Video *VideoCard
Sound *SoundCard
}
var mediator *Mediator
func GetMediatorInstance() *Mediator {
if mediator == nil {
mediator = &Mediator{}
}
return mediator
}
func (m *Mediator) changed(i interface{}) {
switch inst := i.(type) {
case *CDDriver:
m.CPU.Process(inst.Data)
case *CPU:
m.Sound.Play(inst.Sound)
m.Video.Display(inst.Video)
}
}
================================================
FILE: 08_mediator/mediator_test.go
================================================
package mediator
import "testing"
func TestMediator(t *testing.T) {
mediator := GetMediatorInstance()
mediator.CD = &CDDriver{}
mediator.CPU = &CPU{}
mediator.Video = &VideoCard{}
mediator.Sound = &SoundCard{}
// Tiggle
mediator.CD.ReadData()
if mediator.CD.Data != "music,image" {
t.Fatalf("CD unexpect data %s", mediator.CD.Data)
}
if mediator.CPU.Sound != "music" {
t.Fatalf("CPU unexpect sound data %s", mediator.CPU.Sound)
}
if mediator.CPU.Video != "image" {
t.Fatalf("CPU unexpect video data %s", mediator.CPU.Video)
}
if mediator.Video.Data != "image" {
t.Fatalf("VidoeCard unexpect data %s", mediator.Video.Data)
}
if mediator.Sound.Data != "music" {
t.Fatalf("SoundCard unexpect data %s", mediator.Sound.Data)
}
}
================================================
FILE: 09_proxy/README.md
================================================
# 代理模式
代理模式用于延迟处理操作或者在进行实际操作前后进行其它处理。
## 代理模式的常见用法有
* 虚代理
* COW代理
* 远程代理
* 保护代理
* Cache 代理
* 防火墙代理
* 同步代理
* 智能指引
等。。。
================================================
FILE: 09_proxy/proxy.go
================================================
package proxy
type Subject interface {
Do() string
}
type RealSubject struct{}
func (RealSubject) Do() string {
return "real"
}
type Proxy struct {
real RealSubject
}
func (p Proxy) Do() string {
var res string
// 在调用真实对象之前的工作,检查缓存,判断权限,实例化真实对象等。。
res += "pre:"
// 调用真实对象
res += p.real.Do()
// 调用之后的操作,如缓存结果,对结果进行处理等。。
res += ":after"
return res
}
================================================
FILE: 09_proxy/proxy_test.go
================================================
package proxy
import "testing"
func TestProxy(t *testing.T) {
var sub Subject
sub = &Proxy{}
res := sub.Do()
if res != "pre:real:after" {
t.Fail()
}
}
================================================
FILE: 10_observer/README.md
================================================
# 观察者模式
观察者模式用于触发联动。
一个对象的改变会触发其它观察者的相关动作,而此对象无需关心连动对象的具体实现。
================================================
FILE: 10_observer/observer.go
================================================
package observer
import "fmt"
type Subject struct {
observers []Observer
context string
}
func NewSubject() *Subject {
return &Subject{
observers: make([]Observer, 0),
}
}
func (s *Subject) Attach(o Observer) {
s.observers = append(s.observers, o)
}
func (s *Subject) notify() {
for _, o := range s.observers {
o.Update(s)
}
}
func (s *Subject) UpdateContext(context string) {
s.context = context
s.notify()
}
type Observer interface {
Update(*Subject)
}
type Reader struct {
name string
}
func NewReader(name string) *Reader {
return &Reader{
name: name,
}
}
func (r *Reader) Update(s *Subject) {
fmt.Printf("%s receive %s\n", r.name, s.context)
}
================================================
FILE: 10_observer/observer_test.go
================================================
package observer
func ExampleObserver() {
subject := NewSubject()
reader1 := NewReader("reader1")
reader2 := NewReader("reader2")
reader3 := NewReader("reader3")
subject.Attach(reader1)
subject.Attach(reader2)
subject.Attach(reader3)
subject.UpdateContext("observer mode")
// Output:
// reader1 receive observer mode
// reader2 receive observer mode
// reader3 receive observer mode
}
================================================
FILE: 11_command/README.md
================================================
# 命令模式
命令模式本质是把某个对象的方法调用封装到对象中,方便传递、存储、调用。
示例中把主板单中的启动(start)方法和重启(reboot)方法封装为命令对象,再传递到主机(box)对象中。于两个按钮进行绑定:
* 第一个机箱(box1)设置按钮1(button1) 为开机按钮2(button2)为重启。
* 第二个机箱(box1)设置按钮2(button2) 为开机按钮1(button1)为重启。
从而得到配置灵活性。
除了配置灵活外,使用命令模式还可以用作:
* 批处理
* 任务队列
* undo, redo
等把具体命令封装到对象中使用的场合
================================================
FILE: 11_command/command.go
================================================
package command
import "fmt"
type Command interface {
Execute()
}
type StartCommand struct {
mb *MotherBoard
}
func NewStartCommand(mb *MotherBoard) *StartCommand {
return &StartCommand{
mb: mb,
}
}
func (c *StartCommand) Execute() {
c.mb.Start()
}
type RebootCommand struct {
mb *MotherBoard
}
func NewRebootCommand(mb *MotherBoard) *RebootCommand {
return &RebootCommand{
mb: mb,
}
}
func (c *RebootCommand) Execute() {
c.mb.Reboot()
}
type MotherBoard struct{}
func (*MotherBoard) Start() {
fmt.Print("system starting\n")
}
func (*MotherBoard) Reboot() {
fmt.Print("system rebooting\n")
}
type Box struct {
button1 Command
button2 Command
}
func NewBox(button1, button2 Command) *Box {
return &Box{
button1: button1,
button2: button2,
}
}
func (b *Box) PressButton1() {
b.button1.Execute()
}
func (b *Box) PressButton2() {
b.button2.Execute()
}
================================================
FILE: 11_command/command_test.go
================================================
package command
func ExampleCommand() {
mb := &MotherBoard{}
startCommand := NewStartCommand(mb)
rebootCommand := NewRebootCommand(mb)
box1 := NewBox(startCommand, rebootCommand)
box1.PressButton1()
box1.PressButton2()
box2 := NewBox(rebootCommand, startCommand)
box2.PressButton1()
box2.PressButton2()
// Output:
// system starting
// system rebooting
// system rebooting
// system starting
}
================================================
FILE: 12_iterator/README.md
================================================
# 迭代器模式
迭代器模式用于使用相同方式送代不同类型集合或者隐藏集合类型的具体实现。
可以使用迭代器模式使遍历同时应用送代策略,如请求新对象、过滤、处理对象等。
================================================
FILE: 12_iterator/iterator.go
================================================
package iterator
import "fmt"
type Aggregate interface {
Iterator() Iterator
}
type Iterator interface {
First()
IsDone() bool
Next() interface{}
}
type Numbers struct {
start, end int
}
func NewNumbers(start, end int) *Numbers {
return &Numbers{
start: start,
end: end,
}
}
func (n *Numbers) Iterator() Iterator {
return &NumbersIterator{
numbers: n,
next: n.start,
}
}
type NumbersIterator struct {
numbers *Numbers
next int
}
func (i *NumbersIterator) First() {
i.next = i.numbers.start
}
func (i *NumbersIterator) IsDone() bool {
return i.next > i.numbers.end
}
func (i *NumbersIterator) Next() interface{} {
if !i.IsDone() {
next := i.next
i.next++
return next
}
return nil
}
func IteratorPrint(i Iterator) {
for i.First(); !i.IsDone(); {
c := i.Next()
fmt.Printf("%#v\n", c)
}
}
================================================
FILE: 12_iterator/iterator_test.go
================================================
package iterator
func ExampleIterator() {
var aggregate Aggregate
aggregate = NewNumbers(1, 10)
IteratorPrint(aggregate.Iterator())
// Output:
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
}
================================================
FILE: 13_composite/README.md
================================================
# 组合模式
组合模式统一对象和对象集,使得使用相同接口使用对象和对象集。
组合模式常用于树状结构,用于统一叶子节点和树节点的访问,并且可以用于应用某一操作到所有子节点。
================================================
FILE: 13_composite/composite.go
================================================
package composite
import "fmt"
type Component interface {
Parent() Component
SetParent(Component)
Name() string
SetName(string)
AddChild(Component)
Print(string)
}
const (
LeafNode = iota
CompositeNode
)
func NewComponent(kind int, name string) Component {
var c Component
switch kind {
case LeafNode:
c = NewLeaf()
case CompositeNode:
c = NewComposite()
}
c.SetName(name)
return c
}
type component struct {
parent Component
name string
}
func (c *component) Parent() Component {
return c.parent
}
func (c *component) SetParent(parent Component) {
c.parent = parent
}
func (c *component) Name() string {
return c.name
}
func (c *component) SetName(name string) {
c.name = name
}
func (c *component) AddChild(Component) {}
func (c *component) Print(string) {}
type Leaf struct {
component
}
func NewLeaf() *Leaf {
return &Leaf{}
}
func (c *Leaf) Print(pre string) {
fmt.Printf("%s-%s\n", pre, c.Name())
}
type Composite struct {
component
childs []Component
}
func NewComposite() *Composite {
return &Composite{
childs: make([]Component, 0),
}
}
func (c *Composite) AddChild(child Component) {
child.SetParent(c)
c.childs = append(c.childs, child)
}
func (c *Composite) Print(pre string) {
fmt.Printf("%s+%s\n", pre, c.Name())
pre += " "
for _, comp := range c.childs {
comp.Print(pre)
}
}
================================================
FILE: 13_composite/composite_test.go
================================================
package composite
func ExampleComposite() {
root := NewComponent(CompositeNode, "root")
c1 := NewComponent(CompositeNode, "c1")
c2 := NewComponent(CompositeNode, "c2")
c3 := NewComponent(CompositeNode, "c3")
l1 := NewComponent(LeafNode, "l1")
l2 := NewComponent(LeafNode, "l2")
l3 := NewComponent(LeafNode, "l3")
root.AddChild(c1)
root.AddChild(c2)
c1.AddChild(c3)
c1.AddChild(l1)
c2.AddChild(l2)
c2.AddChild(l3)
root.Print("")
// Output:
// +root
// +c1
// +c3
// -l1
// +c2
// -l2
// -l3
}
================================================
FILE: 14_template_method/README.md
================================================
# 模版方法模式
模版方法模式使用继承机制,把通用步骤和通用方法放到父类中,把具体实现延迟到子类中实现。使得实现符合开闭原则。
如实例代码中通用步骤在父类中实现(`准备`、`下载`、`保存`、`收尾`)下载和保存的具体实现留到子类中,并且提供 `保存`方法的默认实现。
因为Golang不提供继承机制,需要使用匿名组合模拟实现继承。
此处需要注意:因为父类需要调用子类方法,所以子类需要匿名组合父类的同时,父类需要持有子类的引用。
================================================
FILE: 14_template_method/templatemethod.go
================================================
package templatemethod
import "fmt"
type Downloader interface {
Download(uri string)
}
type template struct {
implement
uri string
}
type implement interface {
download()
save()
}
func newTemplate(impl implement) *template {
return &template{
implement: impl,
}
}
func (t *template) Download(uri string) {
t.uri = uri
fmt.Print("prepare downloading\n")
t.implement.download()
t.implement.save()
fmt.Print("finish downloading\n")
}
func (t *template) save() {
fmt.Print("default save\n")
}
type HTTPDownloader struct {
*template
}
func NewHTTPDownloader() Downloader {
downloader := &HTTPDownloader{}
template := newTemplate(downloader)
downloader.template = template
return downloader
}
func (d *HTTPDownloader) download() {
fmt.Printf("download %s via http\n", d.uri)
}
func (*HTTPDownloader) save() {
fmt.Printf("http save\n")
}
type FTPDownloader struct {
*template
}
func NewFTPDownloader() Downloader {
downloader := &FTPDownloader{}
template := newTemplate(downloader)
downloader.template = template
return downloader
}
func (d *FTPDownloader) download() {
fmt.Printf("download %s via ftp\n", d.uri)
}
================================================
FILE: 14_template_method/templatemethod_test.go
================================================
package templatemethod
func ExampleHTTPDownloader() {
var downloader Downloader = NewHTTPDownloader()
downloader.Download("http://example.com/abc.zip")
// Output:
// prepare downloading
// download http://example.com/abc.zip via http
// http save
// finish downloading
}
func ExampleFTPDownloader() {
var downloader Downloader = NewFTPDownloader()
downloader.Download("ftp://example.com/abc.zip")
// Output:
// prepare downloading
// download ftp://example.com/abc.zip via ftp
// default save
// finish downloading
}
================================================
FILE: 15_strategy/README.md
================================================
# 策略模式
定义一系列算法,让这些算法在运行时可以互换,使得分离算法,符合开闭原则。
================================================
FILE: 15_strategy/strategy.go
================================================
package strategy
import "fmt"
type Payment struct {
context *PaymentContext
strategy PaymentStrategy
}
type PaymentContext struct {
Name, CardID string
Money int
}
func NewPayment(name, cardid string, money int, strategy PaymentStrategy) *Payment {
return &Payment{
context: &PaymentContext{
Name: name,
CardID: cardid,
Money: money,
},
strategy: strategy,
}
}
func (p *Payment) Pay() {
p.strategy.Pay(p.context)
}
type PaymentStrategy interface {
Pay(*PaymentContext)
}
type Cash struct{}
func (*Cash) Pay(ctx *PaymentContext) {
fmt.Printf("Pay $%d to %s by cash", ctx.Money, ctx.Name)
}
type Bank struct{}
func (*Bank) Pay(ctx *PaymentContext) {
fmt.Printf("Pay $%d to %s by bank account %s", ctx.Money, ctx.Name, ctx.CardID)
}
================================================
FILE: 15_strategy/strategy_test.go
================================================
package strategy
func ExamplePayByCash() {
payment := NewPayment("Ada", "", 123, &Cash{})
payment.Pay()
// Output:
// Pay $123 to Ada by cash
}
func ExamplePayByBank() {
payment := NewPayment("Bob", "0002", 888, &Bank{})
payment.Pay()
// Output:
// Pay $888 to Bob by bank account 0002
}
================================================
FILE: 16_state/README.md
================================================
# 状态模式
状态模式用于分离状态和行为。
================================================
FILE: 16_state/state.go
================================================
package state
import "fmt"
type Week interface {
Today()
Next(*DayContext)
}
type DayContext struct {
today Week
}
func NewDayContext() *DayContext {
return &DayContext{
today: &Sunday{},
}
}
func (d *DayContext) Today() {
d.today.Today()
}
func (d *DayContext) Next() {
d.today.Next(d)
}
type Sunday struct{}
func (*Sunday) Today() {
fmt.Printf("Sunday\n")
}
func (*Sunday) Next(ctx *DayContext) {
ctx.today = &Monday{}
}
type Monday struct{}
func (*Monday) Today() {
fmt.Printf("Monday\n")
}
func (*Monday) Next(ctx *DayContext) {
ctx.today = &Tuesday{}
}
type Tuesday struct{}
func (*Tuesday) Today() {
fmt.Printf("Tuesday\n")
}
func (*Tuesday) Next(ctx *DayContext) {
ctx.today = &Wednesday{}
}
type Wednesday struct{}
func (*Wednesday) Today() {
fmt.Printf("Wednesday\n")
}
func (*Wednesday) Next(ctx *DayContext) {
ctx.today = &Thursday{}
}
type Thursday struct{}
func (*Thursday) Today() {
fmt.Printf("Thursday\n")
}
func (*Thursday) Next(ctx *DayContext) {
ctx.today = &Friday{}
}
type Friday struct{}
func (*Friday) Today() {
fmt.Printf("Friday\n")
}
func (*Friday) Next(ctx *DayContext) {
ctx.today = &Saturday{}
}
type Saturday struct{}
func (*Saturday) Today() {
fmt.Printf("Saturday\n")
}
func (*Saturday) Next(ctx *DayContext) {
ctx.today = &Sunday{}
}
================================================
FILE: 16_state/state_test.go
================================================
package state
func ExampleWeek() {
ctx := NewDayContext()
todayAndNext := func() {
ctx.Today()
ctx.Next()
}
for i := 0; i < 8; i++ {
todayAndNext()
}
// Output:
// Sunday
// Monday
// Tuesday
// Wednesday
// Thursday
// Friday
// Saturday
// Sunday
}
================================================
FILE: 17_memento/README.md
================================================
# 备忘录模式
备忘录模式用于保存程序内部状态到外部,又不希望暴露内部状态的情形。
程序内部状态使用窄接口传递给外部进行存储,从而不暴露程序实现细节。
备忘录模式同时可以离线保存内部状态,如保存到数据库,文件等。
================================================
FILE: 17_memento/memento.go
================================================
package memento
import "fmt"
type Memento interface{}
type Game struct {
hp, mp int
}
type gameMemento struct {
hp, mp int
}
func (g *Game) Play(mpDelta, hpDelta int) {
g.mp += mpDelta
g.hp += hpDelta
}
func (g *Game) Save() Memento {
return &gameMemento{
hp: g.hp,
mp: g.mp,
}
}
func (g *Game) Load(m Memento) {
gm := m.(*gameMemento)
g.mp = gm.mp
g.hp = gm.hp
}
func (g *Game) Status() {
fmt.Printf("Current HP:%d, MP:%d\n", g.hp, g.mp)
}
================================================
FILE: 17_memento/memento_test.go
================================================
package memento
func ExampleGame() {
game := &Game{
hp: 10,
mp: 10,
}
game.Status()
progress := game.Save()
game.Play(-2, -3)
game.Status()
game.Load(progress)
game.Status()
// Output:
// Current HP:10, MP:10
// Current HP:7, MP:8
// Current HP:10, MP:10
}
================================================
FILE: 18_flyweight/README.md
================================================
# 享元模式
享元模式从对象中剥离出不发生改变且多个实例需要的重复数据,独立出一个享元,使多个对象共享,从而节省内存以及减少对象数量。
================================================
FILE: 18_flyweight/flyweight.go
================================================
package flyweight
import "fmt"
type ImageFlyweightFactory struct {
maps map[string]*ImageFlyweight
}
var imageFactory *ImageFlyweightFactory
func GetImageFlyweightFactory() *ImageFlyweightFactory {
if imageFactory == nil {
imageFactory = &ImageFlyweightFactory{
maps: make(map[string]*ImageFlyweight),
}
}
return imageFactory
}
func (f *ImageFlyweightFactory) Get(filename string) *ImageFlyweight {
image := f.maps[filename]
if image == nil {
image = NewImageFlyweight(filename)
f.maps[filename] = image
}
return image
}
type ImageFlyweight struct {
data string
}
func NewImageFlyweight(filename string) *ImageFlyweight {
// Load image file
data := fmt.Sprintf("image data %s", filename)
return &ImageFlyweight{
data: data,
}
}
func (i *ImageFlyweight) Data() string {
return i.data
}
type ImageViewer struct {
*ImageFlyweight
}
func NewImageViewer(filename string) *ImageViewer {
image := GetImageFlyweightFactory().Get(filename)
return &ImageViewer{
ImageFlyweight: image,
}
}
func (i *ImageViewer) Display() {
fmt.Printf("Display: %s\n", i.Data())
}
================================================
FILE: 18_flyweight/flyweight_test.go
================================================
package flyweight
import "testing"
func ExampleFlyweight() {
viewer := NewImageViewer("image1.png")
viewer.Display()
// Output:
// Display: image data image1.png
}
func TestFlyweight(t *testing.T) {
viewer1 := NewImageViewer("image1.png")
viewer2 := NewImageViewer("image1.png")
if viewer1.ImageFlyweight != viewer2.ImageFlyweight {
t.Fail()
}
}
================================================
FILE: 19_interpreter/README.md
================================================
# 解释器模式
解释器模式定义一套语言文法,并设计该语言解释器,使用户能使用特定文法控制解释器行为。
解释器模式的意义在于,它分离多种复杂功能的实现,每个功能只需关注自身的解释。
对于调用者不用关心内部的解释器的工作,只需要用简单的方式组合命令就可以。
================================================
FILE: 19_interpreter/interpreter.go
================================================
package interpreter
import (
"strconv"
"strings"
)
type Node interface {
Interpret() int
}
type ValNode struct {
val int
}
func (n *ValNode) Interpret() int {
return n.val
}
type AddNode struct {
left, right Node
}
func (n *AddNode) Interpret() int {
return n.left.Interpret() + n.right.Interpret()
}
type MinNode struct {
left, right Node
}
func (n *MinNode) Interpret() int {
return n.left.Interpret() - n.right.Interpret()
}
type Parser struct {
exp []string
index int
prev Node
}
func (p *Parser) Parse(exp string) {
p.exp = strings.Split(exp, " ")
for {
if p.index >= len(p.exp) {
return
}
switch p.exp[p.index] {
case "+":
p.prev = p.newAddNode()
case "-":
p.prev = p.newMinNode()
default:
p.prev = p.newValNode()
}
}
}
func (p *Parser) newAddNode() Node {
p.index++
return &AddNode{
left: p.prev,
right: p.newValNode(),
}
}
func (p *Parser) newMinNode() Node {
p.index++
return &MinNode{
left: p.prev,
right: p.newValNode(),
}
}
func (p *Parser) newValNode() Node {
v, _ := strconv.Atoi(p.exp[p.index])
p.index++
return &ValNode{
val: v,
}
}
func (p *Parser) Result() Node {
return p.prev
}
================================================
FILE: 19_interpreter/interpreter_test.go
================================================
package interpreter
import "testing"
func TestInterpreter(t *testing.T) {
p := &Parser{}
p.Parse("1 + 2 + 3 - 4 + 5 - 6")
res := p.Result().Interpret()
expect := 1
if res != expect {
t.Fatalf("expect %d got %d", expect, res)
}
}
================================================
FILE: 20_decorator/README.md
================================================
# 装饰模式
装饰模式使用对象组合的方式动态改变或增加对象行为。
Go语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。
使用匿名组合,在装饰器中不必显式定义转调原对象方法。
================================================
FILE: 20_decorator/decorator.go
================================================
package decorator
type Component interface {
Calc() int
}
type ConcreteComponent struct{}
func (*ConcreteComponent) Calc() int {
return 0
}
type MulDecorator struct {
Component
num int
}
func WrapMulDecorator(c Component, num int) Component {
return &MulDecorator{
Component: c,
num: num,
}
}
func (d *MulDecorator) Calc() int {
return d.Component.Calc() * d.num
}
type AddDecorator struct {
Component
num int
}
func WrapAddDecorator(c Component, num int) Component {
return &AddDecorator{
Component: c,
num: num,
}
}
func (d *AddDecorator) Calc() int {
return d.Component.Calc() + d.num
}
================================================
FILE: 20_decorator/decorator_test.go
================================================
package decorator
import "fmt"
func ExampleDecorator() {
var c Component = &ConcreteComponent{}
c = WrapAddDecorator(c, 10)
c = WrapMulDecorator(c, 8)
res := c.Calc()
fmt.Printf("res %d\n", res)
// Output:
// res 80
}
================================================
FILE: 21_chain_of_responsibility/README.md
================================================
# 职责链模式
职责链模式用于分离不同职责,并且动态组合相关职责。
Golang实现职责链模式时候,因为没有继承的支持,使用链对象包涵职责的方式,即:
* 链对象包含当前职责对象以及下一个职责链。
* 职责对象提供接口表示是否能处理对应请求。
* 职责对象提供处理函数处理相关职责。
同时可在职责链类中实现职责接口相关函数,使职责链对象可以当做一般职责对象是用。
================================================
FILE: 21_chain_of_responsibility/chain.go
================================================
package chain
import "fmt"
type Manager interface {
HaveRight(money int) bool
HandleFeeRequest(name string, money int) bool
}
type RequestChain struct {
Manager
successor *RequestChain
}
func (r *RequestChain) SetSuccessor(m *RequestChain) {
r.successor = m
}
func (r *RequestChain) HandleFeeRequest(name string, money int) bool {
if r.Manager.HaveRight(money) {
return r.Manager.HandleFeeRequest(name, money)
}
if r.successor != nil {
return r.successor.HandleFeeRequest(name, money)
}
return false
}
func (r *RequestChain) HaveRight(money int) bool {
return true
}
type ProjectManager struct{}
func NewProjectManagerChain() *RequestChain {
return &RequestChain{
Manager: &ProjectManager{},
}
}
func (*ProjectManager) HaveRight(money int) bool {
return money < 500
}
func (*ProjectManager) HandleFeeRequest(name string, money int) bool {
if name == "bob" {
fmt.Printf("Project manager permit %s %d fee request\n", name, money)
return true
}
fmt.Printf("Project manager don't permit %s %d fee request\n", name, money)
return false
}
type DepManager struct{}
func NewDepManagerChain() *RequestChain {
return &RequestChain{
Manager: &DepManager{},
}
}
func (*DepManager) HaveRight(money int) bool {
return money < 5000
}
func (*DepManager) HandleFeeRequest(name string, money int) bool {
if name == "tom" {
fmt.Printf("Dep manager permit %s %d fee request\n", name, money)
return true
}
fmt.Printf("Dep manager don't permit %s %d fee request\n", name, money)
return false
}
type GeneralManager struct{}
func NewGeneralManagerChain() *RequestChain {
return &RequestChain{
Manager: &GeneralManager{},
}
}
func (*GeneralManager) HaveRight(money int) bool {
return true
}
func (*GeneralManager) HandleFeeRequest(name string, money int) bool {
if name == "ada" {
fmt.Printf("General manager permit %s %d fee request\n", name, money)
return true
}
fmt.Printf("General manager don't permit %s %d fee request\n", name, money)
return false
}
================================================
FILE: 21_chain_of_responsibility/chain_test.go
================================================
package chain
func ExampleChain() {
c1 := NewProjectManagerChain()
c2 := NewDepManagerChain()
c3 := NewGeneralManagerChain()
c1.SetSuccessor(c2)
c2.SetSuccessor(c3)
var c Manager = c1
c.HandleFeeRequest("bob", 400)
c.HandleFeeRequest("tom", 1400)
c.HandleFeeRequest("ada", 10000)
c.HandleFeeRequest("floar", 400)
// Output:
// Project manager permit bob 400 fee request
// Dep manager permit tom 1400 fee request
// General manager permit ada 10000 fee request
// Project manager don't permit floar 400 fee request
}
================================================
FILE: 22_bridge/README.md
================================================
# 桥接模式
桥接模式分离抽象部分和实现部分。使得两部分独立扩展。
桥接模式类似于策略模式,区别在于策略模式封装一系列算法使得算法可以互相替换。
策略模式使抽象部分和实现部分分离,可以独立变化。
================================================
FILE: 22_bridge/bridge.go
================================================
package bridge
import "fmt"
type AbstractMessage interface {
SendMessage(text, to string)
}
type MessageImplementer interface {
Send(text, to string)
}
type MessageSMS struct{}
func ViaSMS() MessageImplementer {
return &MessageSMS{}
}
func (*MessageSMS) Send(text, to string) {
fmt.Printf("send %s to %s via SMS", text, to)
}
type MessageEmail struct{}
func ViaEmail() MessageImplementer {
return &MessageEmail{}
}
func (*MessageEmail) Send(text, to string) {
fmt.Printf("send %s to %s via Email", text, to)
}
type CommonMessage struct {
method MessageImplementer
}
func NewCommonMessage(method MessageImplementer) *CommonMessage {
return &CommonMessage{
method: method,
}
}
func (m *CommonMessage) SendMessage(text, to string) {
m.method.Send(text, to)
}
type UrgencyMessage struct {
method MessageImplementer
}
func NewUrgencyMessage(method MessageImplementer) *UrgencyMessage {
return &UrgencyMessage{
method: method,
}
}
func (m *UrgencyMessage) SendMessage(text, to string) {
m.method.Send(fmt.Sprintf("[Urgency] %s", text), to)
}
================================================
FILE: 22_bridge/bridge_test.go
================================================
package bridge
func ExampleCommonSMS() {
m := NewCommonMessage(ViaSMS())
m.SendMessage("have a drink?", "bob")
// Output:
// send have a drink? to bob via SMS
}
func ExampleCommonEmail() {
m := NewCommonMessage(ViaEmail())
m.SendMessage("have a drink?", "bob")
// Output:
// send have a drink? to bob via Email
}
func ExampleUrgencySMS() {
m := NewUrgencyMessage(ViaSMS())
m.SendMessage("have a drink?", "bob")
// Output:
// send [Urgency] have a drink? to bob via SMS
}
func ExampleUrgencyEmail() {
m := NewUrgencyMessage(ViaEmail())
m.SendMessage("have a drink?", "bob")
// Output:
// send [Urgency] have a drink? to bob via Email
}
================================================
FILE: 23_visitor/README.md
================================================
# 访问者模式
访问者模式可以给一系列对象透明的添加功能,并且把相关代码封装到一个类中。
对象只要预留访问者接口`Accept`则后期为对象添加功能的时候就不需要改动对象。
================================================
FILE: 23_visitor/visitor.go
================================================
package visitor
import "fmt"
type Customer interface {
Accept(Visitor)
}
type Visitor interface {
Visit(Customer)
}
type EnterpriseCustomer struct {
name string
}
type CustomerCol struct {
customers []Customer
}
func (c *CustomerCol) Add(customer Customer) {
c.customers = append(c.customers, customer)
}
func (c *CustomerCol) Accept(visitor Visitor) {
for _, customer := range c.customers {
customer.Accept(visitor)
}
}
func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
return &EnterpriseCustomer{
name: name,
}
}
func (c *EnterpriseCustomer) Accept(visitor Visitor) {
visitor.Visit(c)
}
type IndividualCustomer struct {
name string
}
func NewIndividualCustomer(name string) *IndividualCustomer {
return &IndividualCustomer{
name: name,
}
}
func (c *IndividualCustomer) Accept(visitor Visitor) {
visitor.Visit(c)
}
type ServiceRequestVisitor struct{}
func (*ServiceRequestVisitor) Visit(customer Customer) {
switch c := customer.(type) {
case *EnterpriseCustomer:
fmt.Printf("serving enterprise customer %s\n", c.name)
case *IndividualCustomer:
fmt.Printf("serving individual customer %s\n", c.name)
}
}
// AnalysisVisitor only for enterprise
type AnalysisVisitor struct{}
func (*AnalysisVisitor) Visit(customer Customer) {
switch c := customer.(type) {
case *EnterpriseCustomer:
fmt.Printf("analysis enterprise customer %s\n", c.name)
}
}
================================================
FILE: 23_visitor/visitor_test.go
================================================
package visitor
func ExampleRequestVisitor() {
c := &CustomerCol{}
c.Add(NewEnterpriseCustomer("A company"))
c.Add(NewEnterpriseCustomer("B company"))
c.Add(NewIndividualCustomer("bob"))
c.Accept(&ServiceRequestVisitor{})
// Output:
// serving enterprise customer A company
// serving enterprise customer B company
// serving individual customer bob
}
func ExampleAnalysis() {
c := &CustomerCol{}
c.Add(NewEnterpriseCustomer("A company"))
c.Add(NewIndividualCustomer("bob"))
c.Add(NewEnterpriseCustomer("B company"))
c.Accept(&AnalysisVisitor{})
// Output:
// analysis enterprise customer A company
// analysis enterprise customer B company
}
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Senghoo Kim And Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Go 语言设计模式
[](https://travis-ci.org/senghoo/golang-design-pattern)
Go 语言设计模式的实例代码
## 创建型模式
* [简单工厂模式(Simple Factory)](https://github.com/senghoo/golang-design-pattern/tree/master/00_simple_factory)
* [工厂方法模式(Factory Method)](https://github.com/senghoo/golang-design-pattern/tree/master/04_factory_method)
* [抽象工厂模式(Abstract Factory)](https://github.com/senghoo/golang-design-pattern/tree/master/05_abstract_factory)
* [创建者模式(Builder)](https://github.com/senghoo/golang-design-pattern/tree/master/06_builder)
* [原型模式(Prototype)](https://github.com/senghoo/golang-design-pattern/tree/master/07_prototype)
* [单例模式(Singleton)](https://github.com/senghoo/golang-design-pattern/tree/master/03_singleton)
## 结构型模式
* [外观模式(Facade)](https://github.com/senghoo/golang-design-pattern/tree/master/01_facade)
* [适配器模式(Adapter)](https://github.com/senghoo/golang-design-pattern/tree/master/02_adapter)
* [代理模式(Proxy)](https://github.com/senghoo/golang-design-pattern/tree/master/09_proxy)
* [组合模式(Composite)](https://github.com/senghoo/golang-design-pattern/tree/master/13_composite)
* [享元模式(Flyweight)](https://github.com/senghoo/golang-design-pattern/tree/master/18_flyweight)
* [装饰模式(Decorator)](https://github.com/senghoo/golang-design-pattern/tree/master/20_decorator)
* [桥模式(Bridge)](https://github.com/senghoo/golang-design-pattern/tree/master/22_bridge)
## 行为型模式
* [中介者模式(Mediator)](https://github.com/senghoo/golang-design-pattern/tree/master/08_mediator)
* [观察者模式(Observer)](https://github.com/senghoo/golang-design-pattern/tree/master/10_observer)
* [命令模式(Command)](https://github.com/senghoo/golang-design-pattern/tree/master/11_command)
* [迭代器模式(Iterator)](https://github.com/senghoo/golang-design-pattern/tree/master/12_iterator)
* [模板方法模式(Template Method)](https://github.com/senghoo/golang-design-pattern/tree/master/14_template_method)
* [策略模式(Strategy)](https://github.com/senghoo/golang-design-pattern/tree/master/15_strategy)
* [状态模式(State)](https://github.com/senghoo/golang-design-pattern/tree/master/16_state)
* [备忘录模式(Memento)](https://github.com/senghoo/golang-design-pattern/tree/master/17_memento)
* [解释器模式(Interpreter)](https://github.com/senghoo/golang-design-pattern/tree/master/19_interpreter)
* [职责链模式(Chain of Responsibility)](https://github.com/senghoo/golang-design-pattern/tree/master/21_chain_of_responsibility)
* [访问者模式(Visitor)](https://github.com/senghoo/golang-design-pattern/tree/master/23_visitor)
gitextract_hshruwzb/ ├── .gitignore ├── .travis.yml ├── 00_simple_factory/ │ ├── README.md │ ├── simple.go │ └── simple_test.go ├── 01_facade/ │ ├── README.md │ ├── facade.go │ └── facade_test.go ├── 02_adapter/ │ ├── README.md │ ├── adapter.go │ └── adapter_test.go ├── 03_singleton/ │ ├── README.md │ ├── singleton.go │ └── singleton_test.go ├── 04_factory_method/ │ ├── README.md │ ├── factorymethod.go │ └── factorymethod_test.go ├── 05_abstract_factory/ │ ├── README.md │ ├── abstractfactory.go │ └── abstractfactory_test.go ├── 06_builder/ │ ├── builder.go │ └── builder_test.go ├── 07_prototype/ │ ├── README.md │ ├── prototype.go │ └── prototype_test.go ├── 08_mediator/ │ ├── README.md │ ├── mediator.go │ └── mediator_test.go ├── 09_proxy/ │ ├── README.md │ ├── proxy.go │ └── proxy_test.go ├── 10_observer/ │ ├── README.md │ ├── observer.go │ └── observer_test.go ├── 11_command/ │ ├── README.md │ ├── command.go │ └── command_test.go ├── 12_iterator/ │ ├── README.md │ ├── iterator.go │ └── iterator_test.go ├── 13_composite/ │ ├── README.md │ ├── composite.go │ └── composite_test.go ├── 14_template_method/ │ ├── README.md │ ├── templatemethod.go │ └── templatemethod_test.go ├── 15_strategy/ │ ├── README.md │ ├── strategy.go │ └── strategy_test.go ├── 16_state/ │ ├── README.md │ ├── state.go │ └── state_test.go ├── 17_memento/ │ ├── README.md │ ├── memento.go │ └── memento_test.go ├── 18_flyweight/ │ ├── README.md │ ├── flyweight.go │ └── flyweight_test.go ├── 19_interpreter/ │ ├── README.md │ ├── interpreter.go │ └── interpreter_test.go ├── 20_decorator/ │ ├── README.md │ ├── decorator.go │ └── decorator_test.go ├── 21_chain_of_responsibility/ │ ├── README.md │ ├── chain.go │ └── chain_test.go ├── 22_bridge/ │ ├── README.md │ ├── bridge.go │ └── bridge_test.go ├── 23_visitor/ │ ├── README.md │ ├── visitor.go │ └── visitor_test.go ├── LICENSE └── README.md
SYMBOL INDEX (322 symbols across 48 files)
FILE: 00_simple_factory/simple.go
type API (line 6) | type API interface
function NewAPI (line 11) | func NewAPI(t int) API {
type hiAPI (line 21) | type hiAPI struct
method Say (line 24) | func (*hiAPI) Say(name string) string {
type helloAPI (line 29) | type helloAPI struct
method Say (line 32) | func (*helloAPI) Say(name string) string {
FILE: 00_simple_factory/simple_test.go
function TestType1 (line 6) | func TestType1(t *testing.T) {
function TestType2 (line 14) | func TestType2(t *testing.T) {
FILE: 01_facade/facade.go
function NewAPI (line 5) | func NewAPI() API {
type API (line 13) | type API interface
type apiImpl (line 18) | type apiImpl struct
method Test (line 23) | func (a *apiImpl) Test() string {
function NewAModuleAPI (line 30) | func NewAModuleAPI() AModuleAPI {
type AModuleAPI (line 35) | type AModuleAPI interface
type aModuleImpl (line 39) | type aModuleImpl struct
method TestA (line 41) | func (*aModuleImpl) TestA() string {
function NewBModuleAPI (line 46) | func NewBModuleAPI() BModuleAPI {
type BModuleAPI (line 51) | type BModuleAPI interface
type bModuleImpl (line 55) | type bModuleImpl struct
method TestB (line 57) | func (*bModuleImpl) TestB() string {
FILE: 01_facade/facade_test.go
function TestFacadeAPI (line 8) | func TestFacadeAPI(t *testing.T) {
FILE: 02_adapter/adapter.go
type Target (line 4) | type Target interface
type Adaptee (line 9) | type Adaptee interface
function NewAdaptee (line 14) | func NewAdaptee() Adaptee {
type adapteeImpl (line 19) | type adapteeImpl struct
method SpecificRequest (line 22) | func (*adapteeImpl) SpecificRequest() string {
function NewAdapter (line 27) | func NewAdapter(adaptee Adaptee) Target {
type adapter (line 34) | type adapter struct
method Request (line 39) | func (a *adapter) Request() string {
FILE: 02_adapter/adapter_test.go
function TestAdapter (line 7) | func TestAdapter(t *testing.T) {
FILE: 03_singleton/singleton.go
type Singleton (line 7) | type Singleton interface
type singleton (line 12) | type singleton struct
method foo (line 14) | func (s singleton) foo() {}
function GetInstance (line 22) | func GetInstance() Singleton {
FILE: 03_singleton/singleton_test.go
constant parCount (line 8) | parCount = 100
function TestSingleton (line 10) | func TestSingleton(t *testing.T) {
function TestParallelSingleton (line 18) | func TestParallelSingleton(t *testing.T) {
FILE: 04_factory_method/factorymethod.go
type Operator (line 4) | type Operator interface
type OperatorFactory (line 11) | type OperatorFactory interface
type OperatorBase (line 16) | type OperatorBase struct
method SetA (line 21) | func (o *OperatorBase) SetA(a int) {
method SetB (line 26) | func (o *OperatorBase) SetB(b int) {
type PlusOperatorFactory (line 31) | type PlusOperatorFactory struct
method Create (line 33) | func (PlusOperatorFactory) Create() Operator {
type PlusOperator (line 40) | type PlusOperator struct
method Result (line 45) | func (o PlusOperator) Result() int {
type MinusOperatorFactory (line 50) | type MinusOperatorFactory struct
method Create (line 52) | func (MinusOperatorFactory) Create() Operator {
type MinusOperator (line 59) | type MinusOperator struct
method Result (line 64) | func (o MinusOperator) Result() int {
FILE: 04_factory_method/factorymethod_test.go
function compute (line 5) | func compute(factory OperatorFactory, a, b int) int {
function TestOperator (line 12) | func TestOperator(t *testing.T) {
FILE: 05_abstract_factory/abstractfactory.go
type OrderMainDAO (line 6) | type OrderMainDAO interface
type OrderDetailDAO (line 11) | type OrderDetailDAO interface
type DAOFactory (line 16) | type DAOFactory interface
type RDBMainDAO (line 22) | type RDBMainDAO struct
method SaveOrderMain (line 25) | func (*RDBMainDAO) SaveOrderMain() {
type RDBDetailDAO (line 30) | type RDBDetailDAO struct
method SaveOrderDetail (line 33) | func (*RDBDetailDAO) SaveOrderDetail() {
type RDBDAOFactory (line 38) | type RDBDAOFactory struct
method CreateOrderMainDAO (line 40) | func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {
method CreateOrderDetailDAO (line 44) | func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
type XMLMainDAO (line 49) | type XMLMainDAO struct
method SaveOrderMain (line 52) | func (*XMLMainDAO) SaveOrderMain() {
type XMLDetailDAO (line 57) | type XMLDetailDAO struct
method SaveOrderDetail (line 60) | func (*XMLDetailDAO) SaveOrderDetail() {
type XMLDAOFactory (line 65) | type XMLDAOFactory struct
method CreateOrderMainDAO (line 67) | func (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO {
method CreateOrderDetailDAO (line 71) | func (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
FILE: 05_abstract_factory/abstractfactory_test.go
function getMainAndDetail (line 3) | func getMainAndDetail(factory DAOFactory) {
function ExampleRdbFactory (line 8) | func ExampleRdbFactory() {
function ExampleXmlFactory (line 17) | func ExampleXmlFactory() {
FILE: 06_builder/builder.go
type Builder (line 4) | type Builder interface
type Director (line 10) | type Director struct
method Construct (line 22) | func (d *Director) Construct() {
function NewDirector (line 15) | func NewDirector(builder Builder) *Director {
type Builder1 (line 28) | type Builder1 struct
method Part1 (line 32) | func (b *Builder1) Part1() {
method Part2 (line 36) | func (b *Builder1) Part2() {
method Part3 (line 40) | func (b *Builder1) Part3() {
method GetResult (line 44) | func (b *Builder1) GetResult() string {
type Builder2 (line 48) | type Builder2 struct
method Part1 (line 52) | func (b *Builder2) Part1() {
method Part2 (line 56) | func (b *Builder2) Part2() {
method Part3 (line 60) | func (b *Builder2) Part3() {
method GetResult (line 64) | func (b *Builder2) GetResult() int {
FILE: 06_builder/builder_test.go
function TestBuilder1 (line 5) | func TestBuilder1(t *testing.T) {
function TestBuilder2 (line 15) | func TestBuilder2(t *testing.T) {
FILE: 07_prototype/prototype.go
type Cloneable (line 4) | type Cloneable interface
type PrototypeManager (line 8) | type PrototypeManager struct
method Get (line 18) | func (p *PrototypeManager) Get(name string) Cloneable {
method Set (line 22) | func (p *PrototypeManager) Set(name string, prototype Cloneable) {
function NewPrototypeManager (line 12) | func NewPrototypeManager() *PrototypeManager {
FILE: 07_prototype/prototype_test.go
type Type1 (line 7) | type Type1 struct
method Clone (line 11) | func (t *Type1) Clone() Cloneable {
type Type2 (line 16) | type Type2 struct
method Clone (line 20) | func (t *Type2) Clone() Cloneable {
function TestClone (line 25) | func TestClone(t *testing.T) {
function TestCloneFromManager (line 35) | func TestCloneFromManager(t *testing.T) {
function init (line 45) | func init() {
FILE: 08_mediator/mediator.go
type CDDriver (line 8) | type CDDriver struct
method ReadData (line 12) | func (c *CDDriver) ReadData() {
type CPU (line 19) | type CPU struct
method Process (line 24) | func (c *CPU) Process(data string) {
type VideoCard (line 33) | type VideoCard struct
method Display (line 37) | func (v *VideoCard) Display(data string) {
type SoundCard (line 43) | type SoundCard struct
method Play (line 47) | func (s *SoundCard) Play(data string) {
type Mediator (line 53) | type Mediator struct
method changed (line 69) | func (m *Mediator) changed(i interface{}) {
function GetMediatorInstance (line 62) | func GetMediatorInstance() *Mediator {
FILE: 08_mediator/mediator_test.go
function TestMediator (line 5) | func TestMediator(t *testing.T) {
FILE: 09_proxy/proxy.go
type Subject (line 3) | type Subject interface
type RealSubject (line 7) | type RealSubject struct
method Do (line 9) | func (RealSubject) Do() string {
type Proxy (line 13) | type Proxy struct
method Do (line 17) | func (p Proxy) Do() string {
FILE: 09_proxy/proxy_test.go
function TestProxy (line 5) | func TestProxy(t *testing.T) {
FILE: 10_observer/observer.go
type Subject (line 5) | type Subject struct
method Attach (line 16) | func (s *Subject) Attach(o Observer) {
method notify (line 20) | func (s *Subject) notify() {
method UpdateContext (line 26) | func (s *Subject) UpdateContext(context string) {
function NewSubject (line 10) | func NewSubject() *Subject {
type Observer (line 31) | type Observer interface
type Reader (line 35) | type Reader struct
method Update (line 45) | func (r *Reader) Update(s *Subject) {
function NewReader (line 39) | func NewReader(name string) *Reader {
FILE: 10_observer/observer_test.go
function ExampleObserver (line 3) | func ExampleObserver() {
FILE: 11_command/command.go
type Command (line 5) | type Command interface
type StartCommand (line 9) | type StartCommand struct
method Execute (line 19) | func (c *StartCommand) Execute() {
function NewStartCommand (line 13) | func NewStartCommand(mb *MotherBoard) *StartCommand {
type RebootCommand (line 23) | type RebootCommand struct
method Execute (line 33) | func (c *RebootCommand) Execute() {
function NewRebootCommand (line 27) | func NewRebootCommand(mb *MotherBoard) *RebootCommand {
type MotherBoard (line 37) | type MotherBoard struct
method Start (line 39) | func (*MotherBoard) Start() {
method Reboot (line 43) | func (*MotherBoard) Reboot() {
type Box (line 47) | type Box struct
method PressButton1 (line 59) | func (b *Box) PressButton1() {
method PressButton2 (line 63) | func (b *Box) PressButton2() {
function NewBox (line 52) | func NewBox(button1, button2 Command) *Box {
FILE: 11_command/command_test.go
function ExampleCommand (line 3) | func ExampleCommand() {
FILE: 12_iterator/iterator.go
type Aggregate (line 5) | type Aggregate interface
type Iterator (line 9) | type Iterator interface
type Numbers (line 15) | type Numbers struct
method Iterator (line 26) | func (n *Numbers) Iterator() Iterator {
function NewNumbers (line 19) | func NewNumbers(start, end int) *Numbers {
type NumbersIterator (line 33) | type NumbersIterator struct
method First (line 38) | func (i *NumbersIterator) First() {
method IsDone (line 42) | func (i *NumbersIterator) IsDone() bool {
method Next (line 46) | func (i *NumbersIterator) Next() interface{} {
function IteratorPrint (line 55) | func IteratorPrint(i Iterator) {
FILE: 12_iterator/iterator_test.go
function ExampleIterator (line 3) | func ExampleIterator() {
FILE: 13_composite/composite.go
type Component (line 5) | type Component interface
constant LeafNode (line 15) | LeafNode = iota
constant CompositeNode (line 16) | CompositeNode
function NewComponent (line 19) | func NewComponent(kind int, name string) Component {
type component (line 32) | type component struct
method Parent (line 37) | func (c *component) Parent() Component {
method SetParent (line 41) | func (c *component) SetParent(parent Component) {
method Name (line 45) | func (c *component) Name() string {
method SetName (line 49) | func (c *component) SetName(name string) {
method AddChild (line 53) | func (c *component) AddChild(Component) {}
method Print (line 55) | func (c *component) Print(string) {}
type Leaf (line 57) | type Leaf struct
method Print (line 65) | func (c *Leaf) Print(pre string) {
function NewLeaf (line 61) | func NewLeaf() *Leaf {
type Composite (line 69) | type Composite struct
method AddChild (line 80) | func (c *Composite) AddChild(child Component) {
method Print (line 85) | func (c *Composite) Print(pre string) {
function NewComposite (line 74) | func NewComposite() *Composite {
FILE: 13_composite/composite_test.go
function ExampleComposite (line 3) | func ExampleComposite() {
FILE: 14_template_method/templatemethod.go
type Downloader (line 5) | type Downloader interface
type template (line 9) | type template struct
method Download (line 25) | func (t *template) Download(uri string) {
method save (line 33) | func (t *template) save() {
type implement (line 14) | type implement interface
function newTemplate (line 19) | func newTemplate(impl implement) *template {
type HTTPDownloader (line 37) | type HTTPDownloader struct
method download (line 48) | func (d *HTTPDownloader) download() {
method save (line 52) | func (*HTTPDownloader) save() {
function NewHTTPDownloader (line 41) | func NewHTTPDownloader() Downloader {
type FTPDownloader (line 56) | type FTPDownloader struct
method download (line 67) | func (d *FTPDownloader) download() {
function NewFTPDownloader (line 60) | func NewFTPDownloader() Downloader {
FILE: 14_template_method/templatemethod_test.go
function ExampleHTTPDownloader (line 3) | func ExampleHTTPDownloader() {
function ExampleFTPDownloader (line 14) | func ExampleFTPDownloader() {
FILE: 15_strategy/strategy.go
type Payment (line 5) | type Payment struct
method Pay (line 26) | func (p *Payment) Pay() {
type PaymentContext (line 10) | type PaymentContext struct
function NewPayment (line 15) | func NewPayment(name, cardid string, money int, strategy PaymentStrategy...
type PaymentStrategy (line 30) | type PaymentStrategy interface
type Cash (line 34) | type Cash struct
method Pay (line 36) | func (*Cash) Pay(ctx *PaymentContext) {
type Bank (line 40) | type Bank struct
method Pay (line 42) | func (*Bank) Pay(ctx *PaymentContext) {
FILE: 15_strategy/strategy_test.go
function ExamplePayByCash (line 3) | func ExamplePayByCash() {
function ExamplePayByBank (line 10) | func ExamplePayByBank() {
FILE: 16_state/state.go
type Week (line 5) | type Week interface
type DayContext (line 10) | type DayContext struct
method Today (line 20) | func (d *DayContext) Today() {
method Next (line 24) | func (d *DayContext) Next() {
function NewDayContext (line 14) | func NewDayContext() *DayContext {
type Sunday (line 28) | type Sunday struct
method Today (line 30) | func (*Sunday) Today() {
method Next (line 34) | func (*Sunday) Next(ctx *DayContext) {
type Monday (line 38) | type Monday struct
method Today (line 40) | func (*Monday) Today() {
method Next (line 44) | func (*Monday) Next(ctx *DayContext) {
type Tuesday (line 48) | type Tuesday struct
method Today (line 50) | func (*Tuesday) Today() {
method Next (line 54) | func (*Tuesday) Next(ctx *DayContext) {
type Wednesday (line 58) | type Wednesday struct
method Today (line 60) | func (*Wednesday) Today() {
method Next (line 64) | func (*Wednesday) Next(ctx *DayContext) {
type Thursday (line 68) | type Thursday struct
method Today (line 70) | func (*Thursday) Today() {
method Next (line 74) | func (*Thursday) Next(ctx *DayContext) {
type Friday (line 78) | type Friday struct
method Today (line 80) | func (*Friday) Today() {
method Next (line 84) | func (*Friday) Next(ctx *DayContext) {
type Saturday (line 88) | type Saturday struct
method Today (line 90) | func (*Saturday) Today() {
method Next (line 94) | func (*Saturday) Next(ctx *DayContext) {
FILE: 16_state/state_test.go
function ExampleWeek (line 3) | func ExampleWeek() {
FILE: 17_memento/memento.go
type Memento (line 5) | type Memento interface
type Game (line 7) | type Game struct
method Play (line 15) | func (g *Game) Play(mpDelta, hpDelta int) {
method Save (line 20) | func (g *Game) Save() Memento {
method Load (line 27) | func (g *Game) Load(m Memento) {
method Status (line 33) | func (g *Game) Status() {
type gameMemento (line 11) | type gameMemento struct
FILE: 17_memento/memento_test.go
function ExampleGame (line 3) | func ExampleGame() {
FILE: 18_flyweight/flyweight.go
type ImageFlyweightFactory (line 5) | type ImageFlyweightFactory struct
method Get (line 20) | func (f *ImageFlyweightFactory) Get(filename string) *ImageFlyweight {
function GetImageFlyweightFactory (line 11) | func GetImageFlyweightFactory() *ImageFlyweightFactory {
type ImageFlyweight (line 30) | type ImageFlyweight struct
method Data (line 42) | func (i *ImageFlyweight) Data() string {
function NewImageFlyweight (line 34) | func NewImageFlyweight(filename string) *ImageFlyweight {
type ImageViewer (line 46) | type ImageViewer struct
method Display (line 57) | func (i *ImageViewer) Display() {
function NewImageViewer (line 50) | func NewImageViewer(filename string) *ImageViewer {
FILE: 18_flyweight/flyweight_test.go
function ExampleFlyweight (line 5) | func ExampleFlyweight() {
function TestFlyweight (line 12) | func TestFlyweight(t *testing.T) {
FILE: 19_interpreter/interpreter.go
type Node (line 8) | type Node interface
type ValNode (line 12) | type ValNode struct
method Interpret (line 16) | func (n *ValNode) Interpret() int {
type AddNode (line 20) | type AddNode struct
method Interpret (line 24) | func (n *AddNode) Interpret() int {
type MinNode (line 28) | type MinNode struct
method Interpret (line 32) | func (n *MinNode) Interpret() int {
type Parser (line 36) | type Parser struct
method Parse (line 42) | func (p *Parser) Parse(exp string) {
method newAddNode (line 60) | func (p *Parser) newAddNode() Node {
method newMinNode (line 68) | func (p *Parser) newMinNode() Node {
method newValNode (line 76) | func (p *Parser) newValNode() Node {
method Result (line 84) | func (p *Parser) Result() Node {
FILE: 19_interpreter/interpreter_test.go
function TestInterpreter (line 5) | func TestInterpreter(t *testing.T) {
FILE: 20_decorator/decorator.go
type Component (line 3) | type Component interface
type ConcreteComponent (line 7) | type ConcreteComponent struct
method Calc (line 9) | func (*ConcreteComponent) Calc() int {
type MulDecorator (line 13) | type MulDecorator struct
method Calc (line 25) | func (d *MulDecorator) Calc() int {
function WrapMulDecorator (line 18) | func WrapMulDecorator(c Component, num int) Component {
type AddDecorator (line 29) | type AddDecorator struct
method Calc (line 41) | func (d *AddDecorator) Calc() int {
function WrapAddDecorator (line 34) | func WrapAddDecorator(c Component, num int) Component {
FILE: 20_decorator/decorator_test.go
function ExampleDecorator (line 5) | func ExampleDecorator() {
FILE: 21_chain_of_responsibility/chain.go
type Manager (line 5) | type Manager interface
type RequestChain (line 10) | type RequestChain struct
method SetSuccessor (line 15) | func (r *RequestChain) SetSuccessor(m *RequestChain) {
method HandleFeeRequest (line 19) | func (r *RequestChain) HandleFeeRequest(name string, money int) bool {
method HaveRight (line 29) | func (r *RequestChain) HaveRight(money int) bool {
type ProjectManager (line 33) | type ProjectManager struct
method HaveRight (line 41) | func (*ProjectManager) HaveRight(money int) bool {
method HandleFeeRequest (line 45) | func (*ProjectManager) HandleFeeRequest(name string, money int) bool {
function NewProjectManagerChain (line 35) | func NewProjectManagerChain() *RequestChain {
type DepManager (line 54) | type DepManager struct
method HaveRight (line 62) | func (*DepManager) HaveRight(money int) bool {
method HandleFeeRequest (line 66) | func (*DepManager) HandleFeeRequest(name string, money int) bool {
function NewDepManagerChain (line 56) | func NewDepManagerChain() *RequestChain {
type GeneralManager (line 75) | type GeneralManager struct
method HaveRight (line 83) | func (*GeneralManager) HaveRight(money int) bool {
method HandleFeeRequest (line 87) | func (*GeneralManager) HandleFeeRequest(name string, money int) bool {
function NewGeneralManagerChain (line 77) | func NewGeneralManagerChain() *RequestChain {
FILE: 21_chain_of_responsibility/chain_test.go
function ExampleChain (line 3) | func ExampleChain() {
FILE: 22_bridge/bridge.go
type AbstractMessage (line 5) | type AbstractMessage interface
type MessageImplementer (line 9) | type MessageImplementer interface
type MessageSMS (line 13) | type MessageSMS struct
method Send (line 19) | func (*MessageSMS) Send(text, to string) {
function ViaSMS (line 15) | func ViaSMS() MessageImplementer {
type MessageEmail (line 23) | type MessageEmail struct
method Send (line 29) | func (*MessageEmail) Send(text, to string) {
function ViaEmail (line 25) | func ViaEmail() MessageImplementer {
type CommonMessage (line 33) | type CommonMessage struct
method SendMessage (line 43) | func (m *CommonMessage) SendMessage(text, to string) {
function NewCommonMessage (line 37) | func NewCommonMessage(method MessageImplementer) *CommonMessage {
type UrgencyMessage (line 47) | type UrgencyMessage struct
method SendMessage (line 57) | func (m *UrgencyMessage) SendMessage(text, to string) {
function NewUrgencyMessage (line 51) | func NewUrgencyMessage(method MessageImplementer) *UrgencyMessage {
FILE: 22_bridge/bridge_test.go
function ExampleCommonSMS (line 3) | func ExampleCommonSMS() {
function ExampleCommonEmail (line 10) | func ExampleCommonEmail() {
function ExampleUrgencySMS (line 17) | func ExampleUrgencySMS() {
function ExampleUrgencyEmail (line 24) | func ExampleUrgencyEmail() {
FILE: 23_visitor/visitor.go
type Customer (line 5) | type Customer interface
type Visitor (line 9) | type Visitor interface
type EnterpriseCustomer (line 13) | type EnterpriseCustomer struct
method Accept (line 37) | func (c *EnterpriseCustomer) Accept(visitor Visitor) {
type CustomerCol (line 17) | type CustomerCol struct
method Add (line 21) | func (c *CustomerCol) Add(customer Customer) {
method Accept (line 25) | func (c *CustomerCol) Accept(visitor Visitor) {
function NewEnterpriseCustomer (line 31) | func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
type IndividualCustomer (line 41) | type IndividualCustomer struct
method Accept (line 51) | func (c *IndividualCustomer) Accept(visitor Visitor) {
function NewIndividualCustomer (line 45) | func NewIndividualCustomer(name string) *IndividualCustomer {
type ServiceRequestVisitor (line 55) | type ServiceRequestVisitor struct
method Visit (line 57) | func (*ServiceRequestVisitor) Visit(customer Customer) {
type AnalysisVisitor (line 67) | type AnalysisVisitor struct
method Visit (line 69) | func (*AnalysisVisitor) Visit(customer Customer) {
FILE: 23_visitor/visitor_test.go
function ExampleRequestVisitor (line 3) | func ExampleRequestVisitor() {
function ExampleAnalysis (line 15) | func ExampleAnalysis() {
Condensed preview — 75 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (48K chars).
[
{
"path": ".gitignore",
"chars": 804,
"preview": "### https://raw.github.com/github/gitignore/23aad6abc4ed1aafb425f6e09334c4e35ad146ac/Global/Emacs.gitignore\n\n# -*- mode:"
},
{
"path": ".travis.yml",
"chars": 65,
"preview": "language: go\ngo:\n - 1.x\n - 1.11.x\nscript:\n - go test -v ./...\n"
},
{
"path": "00_simple_factory/README.md",
"chars": 167,
"preview": "# 简单工厂模式\n\n`go` 语言没有构造函数一说,所以一般会定义 `NewXXX` 函数来初始化相关类。\n`NewXXX` 函数返回接口时就是简单工厂模式,也就是说 `Golang` 的一般推荐做法就是简单工厂。\n\n在这个 `simple"
},
{
"path": "00_simple_factory/simple.go",
"chars": 576,
"preview": "package simplefactory\n\nimport \"fmt\"\n\n// API is interface\ntype API interface {\n\tSay(name string) string\n}\n\n// NewAPI retu"
},
{
"path": "00_simple_factory/simple_test.go",
"chars": 336,
"preview": "package simplefactory\n\nimport \"testing\"\n\n// TestType1 test get hiapi with factory\nfunc TestType1(t *testing.T) {\n\tapi :="
},
{
"path": "01_facade/README.md",
"chars": 150,
"preview": "# 外观模式\n\n`API` 为 `facade` 模块的外观接口,大部分代码使用此接口简化对 `facade` 类的访问。\n\n`facade` 模块同时暴露了 `a` 和 `b` 两个 `Module` 的 `NewXXX` 和 `inte"
},
{
"path": "01_facade/facade.go",
"chars": 919,
"preview": "package facade\n\nimport \"fmt\"\n\nfunc NewAPI() API {\n\treturn &apiImpl{\n\t\ta: NewAModuleAPI(),\n\t\tb: NewBModuleAPI(),\n\t}\n}\n\n//"
},
{
"path": "01_facade/facade_test.go",
"chars": 250,
"preview": "package facade\n\nimport \"testing\"\n\nvar expect = \"A module running\\nB module running\"\n\n// TestFacadeAPI ...\nfunc TestFacad"
},
{
"path": "02_adapter/README.md",
"chars": 193,
"preview": "# 适配器模式\n\n适配器模式用于转换一种接口适配另一种接口。\n\n实际使用中 `Adaptee` 一般为接口,并且使用工厂函数生成实例。\n\n在 `Adapter` 中匿名组合 `Adaptee` 接口,所以 `Adapter` 类也拥有 `S"
},
{
"path": "02_adapter/adapter.go",
"chars": 663,
"preview": "package adapter\n\n// Target 是适配的目标接口\ntype Target interface {\n\tRequest() string\n}\n\n// Adaptee 是被适配的目标接口\ntype Adaptee inter"
},
{
"path": "02_adapter/adapter_test.go",
"chars": 255,
"preview": "package adapter\n\nimport \"testing\"\n\nvar expect = \"adaptee method\"\n\nfunc TestAdapter(t *testing.T) {\n\tadaptee := NewAdapte"
},
{
"path": "03_singleton/README.md",
"chars": 35,
"preview": "# 单例模式\n\n使用懒惰模式的单例模式,使用双重检查加锁保证线程安全\n"
},
{
"path": "03_singleton/singleton.go",
"chars": 388,
"preview": "package singleton\n\nimport \"sync\"\n\n// Singleton 是单例模式接口,导出的\n// 通过该接口可以避免 GetInstance 返回一个包私有类型的指针\ntype Singleton interfac"
},
{
"path": "03_singleton/singleton_test.go",
"chars": 701,
"preview": "package singleton\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\nconst parCount = 100\n\nfunc TestSingleton(t *testing.T) {\n\tins1 := GetI"
},
{
"path": "04_factory_method/README.md",
"chars": 62,
"preview": "# 工厂方法模式\n\n工厂方法模式使用子类的方式延迟生成对象到子类中实现。\n\n`Go` 中不存在继承 所以使用匿名组合来实现\n"
},
{
"path": "04_factory_method/factorymethod.go",
"chars": 1079,
"preview": "package factorymethod\n\n// Operator 是被封装的实际类接口\ntype Operator interface {\n\tSetA(int)\n\tSetB(int)\n\tResult() int\n}\n\n// Operat"
},
{
"path": "04_factory_method/factorymethod_test.go",
"chars": 475,
"preview": "package factorymethod\n\nimport \"testing\"\n\nfunc compute(factory OperatorFactory, a, b int) int {\n\top := factory.Create()\n\t"
},
{
"path": "05_abstract_factory/README.md",
"chars": 171,
"preview": "# 抽象工厂模式\n\n抽象工厂模式用于生成产品族的工厂,所生成的对象是有关联的。\n\n如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。\n\n比如本例子中使用 `RDB` 和 `XML` 存储订单信息,抽象工厂分别能生成相关的主订单信息和订单"
},
{
"path": "05_abstract_factory/abstractfactory.go",
"chars": 1388,
"preview": "package abstractfactory\n\nimport \"fmt\"\n\n// OrderMainDAO 为订单主记录\ntype OrderMainDAO interface {\n\tSaveOrderMain()\n}\n\n// Order"
},
{
"path": "05_abstract_factory/abstractfactory_test.go",
"chars": 485,
"preview": "package abstractfactory\n\nfunc getMainAndDetail(factory DAOFactory) {\n\tfactory.CreateOrderMainDAO().SaveOrderMain()\n\tfact"
},
{
"path": "06_builder/builder.go",
"chars": 840,
"preview": "package builder\n\n// Builder 是生成器接口\ntype Builder interface {\n\tPart1()\n\tPart2()\n\tPart3()\n}\n\ntype Director struct {\n\tbuilde"
},
{
"path": "06_builder/builder_test.go",
"chars": 470,
"preview": "package builder\n\nimport \"testing\"\n\nfunc TestBuilder1(t *testing.T) {\n\tbuilder := &Builder1{}\n\tdirector := NewDirector(bu"
},
{
"path": "07_prototype/README.md",
"chars": 122,
"preview": "# 原型模式\n\n原型模式使对象能复制自身,并且暴露到接口中,使客户端面向接口编程时,不知道接口实际对象的情况下生成新的对象。\n\n原型模式配合原型管理器使用,使得客户端在不知道具体类的情况下,通过接口管理器得到新的实例,并且包含部分预设定配置"
},
{
"path": "07_prototype/prototype.go",
"chars": 478,
"preview": "package prototype\n\n// Cloneable 是原型对象需要实现的接口\ntype Cloneable interface {\n\tClone() Cloneable\n}\n\ntype PrototypeManager stru"
},
{
"path": "07_prototype/prototype_test.go",
"chars": 653,
"preview": "package prototype\n\nimport \"testing\"\n\nvar manager *PrototypeManager\n\ntype Type1 struct {\n\tname string\n}\n\nfunc (t *Type1) "
},
{
"path": "08_mediator/README.md",
"chars": 97,
"preview": "# 中介者模式\n\n中介者模式封装对象之间互交,使依赖变的简单,并且使复杂互交简单化,封装在中介者中。\n\n例子中的中介者使用单例模式生成中介者。\n\n中介者的change使用switch判断类型。\n"
},
{
"path": "08_mediator/mediator.go",
"chars": 1268,
"preview": "package mediator\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype CDDriver struct {\n\tData string\n}\n\nfunc (c *CDDriver) ReadData() {\n\t"
},
{
"path": "08_mediator/mediator_test.go",
"chars": 759,
"preview": "package mediator\n\nimport \"testing\"\n\nfunc TestMediator(t *testing.T) {\n\tmediator := GetMediatorInstance()\n\tmediator.CD = "
},
{
"path": "09_proxy/README.md",
"chars": 122,
"preview": "# 代理模式\n\n代理模式用于延迟处理操作或者在进行实际操作前后进行其它处理。\n\n## 代理模式的常见用法有\n\n* 虚代理\n* COW代理\n* 远程代理\n* 保护代理\n* Cache 代理\n* 防火墙代理\n* 同步代理\n* 智能指引\n\n等。。"
},
{
"path": "09_proxy/proxy.go",
"chars": 368,
"preview": "package proxy\n\ntype Subject interface {\n\tDo() string\n}\n\ntype RealSubject struct{}\n\nfunc (RealSubject) Do() string {\n\tret"
},
{
"path": "09_proxy/proxy_test.go",
"chars": 162,
"preview": "package proxy\n\nimport \"testing\"\n\nfunc TestProxy(t *testing.T) {\n\tvar sub Subject\n\tsub = &Proxy{}\n\n\tres := sub.Do()\n\n\tif "
},
{
"path": "10_observer/README.md",
"chars": 63,
"preview": "# 观察者模式\n\n观察者模式用于触发联动。\n\n一个对象的改变会触发其它观察者的相关动作,而此对象无需关心连动对象的具体实现。\n"
},
{
"path": "10_observer/observer.go",
"chars": 681,
"preview": "package observer\n\nimport \"fmt\"\n\ntype Subject struct {\n\tobservers []Observer\n\tcontext string\n}\n\nfunc NewSubject() *Subj"
},
{
"path": "10_observer/observer_test.go",
"chars": 399,
"preview": "package observer\n\nfunc ExampleObserver() {\n\tsubject := NewSubject()\n\treader1 := NewReader(\"reader1\")\n\treader2 := NewRead"
},
{
"path": "11_command/README.md",
"chars": 290,
"preview": "# 命令模式\n\n命令模式本质是把某个对象的方法调用封装到对象中,方便传递、存储、调用。\n\n示例中把主板单中的启动(start)方法和重启(reboot)方法封装为命令对象,再传递到主机(box)对象中。于两个按钮进行绑定:\n\n* 第一个机箱"
},
{
"path": "11_command/command.go",
"chars": 888,
"preview": "package command\n\nimport \"fmt\"\n\ntype Command interface {\n\tExecute()\n}\n\ntype StartCommand struct {\n\tmb *MotherBoard\n}\n\nfun"
},
{
"path": "11_command/command_test.go",
"chars": 411,
"preview": "package command\n\nfunc ExampleCommand() {\n\tmb := &MotherBoard{}\n\tstartCommand := NewStartCommand(mb)\n\trebootCommand := Ne"
},
{
"path": "12_iterator/README.md",
"chars": 84,
"preview": "# 迭代器模式\n\n迭代器模式用于使用相同方式送代不同类型集合或者隐藏集合类型的具体实现。\n\n可以使用迭代器模式使遍历同时应用送代策略,如请求新对象、过滤、处理对象等。\n"
},
{
"path": "12_iterator/iterator.go",
"chars": 840,
"preview": "package iterator\n\nimport \"fmt\"\n\ntype Aggregate interface {\n\tIterator() Iterator\n}\n\ntype Iterator interface {\n\tFirst()\n\tI"
},
{
"path": "12_iterator/iterator_test.go",
"chars": 212,
"preview": "package iterator\n\nfunc ExampleIterator() {\n\tvar aggregate Aggregate\n\taggregate = NewNumbers(1, 10)\n\n\tIteratorPrint(aggre"
},
{
"path": "13_composite/README.md",
"chars": 88,
"preview": "# 组合模式\n\n组合模式统一对象和对象集,使得使用相同接口使用对象和对象集。\n\n组合模式常用于树状结构,用于统一叶子节点和树节点的访问,并且可以用于应用某一操作到所有子节点。\n"
},
{
"path": "13_composite/composite.go",
"chars": 1352,
"preview": "package composite\n\nimport \"fmt\"\n\ntype Component interface {\n\tParent() Component\n\tSetParent(Component)\n\tName() string\n\tSe"
},
{
"path": "13_composite/composite_test.go",
"chars": 528,
"preview": "package composite\n\nfunc ExampleComposite() {\n\troot := NewComponent(CompositeNode, \"root\")\n\tc1 := NewComponent(CompositeN"
},
{
"path": "14_template_method/README.md",
"chars": 220,
"preview": "# 模版方法模式\n\n模版方法模式使用继承机制,把通用步骤和通用方法放到父类中,把具体实现延迟到子类中实现。使得实现符合开闭原则。\n\n如实例代码中通用步骤在父类中实现(`准备`、`下载`、`保存`、`收尾`)下载和保存的具体实现留到子类中,并"
},
{
"path": "14_template_method/templatemethod.go",
"chars": 1150,
"preview": "package templatemethod\n\nimport \"fmt\"\n\ntype Downloader interface {\n\tDownload(uri string)\n}\n\ntype template struct {\n\timple"
},
{
"path": "14_template_method/templatemethod_test.go",
"chars": 535,
"preview": "package templatemethod\n\nfunc ExampleHTTPDownloader() {\n\tvar downloader Downloader = NewHTTPDownloader()\n\n\tdownloader.Dow"
},
{
"path": "15_strategy/README.md",
"chars": 46,
"preview": "# 策略模式\n\n定义一系列算法,让这些算法在运行时可以互换,使得分离算法,符合开闭原则。\n\n"
},
{
"path": "15_strategy/strategy.go",
"chars": 777,
"preview": "package strategy\n\nimport \"fmt\"\n\ntype Payment struct {\n\tcontext *PaymentContext\n\tstrategy PaymentStrategy\n}\n\ntype Paymen"
},
{
"path": "15_strategy/strategy_test.go",
"chars": 298,
"preview": "package strategy\n\nfunc ExamplePayByCash() {\n\tpayment := NewPayment(\"Ada\", \"\", 123, &Cash{})\n\tpayment.Pay()\n\t// Output:\n\t"
},
{
"path": "16_state/README.md",
"chars": 23,
"preview": "# 状态模式\n\n状态模式用于分离状态和行为。\n"
},
{
"path": "16_state/state.go",
"chars": 1317,
"preview": "package state\n\nimport \"fmt\"\n\ntype Week interface {\n\tToday()\n\tNext(*DayContext)\n}\n\ntype DayContext struct {\n\ttoday Week\n}"
},
{
"path": "16_state/state_test.go",
"chars": 273,
"preview": "package state\n\nfunc ExampleWeek() {\n\tctx := NewDayContext()\n\ttodayAndNext := func() {\n\t\tctx.Today()\n\t\tctx.Next()\n\t}\n\n\tfo"
},
{
"path": "17_memento/README.md",
"chars": 110,
"preview": "# 备忘录模式\n\n备忘录模式用于保存程序内部状态到外部,又不希望暴露内部状态的情形。\n\n程序内部状态使用窄接口传递给外部进行存储,从而不暴露程序实现细节。\n\n备忘录模式同时可以离线保存内部状态,如保存到数据库,文件等。\n"
},
{
"path": "17_memento/memento.go",
"chars": 463,
"preview": "package memento\n\nimport \"fmt\"\n\ntype Memento interface{}\n\ntype Game struct {\n\thp, mp int\n}\n\ntype gameMemento struct {\n\thp"
},
{
"path": "17_memento/memento_test.go",
"chars": 278,
"preview": "package memento\n\nfunc ExampleGame() {\n\tgame := &Game{\n\t\thp: 10,\n\t\tmp: 10,\n\t}\n\n\tgame.Status()\n\tprogress := game.Save()\n\n\t"
},
{
"path": "18_flyweight/README.md",
"chars": 70,
"preview": "# 享元模式\n\n享元模式从对象中剥离出不发生改变且多个实例需要的重复数据,独立出一个享元,使多个对象共享,从而节省内存以及减少对象数量。\n\n"
},
{
"path": "18_flyweight/flyweight.go",
"chars": 1099,
"preview": "package flyweight\n\nimport \"fmt\"\n\ntype ImageFlyweightFactory struct {\n\tmaps map[string]*ImageFlyweight\n}\n\nvar imageFactor"
},
{
"path": "18_flyweight/flyweight_test.go",
"chars": 360,
"preview": "package flyweight\n\nimport \"testing\"\n\nfunc ExampleFlyweight() {\n\tviewer := NewImageViewer(\"image1.png\")\n\tviewer.Display()"
},
{
"path": "19_interpreter/README.md",
"chars": 131,
"preview": "# 解释器模式\n\n解释器模式定义一套语言文法,并设计该语言解释器,使用户能使用特定文法控制解释器行为。\n\n解释器模式的意义在于,它分离多种复杂功能的实现,每个功能只需关注自身的解释。\n\n对于调用者不用关心内部的解释器的工作,只需要用简单的方"
},
{
"path": "19_interpreter/interpreter.go",
"chars": 1180,
"preview": "package interpreter\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype Node interface {\n\tInterpret() int\n}\n\ntype ValNode struct {\n\t"
},
{
"path": "19_interpreter/interpreter_test.go",
"chars": 239,
"preview": "package interpreter\n\nimport \"testing\"\n\nfunc TestInterpreter(t *testing.T) {\n\tp := &Parser{}\n\tp.Parse(\"1 + 2 + 3 - 4 + 5 "
},
{
"path": "20_decorator/README.md",
"chars": 94,
"preview": "# 装饰模式\n\n装饰模式使用对象组合的方式动态改变或增加对象行为。\n\nGo语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。\n\n使用匿名组合,在装饰器中不必显式定义转调原对象方法。\n"
},
{
"path": "20_decorator/decorator.go",
"chars": 631,
"preview": "package decorator\n\ntype Component interface {\n\tCalc() int\n}\n\ntype ConcreteComponent struct{}\n\nfunc (*ConcreteComponent) "
},
{
"path": "20_decorator/decorator_test.go",
"chars": 228,
"preview": "package decorator\n\nimport \"fmt\"\n\nfunc ExampleDecorator() {\n\tvar c Component = &ConcreteComponent{}\n\tc = WrapAddDecorator"
},
{
"path": "21_chain_of_responsibility/README.md",
"chars": 186,
"preview": "# 职责链模式\n\n职责链模式用于分离不同职责,并且动态组合相关职责。\n\nGolang实现职责链模式时候,因为没有继承的支持,使用链对象包涵职责的方式,即:\n\n* 链对象包含当前职责对象以及下一个职责链。\n* 职责对象提供接口表示是否能处理对"
},
{
"path": "21_chain_of_responsibility/chain.go",
"chars": 2003,
"preview": "package chain\n\nimport \"fmt\"\n\ntype Manager interface {\n\tHaveRight(money int) bool\n\tHandleFeeRequest(name string, money in"
},
{
"path": "21_chain_of_responsibility/chain_test.go",
"chars": 537,
"preview": "package chain\n\nfunc ExampleChain() {\n\tc1 := NewProjectManagerChain()\n\tc2 := NewDepManagerChain()\n\tc3 := NewGeneralManage"
},
{
"path": "22_bridge/README.md",
"chars": 101,
"preview": "# 桥接模式\n\n桥接模式分离抽象部分和实现部分。使得两部分独立扩展。\n\n桥接模式类似于策略模式,区别在于策略模式封装一系列算法使得算法可以互相替换。\n\n策略模式使抽象部分和实现部分分离,可以独立变化。\n"
},
{
"path": "22_bridge/bridge.go",
"chars": 1069,
"preview": "package bridge\n\nimport \"fmt\"\n\ntype AbstractMessage interface {\n\tSendMessage(text, to string)\n}\n\ntype MessageImplementer "
},
{
"path": "22_bridge/bridge_test.go",
"chars": 655,
"preview": "package bridge\n\nfunc ExampleCommonSMS() {\n\tm := NewCommonMessage(ViaSMS())\n\tm.SendMessage(\"have a drink?\", \"bob\")\n\t// Ou"
},
{
"path": "23_visitor/README.md",
"chars": 90,
"preview": "# 访问者模式\n\n访问者模式可以给一系列对象透明的添加功能,并且把相关代码封装到一个类中。\n\n对象只要预留访问者接口`Accept`则后期为对象添加功能的时候就不需要改动对象。\n\n"
},
{
"path": "23_visitor/visitor.go",
"chars": 1402,
"preview": "package visitor\n\nimport \"fmt\"\n\ntype Customer interface {\n\tAccept(Visitor)\n}\n\ntype Visitor interface {\n\tVisit(Customer)\n}"
},
{
"path": "23_visitor/visitor_test.go",
"chars": 662,
"preview": "package visitor\n\nfunc ExampleRequestVisitor() {\n\tc := &CustomerCol{}\n\tc.Add(NewEnterpriseCustomer(\"A company\"))\n\tc.Add(N"
},
{
"path": "LICENSE",
"chars": 1085,
"preview": "MIT License\n\nCopyright (c) 2020 Senghoo Kim And Contributors\n\nPermission is hereby granted, free of charge, to any perso"
},
{
"path": "README.md",
"chars": 2522,
"preview": "# Go 语言设计模式\n\n[](https://travis-ci."
}
]
About this extraction
This page contains the full source code of the senghoo/golang-design-pattern GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 75 files (39.2 KB), approximately 14.0k tokens, and a symbol index with 322 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.