[
  {
    "path": ".gitignore",
    "content": "### https://raw.github.com/github/gitignore/23aad6abc4ed1aafb425f6e09334c4e35ad146ac/Global/Emacs.gitignore\n\n# -*- mode: gitignore; -*-\n*~\n\\#*\\#\n/.emacs.desktop\n/.emacs.desktop.lock\n*.elc\nauto-save-list\ntramp\n.\\#*\n\n# Org-mode\n.org-id-locations\n*_archive\n\n# flymake-mode\n*_flymake.*\n\n# eshell files\n/eshell/history\n/eshell/lastdir\n\n# elpa packages\n/elpa/\n\n# reftex files\n*.rel\n\n# AUCTeX auto folder\n/auto/\n\n# cask packages\n.cask/\n\n\n### https://raw.github.com/github/gitignore/23aad6abc4ed1aafb425f6e09334c4e35ad146ac/Go.gitignore\n\n# Compiled Object files, Static and Dynamic libs (Shared Objects)\n*.o\n*.a\n*.so\n\n# Folders\n_obj\n_test\n\n# Architecture specific extensions/prefixes\n*.[568vq]\n[568vq].out\n\n*.cgo1.go\n*.cgo2.c\n_cgo_defun.c\n_cgo_gotypes.go\n_cgo_export.*\n\n_testmain.go\n\n*.exe\n*.test\n*.prof\n\n\n.idea\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: go\ngo:\n  - 1.x\n  - 1.11.x\nscript:\n  - go test -v ./...\n"
  },
  {
    "path": "00_simple_factory/README.md",
    "content": "# 简单工厂模式\n\n`go` 语言没有构造函数一说，所以一般会定义 `NewXXX` 函数来初始化相关类。\n`NewXXX` 函数返回接口时就是简单工厂模式，也就是说 `Golang` 的一般推荐做法就是简单工厂。\n\n在这个 `simplefactory` 包中只有API 接口和 `NewAPI` 函数为包外可见，封装了实现细节。\n"
  },
  {
    "path": "00_simple_factory/simple.go",
    "content": "package simplefactory\n\nimport \"fmt\"\n\n// API is interface\ntype API interface {\n\tSay(name string) string\n}\n\n// NewAPI return Api instance by type\nfunc NewAPI(t int) API {\n\tif t == 1 {\n\t\treturn &hiAPI{}\n\t} else if t == 2 {\n\t\treturn &helloAPI{}\n\t}\n\treturn nil\n}\n\n// hiAPI is one of API implement\ntype hiAPI struct{}\n\n// Say hi to name\nfunc (*hiAPI) Say(name string) string {\n\treturn fmt.Sprintf(\"Hi, %s\", name)\n}\n\n// helloAPI is another API implement\ntype helloAPI struct{}\n\n// Say hello to name\nfunc (*helloAPI) Say(name string) string {\n\treturn fmt.Sprintf(\"Hello, %s\", name)\n}\n"
  },
  {
    "path": "00_simple_factory/simple_test.go",
    "content": "package simplefactory\n\nimport \"testing\"\n\n// TestType1 test get hiapi with factory\nfunc TestType1(t *testing.T) {\n\tapi := NewAPI(1)\n\ts := api.Say(\"Tom\")\n\tif s != \"Hi, Tom\" {\n\t\tt.Fatal(\"Type1 test fail\")\n\t}\n}\n\nfunc TestType2(t *testing.T) {\n\tapi := NewAPI(2)\n\ts := api.Say(\"Tom\")\n\tif s != \"Hello, Tom\" {\n\t\tt.Fatal(\"Type2 test fail\")\n\t}\n}\n"
  },
  {
    "path": "01_facade/README.md",
    "content": "# 外观模式\n\n`API` 为 `facade` 模块的外观接口，大部分代码使用此接口简化对 `facade` 类的访问。\n\n`facade` 模块同时暴露了 `a` 和 `b` 两个 `Module` 的 `NewXXX` 和 `interface`，其它代码如果需要使用细节功能时可以直接调用。\n"
  },
  {
    "path": "01_facade/facade.go",
    "content": "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// API is facade interface of facade package\ntype API interface {\n\tTest() string\n}\n\n// apiImpl facade implement\ntype apiImpl struct {\n\ta AModuleAPI\n\tb BModuleAPI\n}\n\nfunc (a *apiImpl) Test() string {\n\taRet := a.a.TestA()\n\tbRet := a.b.TestB()\n\treturn fmt.Sprintf(\"%s\\n%s\", aRet, bRet)\n}\n\n// NewAModuleAPI return new AModuleAPI\nfunc NewAModuleAPI() AModuleAPI {\n\treturn &aModuleImpl{}\n}\n\n// AModuleAPI ...\ntype AModuleAPI interface {\n\tTestA() string\n}\n\ntype aModuleImpl struct{}\n\nfunc (*aModuleImpl) TestA() string {\n\treturn \"A module running\"\n}\n\n// NewBModuleAPI return new BModuleAPI\nfunc NewBModuleAPI() BModuleAPI {\n\treturn &bModuleImpl{}\n}\n\n// BModuleAPI ...\ntype BModuleAPI interface {\n\tTestB() string\n}\n\ntype bModuleImpl struct{}\n\nfunc (*bModuleImpl) TestB() string {\n\treturn \"B module running\"\n}\n"
  },
  {
    "path": "01_facade/facade_test.go",
    "content": "package facade\n\nimport \"testing\"\n\nvar expect = \"A module running\\nB module running\"\n\n// TestFacadeAPI ...\nfunc TestFacadeAPI(t *testing.T) {\n\tapi := NewAPI()\n\tret := api.Test()\n\tif ret != expect {\n\t\tt.Fatalf(\"expect %s, return %s\", expect, ret)\n\t}\n}\n"
  },
  {
    "path": "02_adapter/README.md",
    "content": "# 适配器模式\n\n适配器模式用于转换一种接口适配另一种接口。\n\n实际使用中 `Adaptee` 一般为接口，并且使用工厂函数生成实例。\n\n在 `Adapter` 中匿名组合 `Adaptee` 接口，所以 `Adapter` 类也拥有 `SpecificRequest` 实例方法，又因为 `Go` 语言中非入侵式接口特征，其实 `Adapter` 也适配 `Adaptee`\n接口。\n"
  },
  {
    "path": "02_adapter/adapter.go",
    "content": "package adapter\n\n// Target 是适配的目标接口\ntype Target interface {\n\tRequest() string\n}\n\n// Adaptee 是被适配的目标接口\ntype Adaptee interface {\n\tSpecificRequest() string\n}\n\n// NewAdaptee 是被适配接口的工厂函数\nfunc NewAdaptee() Adaptee {\n\treturn &adapteeImpl{}\n}\n\n// AdapteeImpl 是被适配的目标类\ntype adapteeImpl struct{}\n\n// SpecificRequest 是目标类的一个方法\nfunc (*adapteeImpl) SpecificRequest() string {\n\treturn \"adaptee method\"\n}\n\n// NewAdapter 是Adapter的工厂函数\nfunc NewAdapter(adaptee Adaptee) Target {\n\treturn &adapter{\n\t\tAdaptee: adaptee,\n\t}\n}\n\n// Adapter 是转换Adaptee为Target接口的适配器\ntype adapter struct {\n\tAdaptee\n}\n\n// Request 实现Target接口\nfunc (a *adapter) Request() string {\n\treturn a.SpecificRequest()\n}\n"
  },
  {
    "path": "02_adapter/adapter_test.go",
    "content": "package adapter\n\nimport \"testing\"\n\nvar expect = \"adaptee method\"\n\nfunc TestAdapter(t *testing.T) {\n\tadaptee := NewAdaptee()\n\ttarget := NewAdapter(adaptee)\n\tres := target.Request()\n\tif res != expect {\n\t\tt.Fatalf(\"expect: %s, actual: %s\", expect, res)\n\t}\n}\n"
  },
  {
    "path": "03_singleton/README.md",
    "content": "# 单例模式\n\n使用懒惰模式的单例模式，使用双重检查加锁保证线程安全\n"
  },
  {
    "path": "03_singleton/singleton.go",
    "content": "package singleton\n\nimport \"sync\"\n\n// Singleton 是单例模式接口，导出的\n// 通过该接口可以避免 GetInstance 返回一个包私有类型的指针\ntype Singleton interface {\n\tfoo()\n}\n\n// singleton 是单例模式类，包私有的\ntype singleton struct{}\n\nfunc (s singleton) foo() {}\n\nvar (\n\tinstance *singleton\n\tonce     sync.Once\n)\n\n// GetInstance 用于获取单例模式对象\nfunc GetInstance() Singleton {\n\tonce.Do(func() {\n\t\tinstance = &singleton{}\n\t})\n\n\treturn instance\n}\n"
  },
  {
    "path": "03_singleton/singleton_test.go",
    "content": "package singleton\n\nimport (\n\t\"sync\"\n\t\"testing\"\n)\n\nconst parCount = 100\n\nfunc TestSingleton(t *testing.T) {\n\tins1 := GetInstance()\n\tins2 := GetInstance()\n\tif ins1 != ins2 {\n\t\tt.Fatal(\"instance is not equal\")\n\t}\n}\n\nfunc TestParallelSingleton(t *testing.T) {\n\tstart := make(chan struct{})\n\twg := sync.WaitGroup{}\n\twg.Add(parCount)\n\tinstances := [parCount]Singleton{}\n\tfor i := 0; i < parCount; i++ {\n\t\tgo func(index int) {\n\t\t\t// 协程阻塞，等待channel被关闭才能继续运行\n\t\t\t<-start\n\t\t\tinstances[index] = GetInstance()\n\t\t\twg.Done()\n\t\t}(i)\n\t}\n\t// 关闭channel，所有协程同时开始运行，实现并行(parallel)\n\tclose(start)\n\twg.Wait()\n\tfor i := 1; i < parCount; i++ {\n\t\tif instances[i] != instances[i-1] {\n\t\t\tt.Fatal(\"instance is not equal\")\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "04_factory_method/README.md",
    "content": "# 工厂方法模式\n\n工厂方法模式使用子类的方式延迟生成对象到子类中实现。\n\n`Go` 中不存在继承 所以使用匿名组合来实现\n"
  },
  {
    "path": "04_factory_method/factorymethod.go",
    "content": "package factorymethod\n\n// Operator 是被封装的实际类接口\ntype Operator interface {\n\tSetA(int)\n\tSetB(int)\n\tResult() int\n}\n\n// OperatorFactory 是工厂接口\ntype OperatorFactory interface {\n\tCreate() Operator\n}\n\n// OperatorBase 是Operator 接口实现的基类，封装公用方法\ntype OperatorBase struct {\n\ta, b int\n}\n\n// SetA 设置 A\nfunc (o *OperatorBase) SetA(a int) {\n\to.a = a\n}\n\n// SetB 设置 B\nfunc (o *OperatorBase) SetB(b int) {\n\to.b = b\n}\n\n// PlusOperatorFactory 是 PlusOperator 的工厂类\ntype PlusOperatorFactory struct{}\n\nfunc (PlusOperatorFactory) Create() Operator {\n\treturn &PlusOperator{\n\t\tOperatorBase: &OperatorBase{},\n\t}\n}\n\n// PlusOperator Operator 的实际加法实现\ntype PlusOperator struct {\n\t*OperatorBase\n}\n\n// Result 获取结果\nfunc (o PlusOperator) Result() int {\n\treturn o.a + o.b\n}\n\n// MinusOperatorFactory 是 MinusOperator 的工厂类\ntype MinusOperatorFactory struct{}\n\nfunc (MinusOperatorFactory) Create() Operator {\n\treturn &MinusOperator{\n\t\tOperatorBase: &OperatorBase{},\n\t}\n}\n\n// MinusOperator Operator 的实际减法实现\ntype MinusOperator struct {\n\t*OperatorBase\n}\n\n// Result 获取结果\nfunc (o MinusOperator) Result() int {\n\treturn o.a - o.b\n}\n"
  },
  {
    "path": "04_factory_method/factorymethod_test.go",
    "content": "package factorymethod\n\nimport \"testing\"\n\nfunc compute(factory OperatorFactory, a, b int) int {\n\top := factory.Create()\n\top.SetA(a)\n\top.SetB(b)\n\treturn op.Result()\n}\n\nfunc TestOperator(t *testing.T) {\n\tvar (\n\t\tfactory OperatorFactory\n\t)\n\n\tfactory = PlusOperatorFactory{}\n\tif compute(factory, 1, 2) != 3 {\n\t\tt.Fatal(\"error with factory method pattern\")\n\t}\n\n\tfactory = MinusOperatorFactory{}\n\tif compute(factory, 4, 2) != 2 {\n\t\tt.Fatal(\"error with factory method pattern\")\n\t}\n}\n"
  },
  {
    "path": "05_abstract_factory/README.md",
    "content": "# 抽象工厂模式\n\n抽象工厂模式用于生成产品族的工厂，所生成的对象是有关联的。\n\n如果抽象工厂退化成生成的对象无关联则成为工厂函数模式。\n\n比如本例子中使用 `RDB` 和 `XML` 存储订单信息，抽象工厂分别能生成相关的主订单信息和订单详情信息。 如果业务逻辑中需要替换使用的时候只需要改动工厂函数相关的类就能替换使用不同的存储方式了。\n"
  },
  {
    "path": "05_abstract_factory/abstractfactory.go",
    "content": "package abstractfactory\n\nimport \"fmt\"\n\n// OrderMainDAO 为订单主记录\ntype OrderMainDAO interface {\n\tSaveOrderMain()\n}\n\n// OrderDetailDAO 为订单详情纪录\ntype OrderDetailDAO interface {\n\tSaveOrderDetail()\n}\n\n// DAOFactory DAO 抽象模式工厂接口\ntype DAOFactory interface {\n\tCreateOrderMainDAO() OrderMainDAO\n\tCreateOrderDetailDAO() OrderDetailDAO\n}\n\n// RDBMainDAO 关系型数据库的OrderMainDAO实现\ntype RDBMainDAO struct{}\n\n// SaveOrderMain ...\nfunc (*RDBMainDAO) SaveOrderMain() {\n\tfmt.Print(\"rdb main save\\n\")\n}\n\n// RDBDetailDAO 为关系型数据库的OrderDetailDAO实现\ntype RDBDetailDAO struct{}\n\n// SaveOrderDetail ...\nfunc (*RDBDetailDAO) SaveOrderDetail() {\n\tfmt.Print(\"rdb detail save\\n\")\n}\n\n// RDBDAOFactory 是RDB 抽象工厂实现\ntype RDBDAOFactory struct{}\n\nfunc (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {\n\treturn &RDBMainDAO{}\n}\n\nfunc (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {\n\treturn &RDBDetailDAO{}\n}\n\n// XMLMainDAO XML存储\ntype XMLMainDAO struct{}\n\n// SaveOrderMain ...\nfunc (*XMLMainDAO) SaveOrderMain() {\n\tfmt.Print(\"xml main save\\n\")\n}\n\n// XMLDetailDAO XML存储\ntype XMLDetailDAO struct{}\n\n// SaveOrderDetail ...\nfunc (*XMLDetailDAO) SaveOrderDetail() {\n\tfmt.Print(\"xml detail save\")\n}\n\n// XMLDAOFactory 是XML 抽象工厂实现\ntype XMLDAOFactory struct{}\n\nfunc (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO {\n\treturn &XMLMainDAO{}\n}\n\nfunc (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {\n\treturn &XMLDetailDAO{}\n}\n"
  },
  {
    "path": "05_abstract_factory/abstractfactory_test.go",
    "content": "package abstractfactory\n\nfunc getMainAndDetail(factory DAOFactory) {\n\tfactory.CreateOrderMainDAO().SaveOrderMain()\n\tfactory.CreateOrderDetailDAO().SaveOrderDetail()\n}\n\nfunc ExampleRdbFactory() {\n\tvar factory DAOFactory\n\tfactory = &RDBDAOFactory{}\n\tgetMainAndDetail(factory)\n\t// Output:\n\t// rdb main save\n\t// rdb detail save\n}\n\nfunc ExampleXmlFactory() {\n\tvar factory DAOFactory\n\tfactory = &XMLDAOFactory{}\n\tgetMainAndDetail(factory)\n\t// Output:\n\t// xml main save\n\t// xml detail save\n}\n"
  },
  {
    "path": "06_builder/builder.go",
    "content": "package builder\n\n// Builder 是生成器接口\ntype Builder interface {\n\tPart1()\n\tPart2()\n\tPart3()\n}\n\ntype Director struct {\n\tbuilder Builder\n}\n\n// NewDirector ...\nfunc NewDirector(builder Builder) *Director {\n\treturn &Director{\n\t\tbuilder: builder,\n\t}\n}\n\n// Construct Product\nfunc (d *Director) Construct() {\n\td.builder.Part1()\n\td.builder.Part2()\n\td.builder.Part3()\n}\n\ntype Builder1 struct {\n\tresult string\n}\n\nfunc (b *Builder1) Part1() {\n\tb.result += \"1\"\n}\n\nfunc (b *Builder1) Part2() {\n\tb.result += \"2\"\n}\n\nfunc (b *Builder1) Part3() {\n\tb.result += \"3\"\n}\n\nfunc (b *Builder1) GetResult() string {\n\treturn b.result\n}\n\ntype Builder2 struct {\n\tresult int\n}\n\nfunc (b *Builder2) Part1() {\n\tb.result += 1\n}\n\nfunc (b *Builder2) Part2() {\n\tb.result += 2\n}\n\nfunc (b *Builder2) Part3() {\n\tb.result += 3\n}\n\nfunc (b *Builder2) GetResult() int {\n\treturn b.result\n}\n"
  },
  {
    "path": "06_builder/builder_test.go",
    "content": "package builder\n\nimport \"testing\"\n\nfunc TestBuilder1(t *testing.T) {\n\tbuilder := &Builder1{}\n\tdirector := NewDirector(builder)\n\tdirector.Construct()\n\tres := builder.GetResult()\n\tif res != \"123\" {\n\t\tt.Fatalf(\"Builder1 fail expect 123 acture %s\", res)\n\t}\n}\n\nfunc TestBuilder2(t *testing.T) {\n\tbuilder := &Builder2{}\n\tdirector := NewDirector(builder)\n\tdirector.Construct()\n\tres := builder.GetResult()\n\tif res != 6 {\n\t\tt.Fatalf(\"Builder2 fail expect 6 acture %d\", res)\n\t}\n}\n"
  },
  {
    "path": "07_prototype/README.md",
    "content": "# 原型模式\n\n原型模式使对象能复制自身，并且暴露到接口中，使客户端面向接口编程时，不知道接口实际对象的情况下生成新的对象。\n\n原型模式配合原型管理器使用，使得客户端在不知道具体类的情况下，通过接口管理器得到新的实例，并且包含部分预设定配置。\n"
  },
  {
    "path": "07_prototype/prototype.go",
    "content": "package prototype\n\n// Cloneable 是原型对象需要实现的接口\ntype Cloneable interface {\n\tClone() Cloneable\n}\n\ntype PrototypeManager struct {\n\tprototypes map[string]Cloneable\n}\n\nfunc NewPrototypeManager() *PrototypeManager {\n\treturn &PrototypeManager{\n\t\tprototypes: make(map[string]Cloneable),\n\t}\n}\n\nfunc (p *PrototypeManager) Get(name string) Cloneable {\n\treturn p.prototypes[name].Clone()\n}\n\nfunc (p *PrototypeManager) Set(name string, prototype Cloneable) {\n\tp.prototypes[name] = prototype\n}\n"
  },
  {
    "path": "07_prototype/prototype_test.go",
    "content": "package prototype\n\nimport \"testing\"\n\nvar manager *PrototypeManager\n\ntype Type1 struct {\n\tname string\n}\n\nfunc (t *Type1) Clone() Cloneable {\n\ttc := *t\n\treturn &tc\n}\n\ntype Type2 struct {\n\tname string\n}\n\nfunc (t *Type2) Clone() Cloneable {\n\ttc := *t\n\treturn &tc\n}\n\nfunc TestClone(t *testing.T) {\n\tt1 := manager.Get(\"t1\")\n\n\tt2 := t1.Clone()\n\n\tif t1 == t2 {\n\t\tt.Fatal(\"error! get clone not working\")\n\t}\n}\n\nfunc TestCloneFromManager(t *testing.T) {\n\tc := manager.Get(\"t1\").Clone()\n\n\tt1 := c.(*Type1)\n\tif t1.name != \"type1\" {\n\t\tt.Fatal(\"error\")\n\t}\n\n}\n\nfunc init() {\n\tmanager = NewPrototypeManager()\n\n\tt1 := &Type1{\n\t\tname: \"type1\",\n\t}\n\tmanager.Set(\"t1\", t1)\n}\n"
  },
  {
    "path": "08_mediator/README.md",
    "content": "# 中介者模式\n\n中介者模式封装对象之间互交，使依赖变的简单，并且使复杂互交简单化，封装在中介者中。\n\n例子中的中介者使用单例模式生成中介者。\n\n中介者的change使用switch判断类型。\n"
  },
  {
    "path": "08_mediator/mediator.go",
    "content": "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\tc.Data = \"music,image\"\n\n\tfmt.Printf(\"CDDriver: reading data %s\\n\", c.Data)\n\tGetMediatorInstance().changed(c)\n}\n\ntype CPU struct {\n\tVideo string\n\tSound string\n}\n\nfunc (c *CPU) Process(data string) {\n\tsp := strings.Split(data, \",\")\n\tc.Sound = sp[0]\n\tc.Video = sp[1]\n\n\tfmt.Printf(\"CPU: split data with Sound %s, Video %s\\n\", c.Sound, c.Video)\n\tGetMediatorInstance().changed(c)\n}\n\ntype VideoCard struct {\n\tData string\n}\n\nfunc (v *VideoCard) Display(data string) {\n\tv.Data = data\n\tfmt.Printf(\"VideoCard: display %s\\n\", v.Data)\n\tGetMediatorInstance().changed(v)\n}\n\ntype SoundCard struct {\n\tData string\n}\n\nfunc (s *SoundCard) Play(data string) {\n\ts.Data = data\n\tfmt.Printf(\"SoundCard: play %s\\n\", s.Data)\n\tGetMediatorInstance().changed(s)\n}\n\ntype Mediator struct {\n\tCD    *CDDriver\n\tCPU   *CPU\n\tVideo *VideoCard\n\tSound *SoundCard\n}\n\nvar mediator *Mediator\n\nfunc GetMediatorInstance() *Mediator {\n\tif mediator == nil {\n\t\tmediator = &Mediator{}\n\t}\n\treturn mediator\n}\n\nfunc (m *Mediator) changed(i interface{}) {\n\tswitch inst := i.(type) {\n\tcase *CDDriver:\n\t\tm.CPU.Process(inst.Data)\n\tcase *CPU:\n\t\tm.Sound.Play(inst.Sound)\n\t\tm.Video.Display(inst.Video)\n\t}\n}\n"
  },
  {
    "path": "08_mediator/mediator_test.go",
    "content": "package mediator\n\nimport \"testing\"\n\nfunc TestMediator(t *testing.T) {\n\tmediator := GetMediatorInstance()\n\tmediator.CD = &CDDriver{}\n\tmediator.CPU = &CPU{}\n\tmediator.Video = &VideoCard{}\n\tmediator.Sound = &SoundCard{}\n\n\t// Tiggle\n\tmediator.CD.ReadData()\n\n\tif mediator.CD.Data != \"music,image\" {\n\t\tt.Fatalf(\"CD unexpect data %s\", mediator.CD.Data)\n\t}\n\n\tif mediator.CPU.Sound != \"music\" {\n\t\tt.Fatalf(\"CPU unexpect sound data %s\", mediator.CPU.Sound)\n\t}\n\n\tif mediator.CPU.Video != \"image\" {\n\t\tt.Fatalf(\"CPU unexpect video data %s\", mediator.CPU.Video)\n\t}\n\n\tif mediator.Video.Data != \"image\" {\n\t\tt.Fatalf(\"VidoeCard unexpect data %s\", mediator.Video.Data)\n\t}\n\n\tif mediator.Sound.Data != \"music\" {\n\t\tt.Fatalf(\"SoundCard unexpect data %s\", mediator.Sound.Data)\n\t}\n}\n"
  },
  {
    "path": "09_proxy/README.md",
    "content": "# 代理模式\n\n代理模式用于延迟处理操作或者在进行实际操作前后进行其它处理。\n\n## 代理模式的常见用法有\n\n* 虚代理\n* COW代理\n* 远程代理\n* 保护代理\n* Cache 代理\n* 防火墙代理\n* 同步代理\n* 智能指引\n\n等。。。\n"
  },
  {
    "path": "09_proxy/proxy.go",
    "content": "package proxy\n\ntype Subject interface {\n\tDo() string\n}\n\ntype RealSubject struct{}\n\nfunc (RealSubject) Do() string {\n\treturn \"real\"\n}\n\ntype Proxy struct {\n\treal RealSubject\n}\n\nfunc (p Proxy) Do() string {\n\tvar res string\n\n\t// 在调用真实对象之前的工作，检查缓存，判断权限，实例化真实对象等。。\n\tres += \"pre:\"\n\n\t// 调用真实对象\n\tres += p.real.Do()\n\n\t// 调用之后的操作，如缓存结果，对结果进行处理等。。\n\tres += \":after\"\n\n\treturn res\n}\n"
  },
  {
    "path": "09_proxy/proxy_test.go",
    "content": "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 res != \"pre:real:after\" {\n\t\tt.Fail()\n\t}\n}\n"
  },
  {
    "path": "10_observer/README.md",
    "content": "# 观察者模式\n\n观察者模式用于触发联动。\n\n一个对象的改变会触发其它观察者的相关动作，而此对象无需关心连动对象的具体实现。\n"
  },
  {
    "path": "10_observer/observer.go",
    "content": "package observer\n\nimport \"fmt\"\n\ntype Subject struct {\n\tobservers []Observer\n\tcontext   string\n}\n\nfunc NewSubject() *Subject {\n\treturn &Subject{\n\t\tobservers: make([]Observer, 0),\n\t}\n}\n\nfunc (s *Subject) Attach(o Observer) {\n\ts.observers = append(s.observers, o)\n}\n\nfunc (s *Subject) notify() {\n\tfor _, o := range s.observers {\n\t\to.Update(s)\n\t}\n}\n\nfunc (s *Subject) UpdateContext(context string) {\n\ts.context = context\n\ts.notify()\n}\n\ntype Observer interface {\n\tUpdate(*Subject)\n}\n\ntype Reader struct {\n\tname string\n}\n\nfunc NewReader(name string) *Reader {\n\treturn &Reader{\n\t\tname: name,\n\t}\n}\n\nfunc (r *Reader) Update(s *Subject) {\n\tfmt.Printf(\"%s receive %s\\n\", r.name, s.context)\n}\n"
  },
  {
    "path": "10_observer/observer_test.go",
    "content": "package observer\n\nfunc ExampleObserver() {\n\tsubject := NewSubject()\n\treader1 := NewReader(\"reader1\")\n\treader2 := NewReader(\"reader2\")\n\treader3 := NewReader(\"reader3\")\n\tsubject.Attach(reader1)\n\tsubject.Attach(reader2)\n\tsubject.Attach(reader3)\n\n\tsubject.UpdateContext(\"observer mode\")\n\t// Output:\n\t// reader1 receive observer mode\n\t// reader2 receive observer mode\n\t// reader3 receive observer mode\n}\n"
  },
  {
    "path": "11_command/README.md",
    "content": "# 命令模式\n\n命令模式本质是把某个对象的方法调用封装到对象中，方便传递、存储、调用。\n\n示例中把主板单中的启动(start)方法和重启(reboot)方法封装为命令对象，再传递到主机(box)对象中。于两个按钮进行绑定：\n\n* 第一个机箱(box1)设置按钮1(button1) 为开机按钮2(button2)为重启。\n* 第二个机箱(box1)设置按钮2(button2) 为开机按钮1(button1)为重启。\n\n从而得到配置灵活性。\n\n除了配置灵活外，使用命令模式还可以用作：\n\n* 批处理\n* 任务队列\n* undo, redo\n\n等把具体命令封装到对象中使用的场合\n\n"
  },
  {
    "path": "11_command/command.go",
    "content": "package command\n\nimport \"fmt\"\n\ntype Command interface {\n\tExecute()\n}\n\ntype StartCommand struct {\n\tmb *MotherBoard\n}\n\nfunc NewStartCommand(mb *MotherBoard) *StartCommand {\n\treturn &StartCommand{\n\t\tmb: mb,\n\t}\n}\n\nfunc (c *StartCommand) Execute() {\n\tc.mb.Start()\n}\n\ntype RebootCommand struct {\n\tmb *MotherBoard\n}\n\nfunc NewRebootCommand(mb *MotherBoard) *RebootCommand {\n\treturn &RebootCommand{\n\t\tmb: mb,\n\t}\n}\n\nfunc (c *RebootCommand) Execute() {\n\tc.mb.Reboot()\n}\n\ntype MotherBoard struct{}\n\nfunc (*MotherBoard) Start() {\n\tfmt.Print(\"system starting\\n\")\n}\n\nfunc (*MotherBoard) Reboot() {\n\tfmt.Print(\"system rebooting\\n\")\n}\n\ntype Box struct {\n\tbutton1 Command\n\tbutton2 Command\n}\n\nfunc NewBox(button1, button2 Command) *Box {\n\treturn &Box{\n\t\tbutton1: button1,\n\t\tbutton2: button2,\n\t}\n}\n\nfunc (b *Box) PressButton1() {\n\tb.button1.Execute()\n}\n\nfunc (b *Box) PressButton2() {\n\tb.button2.Execute()\n}\n"
  },
  {
    "path": "11_command/command_test.go",
    "content": "package command\n\nfunc ExampleCommand() {\n\tmb := &MotherBoard{}\n\tstartCommand := NewStartCommand(mb)\n\trebootCommand := NewRebootCommand(mb)\n\n\tbox1 := NewBox(startCommand, rebootCommand)\n\tbox1.PressButton1()\n\tbox1.PressButton2()\n\n\tbox2 := NewBox(rebootCommand, startCommand)\n\tbox2.PressButton1()\n\tbox2.PressButton2()\n\t// Output:\n\t// system starting\n\t// system rebooting\n\t// system rebooting\n\t// system starting\n}\n"
  },
  {
    "path": "12_iterator/README.md",
    "content": "# 迭代器模式\n\n迭代器模式用于使用相同方式送代不同类型集合或者隐藏集合类型的具体实现。\n\n可以使用迭代器模式使遍历同时应用送代策略，如请求新对象、过滤、处理对象等。\n"
  },
  {
    "path": "12_iterator/iterator.go",
    "content": "package iterator\n\nimport \"fmt\"\n\ntype Aggregate interface {\n\tIterator() Iterator\n}\n\ntype Iterator interface {\n\tFirst()\n\tIsDone() bool\n\tNext() interface{}\n}\n\ntype Numbers struct {\n\tstart, end int\n}\n\nfunc NewNumbers(start, end int) *Numbers {\n\treturn &Numbers{\n\t\tstart: start,\n\t\tend:   end,\n\t}\n}\n\nfunc (n *Numbers) Iterator() Iterator {\n\treturn &NumbersIterator{\n\t\tnumbers: n,\n\t\tnext:    n.start,\n\t}\n}\n\ntype NumbersIterator struct {\n\tnumbers *Numbers\n\tnext    int\n}\n\nfunc (i *NumbersIterator) First() {\n\ti.next = i.numbers.start\n}\n\nfunc (i *NumbersIterator) IsDone() bool {\n\treturn i.next > i.numbers.end\n}\n\nfunc (i *NumbersIterator) Next() interface{} {\n\tif !i.IsDone() {\n\t\tnext := i.next\n\t\ti.next++\n\t\treturn next\n\t}\n\treturn nil\n}\n\nfunc IteratorPrint(i Iterator) {\n\tfor i.First(); !i.IsDone(); {\n\t\tc := i.Next()\n\t\tfmt.Printf(\"%#v\\n\", c)\n\t}\n}\n"
  },
  {
    "path": "12_iterator/iterator_test.go",
    "content": "package iterator\n\nfunc ExampleIterator() {\n\tvar aggregate Aggregate\n\taggregate = NewNumbers(1, 10)\n\n\tIteratorPrint(aggregate.Iterator())\n\t// Output:\n\t// 1\n\t// 2\n\t// 3\n\t// 4\n\t// 5\n\t// 6\n\t// 7\n\t// 8\n\t// 9\n\t// 10\n}\n"
  },
  {
    "path": "13_composite/README.md",
    "content": "# 组合模式\n\n组合模式统一对象和对象集，使得使用相同接口使用对象和对象集。\n\n组合模式常用于树状结构，用于统一叶子节点和树节点的访问，并且可以用于应用某一操作到所有子节点。\n"
  },
  {
    "path": "13_composite/composite.go",
    "content": "package composite\n\nimport \"fmt\"\n\ntype Component interface {\n\tParent() Component\n\tSetParent(Component)\n\tName() string\n\tSetName(string)\n\tAddChild(Component)\n\tPrint(string)\n}\n\nconst (\n\tLeafNode = iota\n\tCompositeNode\n)\n\nfunc NewComponent(kind int, name string) Component {\n\tvar c Component\n\tswitch kind {\n\tcase LeafNode:\n\t\tc = NewLeaf()\n\tcase CompositeNode:\n\t\tc = NewComposite()\n\t}\n\n\tc.SetName(name)\n\treturn c\n}\n\ntype component struct {\n\tparent Component\n\tname   string\n}\n\nfunc (c *component) Parent() Component {\n\treturn c.parent\n}\n\nfunc (c *component) SetParent(parent Component) {\n\tc.parent = parent\n}\n\nfunc (c *component) Name() string {\n\treturn c.name\n}\n\nfunc (c *component) SetName(name string) {\n\tc.name = name\n}\n\nfunc (c *component) AddChild(Component) {}\n\nfunc (c *component) Print(string) {}\n\ntype Leaf struct {\n\tcomponent\n}\n\nfunc NewLeaf() *Leaf {\n\treturn &Leaf{}\n}\n\nfunc (c *Leaf) Print(pre string) {\n\tfmt.Printf(\"%s-%s\\n\", pre, c.Name())\n}\n\ntype Composite struct {\n\tcomponent\n\tchilds []Component\n}\n\nfunc NewComposite() *Composite {\n\treturn &Composite{\n\t\tchilds: make([]Component, 0),\n\t}\n}\n\nfunc (c *Composite) AddChild(child Component) {\n\tchild.SetParent(c)\n\tc.childs = append(c.childs, child)\n}\n\nfunc (c *Composite) Print(pre string) {\n\tfmt.Printf(\"%s+%s\\n\", pre, c.Name())\n\tpre += \" \"\n\tfor _, comp := range c.childs {\n\t\tcomp.Print(pre)\n\t}\n}\n"
  },
  {
    "path": "13_composite/composite_test.go",
    "content": "package composite\n\nfunc ExampleComposite() {\n\troot := NewComponent(CompositeNode, \"root\")\n\tc1 := NewComponent(CompositeNode, \"c1\")\n\tc2 := NewComponent(CompositeNode, \"c2\")\n\tc3 := NewComponent(CompositeNode, \"c3\")\n\n\tl1 := NewComponent(LeafNode, \"l1\")\n\tl2 := NewComponent(LeafNode, \"l2\")\n\tl3 := NewComponent(LeafNode, \"l3\")\n\n\troot.AddChild(c1)\n\troot.AddChild(c2)\n\tc1.AddChild(c3)\n\tc1.AddChild(l1)\n\tc2.AddChild(l2)\n\tc2.AddChild(l3)\n\n\troot.Print(\"\")\n\t// Output:\n\t// +root\n\t//  +c1\n\t//   +c3\n\t//   -l1\n\t//  +c2\n\t//   -l2\n\t//   -l3\n}\n"
  },
  {
    "path": "14_template_method/README.md",
    "content": "# 模版方法模式\n\n模版方法模式使用继承机制，把通用步骤和通用方法放到父类中，把具体实现延迟到子类中实现。使得实现符合开闭原则。\n\n如实例代码中通用步骤在父类中实现（`准备`、`下载`、`保存`、`收尾`）下载和保存的具体实现留到子类中，并且提供 `保存`方法的默认实现。\n\n因为Golang不提供继承机制，需要使用匿名组合模拟实现继承。\n\n此处需要注意：因为父类需要调用子类方法，所以子类需要匿名组合父类的同时，父类需要持有子类的引用。\n"
  },
  {
    "path": "14_template_method/templatemethod.go",
    "content": "package templatemethod\n\nimport \"fmt\"\n\ntype Downloader interface {\n\tDownload(uri string)\n}\n\ntype template struct {\n\timplement\n\turi string\n}\n\ntype implement interface {\n\tdownload()\n\tsave()\n}\n\nfunc newTemplate(impl implement) *template {\n\treturn &template{\n\t\timplement: impl,\n\t}\n}\n\nfunc (t *template) Download(uri string) {\n\tt.uri = uri\n\tfmt.Print(\"prepare downloading\\n\")\n\tt.implement.download()\n\tt.implement.save()\n\tfmt.Print(\"finish downloading\\n\")\n}\n\nfunc (t *template) save() {\n\tfmt.Print(\"default save\\n\")\n}\n\ntype HTTPDownloader struct {\n\t*template\n}\n\nfunc NewHTTPDownloader() Downloader {\n\tdownloader := &HTTPDownloader{}\n\ttemplate := newTemplate(downloader)\n\tdownloader.template = template\n\treturn downloader\n}\n\nfunc (d *HTTPDownloader) download() {\n\tfmt.Printf(\"download %s via http\\n\", d.uri)\n}\n\nfunc (*HTTPDownloader) save() {\n\tfmt.Printf(\"http save\\n\")\n}\n\ntype FTPDownloader struct {\n\t*template\n}\n\nfunc NewFTPDownloader() Downloader {\n\tdownloader := &FTPDownloader{}\n\ttemplate := newTemplate(downloader)\n\tdownloader.template = template\n\treturn downloader\n}\n\nfunc (d *FTPDownloader) download() {\n\tfmt.Printf(\"download %s via ftp\\n\", d.uri)\n}\n"
  },
  {
    "path": "14_template_method/templatemethod_test.go",
    "content": "package templatemethod\n\nfunc ExampleHTTPDownloader() {\n\tvar downloader Downloader = NewHTTPDownloader()\n\n\tdownloader.Download(\"http://example.com/abc.zip\")\n\t// Output:\n\t// prepare downloading\n\t// download http://example.com/abc.zip via http\n\t// http save\n\t// finish downloading\n}\n\nfunc ExampleFTPDownloader() {\n\tvar downloader Downloader = NewFTPDownloader()\n\n\tdownloader.Download(\"ftp://example.com/abc.zip\")\n\t// Output:\n\t// prepare downloading\n\t// download ftp://example.com/abc.zip via ftp\n\t// default save\n\t// finish downloading\n}\n"
  },
  {
    "path": "15_strategy/README.md",
    "content": "# 策略模式\n\n定义一系列算法，让这些算法在运行时可以互换，使得分离算法，符合开闭原则。\n\n"
  },
  {
    "path": "15_strategy/strategy.go",
    "content": "package strategy\n\nimport \"fmt\"\n\ntype Payment struct {\n\tcontext  *PaymentContext\n\tstrategy PaymentStrategy\n}\n\ntype PaymentContext struct {\n\tName, CardID string\n\tMoney        int\n}\n\nfunc NewPayment(name, cardid string, money int, strategy PaymentStrategy) *Payment {\n\treturn &Payment{\n\t\tcontext: &PaymentContext{\n\t\t\tName:   name,\n\t\t\tCardID: cardid,\n\t\t\tMoney:  money,\n\t\t},\n\t\tstrategy: strategy,\n\t}\n}\n\nfunc (p *Payment) Pay() {\n\tp.strategy.Pay(p.context)\n}\n\ntype PaymentStrategy interface {\n\tPay(*PaymentContext)\n}\n\ntype Cash struct{}\n\nfunc (*Cash) Pay(ctx *PaymentContext) {\n\tfmt.Printf(\"Pay $%d to %s by cash\", ctx.Money, ctx.Name)\n}\n\ntype Bank struct{}\n\nfunc (*Bank) Pay(ctx *PaymentContext) {\n\tfmt.Printf(\"Pay $%d to %s by bank account %s\", ctx.Money, ctx.Name, ctx.CardID)\n\n}\n"
  },
  {
    "path": "15_strategy/strategy_test.go",
    "content": "package strategy\n\nfunc ExamplePayByCash() {\n\tpayment := NewPayment(\"Ada\", \"\", 123, &Cash{})\n\tpayment.Pay()\n\t// Output:\n\t// Pay $123 to Ada by cash\n}\n\nfunc ExamplePayByBank() {\n\tpayment := NewPayment(\"Bob\", \"0002\", 888, &Bank{})\n\tpayment.Pay()\n\t// Output:\n\t// Pay $888 to Bob by bank account 0002\n}\n"
  },
  {
    "path": "16_state/README.md",
    "content": "# 状态模式\n\n状态模式用于分离状态和行为。\n"
  },
  {
    "path": "16_state/state.go",
    "content": "package state\n\nimport \"fmt\"\n\ntype Week interface {\n\tToday()\n\tNext(*DayContext)\n}\n\ntype DayContext struct {\n\ttoday Week\n}\n\nfunc NewDayContext() *DayContext {\n\treturn &DayContext{\n\t\ttoday: &Sunday{},\n\t}\n}\n\nfunc (d *DayContext) Today() {\n\td.today.Today()\n}\n\nfunc (d *DayContext) Next() {\n\td.today.Next(d)\n}\n\ntype Sunday struct{}\n\nfunc (*Sunday) Today() {\n\tfmt.Printf(\"Sunday\\n\")\n}\n\nfunc (*Sunday) Next(ctx *DayContext) {\n\tctx.today = &Monday{}\n}\n\ntype Monday struct{}\n\nfunc (*Monday) Today() {\n\tfmt.Printf(\"Monday\\n\")\n}\n\nfunc (*Monday) Next(ctx *DayContext) {\n\tctx.today = &Tuesday{}\n}\n\ntype Tuesday struct{}\n\nfunc (*Tuesday) Today() {\n\tfmt.Printf(\"Tuesday\\n\")\n}\n\nfunc (*Tuesday) Next(ctx *DayContext) {\n\tctx.today = &Wednesday{}\n}\n\ntype Wednesday struct{}\n\nfunc (*Wednesday) Today() {\n\tfmt.Printf(\"Wednesday\\n\")\n}\n\nfunc (*Wednesday) Next(ctx *DayContext) {\n\tctx.today = &Thursday{}\n}\n\ntype Thursday struct{}\n\nfunc (*Thursday) Today() {\n\tfmt.Printf(\"Thursday\\n\")\n}\n\nfunc (*Thursday) Next(ctx *DayContext) {\n\tctx.today = &Friday{}\n}\n\ntype Friday struct{}\n\nfunc (*Friday) Today() {\n\tfmt.Printf(\"Friday\\n\")\n}\n\nfunc (*Friday) Next(ctx *DayContext) {\n\tctx.today = &Saturday{}\n}\n\ntype Saturday struct{}\n\nfunc (*Saturday) Today() {\n\tfmt.Printf(\"Saturday\\n\")\n}\n\nfunc (*Saturday) Next(ctx *DayContext) {\n\tctx.today = &Sunday{}\n}\n"
  },
  {
    "path": "16_state/state_test.go",
    "content": "package state\n\nfunc ExampleWeek() {\n\tctx := NewDayContext()\n\ttodayAndNext := func() {\n\t\tctx.Today()\n\t\tctx.Next()\n\t}\n\n\tfor i := 0; i < 8; i++ {\n\t\ttodayAndNext()\n\t}\n\t// Output:\n\t// Sunday\n\t// Monday\n\t// Tuesday\n\t// Wednesday\n\t// Thursday\n\t// Friday\n\t// Saturday\n\t// Sunday\n}\n"
  },
  {
    "path": "17_memento/README.md",
    "content": "# 备忘录模式\n\n备忘录模式用于保存程序内部状态到外部，又不希望暴露内部状态的情形。\n\n程序内部状态使用窄接口传递给外部进行存储，从而不暴露程序实现细节。\n\n备忘录模式同时可以离线保存内部状态，如保存到数据库，文件等。\n"
  },
  {
    "path": "17_memento/memento.go",
    "content": "package memento\n\nimport \"fmt\"\n\ntype Memento interface{}\n\ntype Game struct {\n\thp, mp int\n}\n\ntype gameMemento struct {\n\thp, mp int\n}\n\nfunc (g *Game) Play(mpDelta, hpDelta int) {\n\tg.mp += mpDelta\n\tg.hp += hpDelta\n}\n\nfunc (g *Game) Save() Memento {\n\treturn &gameMemento{\n\t\thp: g.hp,\n\t\tmp: g.mp,\n\t}\n}\n\nfunc (g *Game) Load(m Memento) {\n\tgm := m.(*gameMemento)\n\tg.mp = gm.mp\n\tg.hp = gm.hp\n}\n\nfunc (g *Game) Status() {\n\tfmt.Printf(\"Current HP:%d, MP:%d\\n\", g.hp, g.mp)\n}\n"
  },
  {
    "path": "17_memento/memento_test.go",
    "content": "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\tgame.Play(-2, -3)\n\tgame.Status()\n\n\tgame.Load(progress)\n\tgame.Status()\n\n\t// Output:\n\t// Current HP:10, MP:10\n\t// Current HP:7, MP:8\n\t// Current HP:10, MP:10\n}\n"
  },
  {
    "path": "18_flyweight/README.md",
    "content": "# 享元模式\n\n享元模式从对象中剥离出不发生改变且多个实例需要的重复数据，独立出一个享元，使多个对象共享，从而节省内存以及减少对象数量。\n\n"
  },
  {
    "path": "18_flyweight/flyweight.go",
    "content": "package flyweight\n\nimport \"fmt\"\n\ntype ImageFlyweightFactory struct {\n\tmaps map[string]*ImageFlyweight\n}\n\nvar imageFactory *ImageFlyweightFactory\n\nfunc GetImageFlyweightFactory() *ImageFlyweightFactory {\n\tif imageFactory == nil {\n\t\timageFactory = &ImageFlyweightFactory{\n\t\t\tmaps: make(map[string]*ImageFlyweight),\n\t\t}\n\t}\n\treturn imageFactory\n}\n\nfunc (f *ImageFlyweightFactory) Get(filename string) *ImageFlyweight {\n\timage := f.maps[filename]\n\tif image == nil {\n\t\timage = NewImageFlyweight(filename)\n\t\tf.maps[filename] = image\n\t}\n\n\treturn image\n}\n\ntype ImageFlyweight struct {\n\tdata string\n}\n\nfunc NewImageFlyweight(filename string) *ImageFlyweight {\n\t// Load image file\n\tdata := fmt.Sprintf(\"image data %s\", filename)\n\treturn &ImageFlyweight{\n\t\tdata: data,\n\t}\n}\n\nfunc (i *ImageFlyweight) Data() string {\n\treturn i.data\n}\n\ntype ImageViewer struct {\n\t*ImageFlyweight\n}\n\nfunc NewImageViewer(filename string) *ImageViewer {\n\timage := GetImageFlyweightFactory().Get(filename)\n\treturn &ImageViewer{\n\t\tImageFlyweight: image,\n\t}\n}\n\nfunc (i *ImageViewer) Display() {\n\tfmt.Printf(\"Display: %s\\n\", i.Data())\n}\n"
  },
  {
    "path": "18_flyweight/flyweight_test.go",
    "content": "package flyweight\n\nimport \"testing\"\n\nfunc ExampleFlyweight() {\n\tviewer := NewImageViewer(\"image1.png\")\n\tviewer.Display()\n\t// Output:\n\t// Display: image data image1.png\n}\n\nfunc TestFlyweight(t *testing.T) {\n\tviewer1 := NewImageViewer(\"image1.png\")\n\tviewer2 := NewImageViewer(\"image1.png\")\n\n\tif viewer1.ImageFlyweight != viewer2.ImageFlyweight {\n\t\tt.Fail()\n\t}\n}\n"
  },
  {
    "path": "19_interpreter/README.md",
    "content": "# 解释器模式\n\n解释器模式定义一套语言文法，并设计该语言解释器，使用户能使用特定文法控制解释器行为。\n\n解释器模式的意义在于，它分离多种复杂功能的实现，每个功能只需关注自身的解释。\n\n对于调用者不用关心内部的解释器的工作，只需要用简单的方式组合命令就可以。\n\n"
  },
  {
    "path": "19_interpreter/interpreter.go",
    "content": "package interpreter\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n)\n\ntype Node interface {\n\tInterpret() int\n}\n\ntype ValNode struct {\n\tval int\n}\n\nfunc (n *ValNode) Interpret() int {\n\treturn n.val\n}\n\ntype AddNode struct {\n\tleft, right Node\n}\n\nfunc (n *AddNode) Interpret() int {\n\treturn n.left.Interpret() + n.right.Interpret()\n}\n\ntype MinNode struct {\n\tleft, right Node\n}\n\nfunc (n *MinNode) Interpret() int {\n\treturn n.left.Interpret() - n.right.Interpret()\n}\n\ntype Parser struct {\n\texp   []string\n\tindex int\n\tprev  Node\n}\n\nfunc (p *Parser) Parse(exp string) {\n\tp.exp = strings.Split(exp, \" \")\n\n\tfor {\n\t\tif p.index >= len(p.exp) {\n\t\t\treturn\n\t\t}\n\t\tswitch p.exp[p.index] {\n\t\tcase \"+\":\n\t\t\tp.prev = p.newAddNode()\n\t\tcase \"-\":\n\t\t\tp.prev = p.newMinNode()\n\t\tdefault:\n\t\t\tp.prev = p.newValNode()\n\t\t}\n\t}\n}\n\nfunc (p *Parser) newAddNode() Node {\n\tp.index++\n\treturn &AddNode{\n\t\tleft:  p.prev,\n\t\tright: p.newValNode(),\n\t}\n}\n\nfunc (p *Parser) newMinNode() Node {\n\tp.index++\n\treturn &MinNode{\n\t\tleft:  p.prev,\n\t\tright: p.newValNode(),\n\t}\n}\n\nfunc (p *Parser) newValNode() Node {\n\tv, _ := strconv.Atoi(p.exp[p.index])\n\tp.index++\n\treturn &ValNode{\n\t\tval: v,\n\t}\n}\n\nfunc (p *Parser) Result() Node {\n\treturn p.prev\n}\n"
  },
  {
    "path": "19_interpreter/interpreter_test.go",
    "content": "package interpreter\n\nimport \"testing\"\n\nfunc TestInterpreter(t *testing.T) {\n\tp := &Parser{}\n\tp.Parse(\"1 + 2 + 3 - 4 + 5 - 6\")\n\tres := p.Result().Interpret()\n\texpect := 1\n\tif res != expect {\n\t\tt.Fatalf(\"expect %d got %d\", expect, res)\n\t}\n}\n"
  },
  {
    "path": "20_decorator/README.md",
    "content": "# 装饰模式\n\n装饰模式使用对象组合的方式动态改变或增加对象行为。\n\nGo语言借助于匿名组合和非入侵式接口可以很方便实现装饰模式。\n\n使用匿名组合，在装饰器中不必显式定义转调原对象方法。\n"
  },
  {
    "path": "20_decorator/decorator.go",
    "content": "package decorator\n\ntype Component interface {\n\tCalc() int\n}\n\ntype ConcreteComponent struct{}\n\nfunc (*ConcreteComponent) Calc() int {\n\treturn 0\n}\n\ntype MulDecorator struct {\n\tComponent\n\tnum int\n}\n\nfunc WrapMulDecorator(c Component, num int) Component {\n\treturn &MulDecorator{\n\t\tComponent: c,\n\t\tnum:       num,\n\t}\n}\n\nfunc (d *MulDecorator) Calc() int {\n\treturn d.Component.Calc() * d.num\n}\n\ntype AddDecorator struct {\n\tComponent\n\tnum int\n}\n\nfunc WrapAddDecorator(c Component, num int) Component {\n\treturn &AddDecorator{\n\t\tComponent: c,\n\t\tnum:       num,\n\t}\n}\n\nfunc (d *AddDecorator) Calc() int {\n\treturn d.Component.Calc() + d.num\n}\n"
  },
  {
    "path": "20_decorator/decorator_test.go",
    "content": "package decorator\n\nimport \"fmt\"\n\nfunc ExampleDecorator() {\n\tvar c Component = &ConcreteComponent{}\n\tc = WrapAddDecorator(c, 10)\n\tc = WrapMulDecorator(c, 8)\n\tres := c.Calc()\n\n\tfmt.Printf(\"res %d\\n\", res)\n\t// Output:\n\t// res 80\n}\n"
  },
  {
    "path": "21_chain_of_responsibility/README.md",
    "content": "# 职责链模式\n\n职责链模式用于分离不同职责，并且动态组合相关职责。\n\nGolang实现职责链模式时候，因为没有继承的支持，使用链对象包涵职责的方式，即：\n\n* 链对象包含当前职责对象以及下一个职责链。\n* 职责对象提供接口表示是否能处理对应请求。\n* 职责对象提供处理函数处理相关职责。\n\n同时可在职责链类中实现职责接口相关函数，使职责链对象可以当做一般职责对象是用。\n"
  },
  {
    "path": "21_chain_of_responsibility/chain.go",
    "content": "package chain\n\nimport \"fmt\"\n\ntype Manager interface {\n\tHaveRight(money int) bool\n\tHandleFeeRequest(name string, money int) bool\n}\n\ntype RequestChain struct {\n\tManager\n\tsuccessor *RequestChain\n}\n\nfunc (r *RequestChain) SetSuccessor(m *RequestChain) {\n\tr.successor = m\n}\n\nfunc (r *RequestChain) HandleFeeRequest(name string, money int) bool {\n\tif r.Manager.HaveRight(money) {\n\t\treturn r.Manager.HandleFeeRequest(name, money)\n\t}\n\tif r.successor != nil {\n\t\treturn r.successor.HandleFeeRequest(name, money)\n\t}\n\treturn false\n}\n\nfunc (r *RequestChain) HaveRight(money int) bool {\n\treturn true\n}\n\ntype ProjectManager struct{}\n\nfunc NewProjectManagerChain() *RequestChain {\n\treturn &RequestChain{\n\t\tManager: &ProjectManager{},\n\t}\n}\n\nfunc (*ProjectManager) HaveRight(money int) bool {\n\treturn money < 500\n}\n\nfunc (*ProjectManager) HandleFeeRequest(name string, money int) bool {\n\tif name == \"bob\" {\n\t\tfmt.Printf(\"Project manager permit %s %d fee request\\n\", name, money)\n\t\treturn true\n\t}\n\tfmt.Printf(\"Project manager don't permit %s %d fee request\\n\", name, money)\n\treturn false\n}\n\ntype DepManager struct{}\n\nfunc NewDepManagerChain() *RequestChain {\n\treturn &RequestChain{\n\t\tManager: &DepManager{},\n\t}\n}\n\nfunc (*DepManager) HaveRight(money int) bool {\n\treturn money < 5000\n}\n\nfunc (*DepManager) HandleFeeRequest(name string, money int) bool {\n\tif name == \"tom\" {\n\t\tfmt.Printf(\"Dep manager permit %s %d fee request\\n\", name, money)\n\t\treturn true\n\t}\n\tfmt.Printf(\"Dep manager don't permit %s %d fee request\\n\", name, money)\n\treturn false\n}\n\ntype GeneralManager struct{}\n\nfunc NewGeneralManagerChain() *RequestChain {\n\treturn &RequestChain{\n\t\tManager: &GeneralManager{},\n\t}\n}\n\nfunc (*GeneralManager) HaveRight(money int) bool {\n\treturn true\n}\n\nfunc (*GeneralManager) HandleFeeRequest(name string, money int) bool {\n\tif name == \"ada\" {\n\t\tfmt.Printf(\"General manager permit %s %d fee request\\n\", name, money)\n\t\treturn true\n\t}\n\tfmt.Printf(\"General manager don't permit %s %d fee request\\n\", name, money)\n\treturn false\n}\n"
  },
  {
    "path": "21_chain_of_responsibility/chain_test.go",
    "content": "package chain\n\nfunc ExampleChain() {\n\tc1 := NewProjectManagerChain()\n\tc2 := NewDepManagerChain()\n\tc3 := NewGeneralManagerChain()\n\n\tc1.SetSuccessor(c2)\n\tc2.SetSuccessor(c3)\n\n\tvar c Manager = c1\n\n\tc.HandleFeeRequest(\"bob\", 400)\n\tc.HandleFeeRequest(\"tom\", 1400)\n\tc.HandleFeeRequest(\"ada\", 10000)\n\tc.HandleFeeRequest(\"floar\", 400)\n\t// Output:\n\t// Project manager permit bob 400 fee request\n\t// Dep manager permit tom 1400 fee request\n\t// General manager permit ada 10000 fee request\n\t// Project manager don't permit floar 400 fee request\n\n}\n"
  },
  {
    "path": "22_bridge/README.md",
    "content": "# 桥接模式\n\n桥接模式分离抽象部分和实现部分。使得两部分独立扩展。\n\n桥接模式类似于策略模式，区别在于策略模式封装一系列算法使得算法可以互相替换。\n\n策略模式使抽象部分和实现部分分离，可以独立变化。\n"
  },
  {
    "path": "22_bridge/bridge.go",
    "content": "package bridge\n\nimport \"fmt\"\n\ntype AbstractMessage interface {\n\tSendMessage(text, to string)\n}\n\ntype MessageImplementer interface {\n\tSend(text, to string)\n}\n\ntype MessageSMS struct{}\n\nfunc ViaSMS() MessageImplementer {\n\treturn &MessageSMS{}\n}\n\nfunc (*MessageSMS) Send(text, to string) {\n\tfmt.Printf(\"send %s to %s via SMS\", text, to)\n}\n\ntype MessageEmail struct{}\n\nfunc ViaEmail() MessageImplementer {\n\treturn &MessageEmail{}\n}\n\nfunc (*MessageEmail) Send(text, to string) {\n\tfmt.Printf(\"send %s to %s via Email\", text, to)\n}\n\ntype CommonMessage struct {\n\tmethod MessageImplementer\n}\n\nfunc NewCommonMessage(method MessageImplementer) *CommonMessage {\n\treturn &CommonMessage{\n\t\tmethod: method,\n\t}\n}\n\nfunc (m *CommonMessage) SendMessage(text, to string) {\n\tm.method.Send(text, to)\n}\n\ntype UrgencyMessage struct {\n\tmethod MessageImplementer\n}\n\nfunc NewUrgencyMessage(method MessageImplementer) *UrgencyMessage {\n\treturn &UrgencyMessage{\n\t\tmethod: method,\n\t}\n}\n\nfunc (m *UrgencyMessage) SendMessage(text, to string) {\n\tm.method.Send(fmt.Sprintf(\"[Urgency] %s\", text), to)\n}\n"
  },
  {
    "path": "22_bridge/bridge_test.go",
    "content": "package bridge\n\nfunc ExampleCommonSMS() {\n\tm := NewCommonMessage(ViaSMS())\n\tm.SendMessage(\"have a drink?\", \"bob\")\n\t// Output:\n\t// send have a drink? to bob via SMS\n}\n\nfunc ExampleCommonEmail() {\n\tm := NewCommonMessage(ViaEmail())\n\tm.SendMessage(\"have a drink?\", \"bob\")\n\t// Output:\n\t// send have a drink? to bob via Email\n}\n\nfunc ExampleUrgencySMS() {\n\tm := NewUrgencyMessage(ViaSMS())\n\tm.SendMessage(\"have a drink?\", \"bob\")\n\t// Output:\n\t// send [Urgency] have a drink? to bob via SMS\n}\n\nfunc ExampleUrgencyEmail() {\n\tm := NewUrgencyMessage(ViaEmail())\n\tm.SendMessage(\"have a drink?\", \"bob\")\n\t// Output:\n\t// send [Urgency] have a drink? to bob via Email\n}\n"
  },
  {
    "path": "23_visitor/README.md",
    "content": "# 访问者模式\n\n访问者模式可以给一系列对象透明的添加功能，并且把相关代码封装到一个类中。\n\n对象只要预留访问者接口`Accept`则后期为对象添加功能的时候就不需要改动对象。\n\n"
  },
  {
    "path": "23_visitor/visitor.go",
    "content": "package visitor\n\nimport \"fmt\"\n\ntype Customer interface {\n\tAccept(Visitor)\n}\n\ntype Visitor interface {\n\tVisit(Customer)\n}\n\ntype EnterpriseCustomer struct {\n\tname string\n}\n\ntype CustomerCol struct {\n\tcustomers []Customer\n}\n\nfunc (c *CustomerCol) Add(customer Customer) {\n\tc.customers = append(c.customers, customer)\n}\n\nfunc (c *CustomerCol) Accept(visitor Visitor) {\n\tfor _, customer := range c.customers {\n\t\tcustomer.Accept(visitor)\n\t}\n}\n\nfunc NewEnterpriseCustomer(name string) *EnterpriseCustomer {\n\treturn &EnterpriseCustomer{\n\t\tname: name,\n\t}\n}\n\nfunc (c *EnterpriseCustomer) Accept(visitor Visitor) {\n\tvisitor.Visit(c)\n}\n\ntype IndividualCustomer struct {\n\tname string\n}\n\nfunc NewIndividualCustomer(name string) *IndividualCustomer {\n\treturn &IndividualCustomer{\n\t\tname: name,\n\t}\n}\n\nfunc (c *IndividualCustomer) Accept(visitor Visitor) {\n\tvisitor.Visit(c)\n}\n\ntype ServiceRequestVisitor struct{}\n\nfunc (*ServiceRequestVisitor) Visit(customer Customer) {\n\tswitch c := customer.(type) {\n\tcase *EnterpriseCustomer:\n\t\tfmt.Printf(\"serving enterprise customer %s\\n\", c.name)\n\tcase *IndividualCustomer:\n\t\tfmt.Printf(\"serving individual customer %s\\n\", c.name)\n\t}\n}\n\n// AnalysisVisitor only for enterprise\ntype AnalysisVisitor struct{}\n\nfunc (*AnalysisVisitor) Visit(customer Customer) {\n\tswitch c := customer.(type) {\n\tcase *EnterpriseCustomer:\n\t\tfmt.Printf(\"analysis enterprise customer %s\\n\", c.name)\n\t}\n}\n"
  },
  {
    "path": "23_visitor/visitor_test.go",
    "content": "package visitor\n\nfunc ExampleRequestVisitor() {\n\tc := &CustomerCol{}\n\tc.Add(NewEnterpriseCustomer(\"A company\"))\n\tc.Add(NewEnterpriseCustomer(\"B company\"))\n\tc.Add(NewIndividualCustomer(\"bob\"))\n\tc.Accept(&ServiceRequestVisitor{})\n\t// Output:\n\t// serving enterprise customer A company\n\t// serving enterprise customer B company\n\t// serving individual customer bob\n}\n\nfunc ExampleAnalysis() {\n\tc := &CustomerCol{}\n\tc.Add(NewEnterpriseCustomer(\"A company\"))\n\tc.Add(NewIndividualCustomer(\"bob\"))\n\tc.Add(NewEnterpriseCustomer(\"B company\"))\n\tc.Accept(&AnalysisVisitor{})\n\t// Output:\n\t// analysis enterprise customer A company\n\t// analysis enterprise customer B company\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Senghoo Kim And Contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Go 语言设计模式\n\n[![Build Status](https://travis-ci.org/senghoo/golang-design-pattern.svg?branch=master)](https://travis-ci.org/senghoo/golang-design-pattern)\n\nGo 语言设计模式的实例代码\n\n## 创建型模式\n\n* [简单工厂模式（Simple Factory）](https://github.com/senghoo/golang-design-pattern/tree/master/00_simple_factory)\n* [工厂方法模式（Factory Method）](https://github.com/senghoo/golang-design-pattern/tree/master/04_factory_method)\n* [抽象工厂模式（Abstract Factory）](https://github.com/senghoo/golang-design-pattern/tree/master/05_abstract_factory)\n* [创建者模式（Builder）](https://github.com/senghoo/golang-design-pattern/tree/master/06_builder)\n* [原型模式（Prototype）](https://github.com/senghoo/golang-design-pattern/tree/master/07_prototype)\n* [单例模式（Singleton）](https://github.com/senghoo/golang-design-pattern/tree/master/03_singleton)\n\n## 结构型模式\n\n* [外观模式（Facade）](https://github.com/senghoo/golang-design-pattern/tree/master/01_facade)\n* [适配器模式（Adapter）](https://github.com/senghoo/golang-design-pattern/tree/master/02_adapter)\n* [代理模式（Proxy）](https://github.com/senghoo/golang-design-pattern/tree/master/09_proxy)\n* [组合模式（Composite）](https://github.com/senghoo/golang-design-pattern/tree/master/13_composite)\n* [享元模式（Flyweight）](https://github.com/senghoo/golang-design-pattern/tree/master/18_flyweight)\n* [装饰模式（Decorator）](https://github.com/senghoo/golang-design-pattern/tree/master/20_decorator)\n* [桥模式（Bridge）](https://github.com/senghoo/golang-design-pattern/tree/master/22_bridge)\n\n## 行为型模式\n\n* [中介者模式（Mediator）](https://github.com/senghoo/golang-design-pattern/tree/master/08_mediator)\n* [观察者模式（Observer）](https://github.com/senghoo/golang-design-pattern/tree/master/10_observer)\n* [命令模式（Command）](https://github.com/senghoo/golang-design-pattern/tree/master/11_command)\n* [迭代器模式（Iterator）](https://github.com/senghoo/golang-design-pattern/tree/master/12_iterator)\n* [模板方法模式（Template Method）](https://github.com/senghoo/golang-design-pattern/tree/master/14_template_method)\n* [策略模式（Strategy）](https://github.com/senghoo/golang-design-pattern/tree/master/15_strategy)\n* [状态模式（State）](https://github.com/senghoo/golang-design-pattern/tree/master/16_state)\n* [备忘录模式（Memento）](https://github.com/senghoo/golang-design-pattern/tree/master/17_memento)\n* [解释器模式（Interpreter）](https://github.com/senghoo/golang-design-pattern/tree/master/19_interpreter)\n* [职责链模式（Chain of Responsibility）](https://github.com/senghoo/golang-design-pattern/tree/master/21_chain_of_responsibility)\n* [访问者模式（Visitor）](https://github.com/senghoo/golang-design-pattern/tree/master/23_visitor)\n"
  }
]