Repository: BPing/golang_design_pattern Branch: master Commit: 765d1ed67825 Files: 31 Total size: 39.7 KB Directory structure: gitextract_bpv9jzt_/ ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── main.go └── pattern/ ├── AbstractFactory.go ├── Adapter.go ├── Bridge.go ├── Builder.go ├── ChainOfResponsibility.go ├── Command.go ├── Composite.go ├── Decorator.go ├── Facade.go ├── Factory.go ├── Flyweight.go ├── Interpreter.go ├── Iterator.go ├── Mediator.go ├── Memento.go ├── Observer.go ├── Prototype.go ├── Proxy.go ├── README.md ├── Singleton.go ├── Singleton2.go ├── State.go ├── Strategy.go ├── Template.go ├── Visitor.go └── doc.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .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 ================================================ FILE: .travis.yml ================================================ language: go go: - 1.6 install: - go get golang.org/x/tools/cmd/cover - go get github.com/mattn/goveralls script: - go build github.com/BPing/golang_design_pattern/pattern ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ # golang_design_pattern Code to achieve the design model with golang [![Stargazers over time](https://starcharts.herokuapp.com/BPing/golang_design_pattern.svg)](https://starcharts.herokuapp.com/BPing/golang_design_pattern) # 设计模式 用golang语言实现设计模式 # 设计模式的六大原则 摘自 [Java开发中的23种设计模式详解](http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html) * 1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。 所以一句话概括就是:为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类,后 面的具体设计中我们会提到这点。 * 2、里氏代换原则(Liskov Substitution Principle) 里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何 基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受 到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。 实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽 象化的具体步骤的规范。—— From Baidu 百科 * 3、依赖倒转原则(Dependence Inversion Principle) 这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。 * 4、接口隔离原则(Interface Segregation Principle) 这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度的意思,从这儿我们看出, 其实设计模式就是一个软件的设计思想,从大型软件架构出发,为了升级和维护方便。所以上文中多次出现:降低依赖,降低耦合。 * 5、迪米特法则(最少知道原则)(Demeter Principle) 为什么叫最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。 * 6、合成复用原则(Composite Reuse Principle) 原则是尽量使用合成/聚合的方式,而不是使用继承。 # 文档 https://godoc.org/github.com/BPing/golang_design_pattern/pattern [![GoDoc](https://godoc.org/github.com/BPing/golang_design_pattern/pattern?status.svg)](https://godoc.org/github.com/BPing/golang_design_pattern/pattern) # 同类项目(golang) [go-pattern](https://github.com/tmrts/go-patterns) ================================================ FILE: main.go ================================================ package main import ( "github.com/BPing/golang_design_pattern/pattern" ) func main() { var battery pattern.RechargeableBattery battery = pattern.AdapterNonToYes{pattern.NonRechargeableA{}} battery.Use() battery.Charge() battery = pattern.NonRechargeableB{} battery.Use() battery.Charge() } ================================================ FILE: pattern/AbstractFactory.go ================================================ package pattern //抽象工厂 type AbstractFactory interface { Produce() pen //生产笔 } type PencilFactory struct { } func (PencilFactory) Produce() pen { return new(pencil) } type BrushPen struct { } func (BrushPen) Produce() pen { return new(brushPen) } ================================================ FILE: pattern/Adapter.go ================================================ package pattern import "fmt" // // 适配器模式 // 是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。 // 或者 // 将一个类的接口转换成客户希望的另外一个接口。 // Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 // // 主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式 // //不可充电电池使用接口 type NonRechargeableBattery interface { Use() } //可充电电池使用接口 type RechargeableBattery interface { Use() Charge() } //不可充电电池A type NonRechargeableA struct { } func (NonRechargeableA) Use() { fmt.Println("NonRechargeableA using ") } //类的适配器模式 // 似乎golang语言层面已经支持了,暂且搁置 // // //对象的适配器模式 //适配可充电电池使用接口 type AdapterNonToYes struct { NonRechargeableBattery } func (AdapterNonToYes) Charge() { fmt.Println("AdapterNonToYes Charging") //nothing to do ,just adapt for RechargeableBattery's interface } //接口的适配器模式 type RechargeableBatteryAbstract struct { } func (RechargeableBatteryAbstract) Use() { fmt.Println("RechargeableBatteryAbstract using") } func (RechargeableBatteryAbstract) Charge() { fmt.Println("RechargeableBatteryAbstract Charging") } type NonRechargeableB struct { RechargeableBatteryAbstract } func (NonRechargeableB) Use() { fmt.Println("NonRechargeableB using ") } //test func AdapterTest() { var battery RechargeableBattery battery = AdapterNonToYes{NonRechargeableA{}} battery.Use() battery.Charge() battery = NonRechargeableB{} battery.Use() battery.Charge() } ================================================ FILE: pattern/Bridge.go ================================================ package pattern import ( "fmt" "net/http" ) // // 桥接模式 // 是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式, // 它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。 // //请求接口 type Request interface { HttpRequest() (*http.Request, error) } //客户端 type Client struct { Client *http.Client } func (c *Client) Query(req Request) (resp *http.Response, err error) { httpreq,_:=req.HttpRequest() resp, err = c.Client.Do(httpreq) return } type CdnRequest struct { } func (cdn *CdnRequest) HttpRequest() (*http.Request, error) { return http.NewRequest("GET", "/cdn", nil) } type LiveRequest struct { } func (cdn *LiveRequest) HttpRequest() (*http.Request, error) { return http.NewRequest("GET", "/live", nil) } func TestBridge() { client := &Client{http.DefaultClient} cdnReq := &CdnRequest{} fmt.Println(client.Query(cdnReq)) liveReq := &LiveRequest{} fmt.Println(client.Query(liveReq)) } ================================================ FILE: pattern/Builder.go ================================================ package pattern const ( FOOD = "food" DRINK = "drink" ) type Item interface { Price() float32 //价钱 Name() string //名称 Category() string //类别 } //食物 type Food struct { } func (Food) Price() float32 { return 0.0 } func (Food) Name() string { return "" } func (Food) Category() string { return FOOD } //饮料 type Drink struct { } func (Drink) Price() float32 { return 0.0 } func (Drink) Name() string { return "" } func (Drink) Category() string { return DRINK } //汉堡 type Hamburger struct { Food } func (Hamburger) Price() float32 { return 12.00 } func (Hamburger) Name() string { return "Hamburger" } //炸鸡 type FriedChicken struct { Food } func (FriedChicken) Price() float32 { return 18.00 } func (FriedChicken) Name() string { return "FriedChicken" } //可乐 type Cola struct { Drink } func (Cola) Price() float32 { return 3.00 } func (Cola) Name() string { return "Cola" } //啤酒 type Beer struct { Drink } func (Beer) Price() float32 { return 5.00 } func (Beer) Name() string { return "Beer" } type Meal []Item func (this *Meal) AddItem(item ...Item) { *this = append(*this, item...) } func (this Meal) GetCost() (cost float32) { for _, val := range this { cost += val.Price() } return } func (this Meal) ShowItems() (msg string) { for _, val := range this { msg += "Category:" + val.Category() + " Name:" + val.Name() + "\n" } return } //建造者 type MealBuilder struct { } func (MealBuilder) MealOne() (meal *Meal) { meal = new(Meal) meal.AddItem(new(FriedChicken), new(Beer)) return } ================================================ FILE: pattern/ChainOfResponsibility.go ================================================ package pattern import "fmt" // 责任链模式 // 使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。 // 将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。 // // github.com/BPing/Golib/middleware 包就是基于此模式实现的 type ScreenEvent struct { Type string Comment string } type IScreenEventHandler interface{ Handle(*ScreenEvent)bool SetNextHandler(IScreenEventHandler) } type AbsScreenEventHandler struct { NextHandler IScreenEventHandler } func(ase *AbsScreenEventHandler)Handle(se *ScreenEvent)bool{ if ase.NextHandler!=nil { return ase.NextHandler.Handle(se) } return false } func(ase *AbsScreenEventHandler)SetNextHandler(ise IScreenEventHandler){ ase.NextHandler=ise } type HomeScreenEventHandler struct { AbsScreenEventHandler } func(hse *HomeScreenEventHandler)Handle(se *ScreenEvent)bool{ fmt.Println("HomeScreenEventHandler.....") if se.Type=="HomeClick" { fmt.Println("HomeClick") return true } return hse.AbsScreenEventHandler.Handle(se) } type UserScreenEventHandler struct { AbsScreenEventHandler } func(use *UserScreenEventHandler)Handle(se *ScreenEvent)bool{ fmt.Println("UserScreenEventHandler.....") if se.Type=="UserModelClick" { fmt.Println("UserModelClick") return true } return use.AbsScreenEventHandler.Handle(se) } func ChainOfResponsibilityTest(){ var osd IScreenEventHandler osd=&AbsScreenEventHandler{} home:=&HomeScreenEventHandler{} user:=&UserScreenEventHandler{} home.SetNextHandler(user) osd.SetNextHandler(home) screenEvent:=&ScreenEvent{Type:"HomeClick"} osd.Handle(screenEvent) fmt.Println("-----------------------------------------------\n") screenEvent=&ScreenEvent{Type:"UserModelClick"} osd.Handle(screenEvent) fmt.Println("-----------------------------------------------\n") screenEvent=&ScreenEvent{Type:"Null"} osd.Handle(screenEvent) } ================================================ FILE: pattern/Command.go ================================================ package pattern import ( "errors" "fmt" ) // Command(命令) // 命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式。 // 请求以命令的形式包裹在对象中,并传给调用对象。 调用对象寻找可以处理该命令 // 的合适的对象,并把该命令传给相应的对象,该对象执行命令。 // // 命令接口 type Command interface { Do(args interface{}) (interface{}, error) } // Get 命令 type GetCommand struct { } func (gc *GetCommand) Do(args interface{}) (interface{}, error) { fmt.Println("GetCommand") return args, nil } // post 命令 type PostCommand struct { } func (pc *PostCommand) Do(args interface{}) (interface{}, error) { fmt.Println("PostCommand") return args, nil } // 上下文 type CmdContext struct { CmdType string Args interface{} } // 命令管理者 type CommandHandler struct { CmdMap map[string]Command } // 处理命令 func (ch *CommandHandler) Handle(ctx *CmdContext) (interface{}, error) { if ctx == nil { return nil, errors.New("") } cmd, ok := ch.CmdMap[ctx.CmdType] if ok { return cmd.Do(ctx.Args) } return nil, errors.New("invalid Command ") } // 注册命令 func (ch *CommandHandler) Register(cmdType string, cmd Command) { ch.CmdMap[cmdType] = cmd } // func CommandTest() { cmdHandler := &CommandHandler{CmdMap: make(map[string]Command)} postCtx := &CmdContext{CmdType: "post", Args: " Post"} getCtx := &CmdContext{CmdType: "get", Args: " Get"} nullCtx := &CmdContext{CmdType: "null", Args: " Get"} cmdHandler.Register("post", &PostCommand{}) cmdHandler.Register("get", &GetCommand{}) fmt.Println(cmdHandler.Handle(postCtx)) fmt.Println(cmdHandler.Handle(getCtx)) fmt.Println(cmdHandler.Handle(nullCtx)) } ================================================ FILE: pattern/Composite.go ================================================ package pattern import "fmt" // // 组合模式 将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 // type Department struct { List map[string]*Department Parent *Department Name string Id string } // 批量添加子节点 func (this *Department) Add(departments ...*Department) { for _, department := range departments { department.AddTo(this) } } // 添加到对应的父节点 func (this *Department) AddTo(parent *Department) { this.Parent = parent parent.add(this) } // 添加子节点 func (this *Department) add(department *Department) { this.List[department.Id] = department } // 查找子节点 func (this *Department) Find(id string) (department *Department) { department, ok := this.List[id] if !ok { for _, de := range this.List { department = de.Find(id) if nil != department { return } } return } return } // 移除子节点 func (this *Department) Remove(id string) (department *Department) { department, ok := this.List[id] if !ok { for _, de := range this.List { department = de.Remove(id) if nil != department { return } } return } delete(this.List, id) return } // 遍历 func (this *Department) ReadList() { fmt.Printf("Node :%s(%s) \n the children: \n", this.Id, this.Name) for _, de := range this.List { de.ReadList() } } // example func CompositeTest() { root := &Department{Name: "root", Id: "0010"} children1 := &Department{Name: "network", Id: "00010"} children2 := &Department{Name: "forward", Id: "00011"} root.Add(children1, children2) children1.Add(&Department{Name: "network1", Id: "0001010"}) root.Find("0001010").ReadList() root.ReadList() root.Remove("00010").ReadList() root.ReadList() } ================================================ FILE: pattern/Decorator.go ================================================ package pattern import ( "strings" "fmt" "log" ) // // 装饰模式 // 动态地给一个对象添加一些额外的职责,同时又不改变其结构 // // 接口 type MessageBuilder interface{ Build(messages ... string) string } // 基本信息构造器 type BaseMessageBuilder struct { } func(b *BaseMessageBuilder)Build(messages ... string) string{ return strings.Join(messages,",") } // 引号装饰器 type QuoteMessageBuilderDecorator struct { Builder MessageBuilder } func(q *QuoteMessageBuilderDecorator)Build(messages ... string) string{ return "\""+q.Builder.Build(messages...)+"\"" } // 大括号装饰器 type BraceMessageBuilderDecorator struct { Builder MessageBuilder } func(b *BraceMessageBuilderDecorator)Build(messages ... string) string{ return "{"+b.Builder.Build(messages...)+"}" } // 或者 type Object func(int) int func LogDecorate(fn Object) Object { return func(n int) int { log.Println("Starting the execution with the integer", n) result := fn(n) log.Println("Execution is completed with the result", result) return result } } func Double(n int) int { return n * 2 } // 调试 func DecoratorTest(){ var MB MessageBuilder MB=&BaseMessageBuilder{} fmt.Println(MB.Build("hello world")) MB=&QuoteMessageBuilderDecorator{MB} fmt.Println(MB.Build("hello world")) MB=&BraceMessageBuilderDecorator{MB} fmt.Println(MB.Build("hello world")) // f := LogDecorate(Double) f(5) } ================================================ FILE: pattern/Facade.go ================================================ package pattern import "fmt" // // 外观模式 // 隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口 // type Coder struct { } func (c *Coder) Coding() { fmt.Println("Coding ....") } type Tester struct { } func (t *Tester) Testing() { fmt.Println("Testing ....") } type ProductPlanner struct { } func (p *ProductPlanner) Planing() { fmt.Println("Planing ....") } type MaintenancePeople struct { } func (m *MaintenancePeople) Releasing() { fmt.Println("Releasing ....") } // 公司 // 拥有产品策划、程序员、测试人员,运维人员 // 通过公司这个外观对外提供服务, // 而不是直接通过某个类型人员对外服务(虽然最终提供服务的也是某个类型的人员) type Company struct { ProductPlanner Coder Tester MaintenancePeople } // 对外提供生产产品服务 // 需要各个类型人员合作,但细节不对外公开的 func (com *Company) Producing() { // 策划产品 com.ProductPlanner.Planing() // 编码实现 com.Coder.Coding() // 测试产品 com.Tester.Testing() // 发布产品 com.MaintenancePeople.Releasing() // 或者 //com.Planing() //com.Coding() //com.Testing() //com.Releasing() } func FacadeTest() { com := &Company{} com.Producing() // 单独调用某个功能, // 通过公司外观提供的服务 com.Testing() } ================================================ FILE: pattern/Factory.go ================================================ package pattern //工厂模式适合:凡是出现了大量的产品需要创建, //并且具有共同的接口时,可以通过工厂方法模式进行创建 import "fmt" //笔 type pen interface { //写字 Write() } type pencil struct { } func (p *pencil) Write() { fmt.Println("铅笔") } type brushPen struct { } func (p *brushPen) Write() { fmt.Println("毛笔") } //工厂 type PenFactory struct { } func (this PenFactory) Produce(typ string) pen { switch typ { case "pencil": return this.ProducePencil() case "brush": return this.ProduceBrushPen() default: return nil } } func (PenFactory) ProducePencil() pen { return new(pencil) } func (PenFactory) ProduceBrushPen() pen { return new(brushPen) } ================================================ FILE: pattern/Flyweight.go ================================================ package pattern import ( "fmt" ) // // 享元模式 // 实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用。 // sync.pool 就属于此模式 // // 数据库连接池 type DbConnectPool struct { ConnChan chan *DbConnect } func NewDbConnectPool(chanLen int)*DbConnectPool{ return &DbConnectPool{ConnChan:make(chan *DbConnect,chanLen)} } func(dc *DbConnectPool) Get()*DbConnect{ select { case conn := <-dc.ConnChan: return conn default: // 无则新建 return new(DbConnect) } } func(dc *DbConnectPool) Put(conn *DbConnect){ select { case dc.ConnChan <- conn: return default: // 满则丢弃 return } } // 数据库连接 type DbConnect struct { } func (*DbConnect) Do(){ fmt.Println("connect......doing....") } func FlyweightTest(){ pool:=NewDbConnectPool(2) conn:=pool.Get() conn.Do() pool.Put(conn) } ================================================ FILE: pattern/Interpreter.go ================================================ package pattern import ( "strings" "fmt" ) //解释器模式(Interpreter Pattern) // 提供了评估语言的语法或表达式的方式,文法解释,它属于行为型模式。 // 这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。 // // 一般递归处理 type Expression interface { Interpret(context string) bool } type TerminalExpression struct { Word string } // 终结符 func(te *TerminalExpression)Interpret(context string) bool{ if strings.Contains(context,te.Word) { return true } return false } // 或 type OrExpression struct { A Expression B Expression } func(oe *OrExpression)Interpret(context string) bool{ return oe.A.Interpret(context)||oe.B.Interpret(context) } // 与 type AndExpression struct { A Expression B Expression } func(ae *AndExpression )Interpret(context string) bool{ return ae.A.Interpret(context)&&ae.B.Interpret(context) } func InterpreterTest(){ isMale :=&OrExpression{&TerminalExpression{"Robert"},&TerminalExpression{"John"}} isMarriedWoman :=&AndExpression{&TerminalExpression{"Julie"},&TerminalExpression{"Married"}} fmt.Println("John is male?",isMale.Interpret("John")) fmt.Println("Julie is a married women?",isMarriedWoman.Interpret("Married Julie")) } ================================================ FILE: pattern/Iterator.go ================================================ package pattern import "fmt" // // 迭代器模式(Iterator Pattern) // 这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。 // 迭代器接口 type Iterator interface { HasNext() bool Next() interface{} } // 集合接口 type Container interface { GetIterator() Iterator } // 数组迭代器 type ArrayIterator struct { currentIndex int ac *ArrayContainer } func (ai *ArrayIterator) HasNext() bool { if ai.ac.arrayData!=nil&&ai.currentIndex < len(ai.ac.arrayData) { return true } return false } func (ai *ArrayIterator) Next() interface{} { if ai.HasNext() { defer func() { ai.currentIndex++ }() return ai.ac.arrayData[ai.currentIndex] } return nil } // 数组集合 type ArrayContainer struct { arrayData []interface{} } func (ac *ArrayContainer) GetIterator() Iterator { return &ArrayIterator{currentIndex: 0, ac: ac} } func IteratorTest(){ arr:=[]interface{}{"a","b","c","d"} arrayContainer:=&ArrayContainer{arrayData:arr} iterator:=arrayContainer.GetIterator() for iterator.HasNext(){ fmt.Println(iterator.Next().(string)) } } ================================================ FILE: pattern/Mediator.go ================================================ package pattern import "fmt" // 中介者模式(Mediator Pattern) // 是用来降低多个对象和类之间的通信复杂性。 // 这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护 type ChatRoom struct { name string } func (cr *ChatRoom)SendMsg(msg string){ fmt.Println(cr.name+" : "+msg) } func (cr *ChatRoom)RegisterUser(u *User){ u.cr=cr } type User struct { name string cr *ChatRoom } func (u *User)SendMsg(msg string){ if u.cr!=nil { u.cr.SendMsg(u.name+" : "+msg) } } func MediatorTest(){ AUser:=&User{name:"AUser"} BUser:=&User{name:"BUser"} chatRoom:=&ChatRoom{name:"chatRoom123456"} chatRoom.RegisterUser(AUser) chatRoom.RegisterUser(BUser) AUser.SendMsg("hello AUser") BUser.SendMsg("hello BUser") } ================================================ FILE: pattern/Memento.go ================================================ package pattern import ( "container/list" "fmt" ) // 备忘录模式(Memento pattern) // 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。 // 这样以后就可将该对象恢复到原先保存的状态。 // 相关模式:原型模式 // 文本编辑 type Text struct { Value string } // 写 func (t *Text) Write(value string) { t.Value = value } // 读取 func (t *Text) Read() string { return t.Value } // 备忘 func (t *Text) SaveToMemento() *Memento { return &Memento{Value: t.Value} } // 从备忘恢复 func (t *Text) RestoreFromMemento(m *Memento) { if m!=nil { t.Value = m.Value } return } // 备忘结构 type Memento struct { Value string } // 管理备忘记录 type Storage struct { *list.List } // Back returns the last element of list l or nil. // and remove form list func (s *Storage)RPop()*list.Element{ ele:=s.Back() if ele!=nil{ s.Remove(ele) } return ele } func MementoTest(){ storage:=&Storage{list.New()} text:=&Text{"hello world"} fmt.Println(text.Read()) storage.PushBack(text.SaveToMemento()) text.Write("nihao") fmt.Println(text.Read()) storage.PushBack(text.SaveToMemento()) text.Write("i know") fmt.Println(text.Read()) //后退回滚 mediator:=storage.RPop() if mediator!=nil { text.RestoreFromMemento(mediator.Value.(*Memento)) } fmt.Println(text.Read()) //后退回滚 mediator=storage.RPop() if mediator!=nil { text.RestoreFromMemento(mediator.Value.(*Memento)) } fmt.Println(text.Read()) //后退 已没有 mediator=storage.RPop() if mediator!=nil { text.RestoreFromMemento(mediator.Value.(*Memento)) } fmt.Println(text.Read()) } ================================================ FILE: pattern/Observer.go ================================================ package pattern import "fmt" // // 观察者模式(Observer Pattern) // 定义对象间的一种一对多的依赖关系, // 当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。 // type Observer interface { Notify(interface{}) } type Subject struct { observers []Observer state string } func (s *Subject)SetState(state string) { s.state = state s.NotifyAllObservers() } func (s *Subject)Attach(observer ... Observer) { s.observers = append(s.observers, observer ...) } func (s *Subject)NotifyAllObservers() { for _, obs := range s.observers { obs.Notify(s) } } type AObserver struct { Id string } func (ao *AObserver)Notify(sub interface{}) { fmt.Println(ao.Id , " receive ", sub.(*Subject).state) } func ObserverTest() { sub := &Subject{} a := &AObserver{Id:"A"} b := &AObserver{Id:"b"} sub.Attach(a,b) sub.SetState("hello world") sub.SetState("i know") } ================================================ FILE: pattern/Prototype.go ================================================ package pattern import ( "fmt" "reflect" ) // // 原型模式 // 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 // // ps:或者可以使用sync.Pool来替代原型模式方式 // type Cloneable interface { Clone() interface{} } type Context struct { } func (this *Context) Clone() interface{} { new_obj := (*this) return &new_obj } //结构体基本信息 func (this *Context) string(typ interface{}) (str string) { v := reflect.ValueOf(typ).Elem() str += "Type:" + v.Type().Name() + "\n" for i := 0; i < v.NumField(); i++ { f := v.Field(i) str += fmt.Sprintf("index %d: %s %s = %v\n", i, v.Type().Field(i).Name, f.Type(), f.Interface()) } return } type Context1 struct { Uri string Context } func (this *Context1) SetUri(uri string) { this.Uri = uri } func (this *Context1) String() (str string) { return this.string(this) } type Context2 struct { Context Echo string } func (this *Context2) SetEcho(echo string) { this.Echo = echo } func (this *Context2) String() (str string) { return this.string(this) } //原型池 type ContextPool map[string]*Context func (this *ContextPool) AddContext(key string, val *Context) { (*this)[key] = val } func (this *ContextPool) GetContext(key string) *Context { val, ok := (*this)[key] if ok { return val.Clone().(*Context) } return nil } ================================================ FILE: pattern/Proxy.go ================================================ package pattern import ( "errors" "fmt" ) // 代理模式 // 为其他对象提供一种代理以控制对这个对象的访问 // 优点: 1、职责清晰。 2、高扩展性。 3、智能化。 // 注意事项: // 1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口, // 而代理模式不能改变所代理类的接口。 // 2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式 // 是为了加以控制。 // 似乎有点像装饰模式 type Device interface { Read()([]byte,error) Write(word []byte)error } type HardDisk struct { storage []byte } func(h *HardDisk)Read()([]byte,error){ return h.storage,nil } func(h *HardDisk)Write(word []byte)error{ h.storage=word return nil } type HardDiskProxy struct { OpId string hd *HardDisk } func(h *HardDiskProxy)Read()([]byte,error){ if !h.permission("read") { return nil ,errors.New("You don't have permission to read") } return h.hd.Read() } func(h *HardDiskProxy)Write(word []byte)error{ if !h.permission("wrire") { return errors.New("You don't have permission to write") } return h.hd.Write(word) } // 权限判断 func(h *HardDiskProxy)permission(tag string)bool{ if h.OpId=="admin"{ return true } if h.OpId=="reader"&&tag=="read"{ return true } if h.OpId=="writer"&&tag=="wrire"{ return true } return false } func ProxyTest(){ var devI Device devI=&HardDiskProxy{OpId:"admin",hd:&HardDisk{}} devI.Write([]byte("Hello world!")) data,_:=devI.Read() fmt.Println(string(data)) devI=&HardDiskProxy{OpId:"reader",hd:&HardDisk{storage:[]byte("only read")}} err:=devI.Write([]byte("Hello world!")) fmt.Println(err.Error()) data,_=devI.Read() fmt.Println(string(data)) devI=&HardDiskProxy{OpId:"writer",hd:&HardDisk{}} err=devI.Write([]byte("only writer")) fmt.Println(err) data,err=devI.Read() fmt.Println(string(data),err.Error()) } ================================================ FILE: pattern/README.md ================================================ # 设计模式 * 创建型 C * 结构型 J * 行为型 X ``` -AbstractFactory.go : 抽象工厂模式(C) -Adapter.go : 适配器模式(J) -Bridge.go : 桥接模式(J) -Builder.go : 建造者模式(C) -ChainOfResponsibility.go : 责任链模式(X) -Command.go : 命令模式(X) -Composite.go : 组合模式(J) -Decorator.go : 装饰器模式(J) -Facade.go : 外观模式(J) -Factory.go : 工厂模式(C) -Flyweight.go : 享元模式(J) -Interpreter.go : 解释器模式(X) -Iterator.go : 迭代器模式(X) -Mediator.go : 中介者模式(X) -Memento.go : 备忘录模式(X) -Observer.go : 观察者模式(X) -Prototype.go : 原型模式(C) -Proxy.go : 代理模式(J) -Singleton.go : 单例模式(C) -Singleton2.go : 单例模式(C) -State.go : 状态模式(X) -Strategy.go : 策略模式(X) -Template.go : 模板模式(X) -Visitor.go : 访问者模式(X) ``` # 参考资料 * http://www.runoob.com/design-pattern/design-pattern-tutorial.html * http://www.cnblogs.com/beijiguangyong/archive/2010/11/15/2302807.html#_Toc281750448 * http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html ================================================ FILE: pattern/Singleton.go ================================================ package pattern import "fmt" type Singleton interface { SaySomething() } type singleton struct { } func (singleton) SaySomething() { fmt.Println("Singleton") } var singletonInstance Singleton func NewSingletonInstance() Singleton { if nil == singletonInstance { singletonInstance = &singleton{} } return singletonInstance } ================================================ FILE: pattern/Singleton2.go ================================================ package pattern // //另一种单例模式的实现方式,也是golang语言常用的模式 //采用init()方法全局之实例化一次 // import "fmt" type Singleton2 interface { SaySomething() } type singleton2 struct { } func (singleton2) SaySomething() { fmt.Println("Singleton") } var singletonInstance2 Singleton2 func init() { singletonInstance2 = new(singleton2) } func Singleton2SaySomething() { singletonInstance2.SaySomething() } ================================================ FILE: pattern/State.go ================================================ package pattern import "fmt" // 状态模式(State Pattern) // 核心思想就是:当对象的状态改变时,同时改变其行为,很好理解! // 就拿QQ来说,有几种状态,在线、隐身、忙碌等,每个状态对应不同的操作, // 而且你的好友也能看到你的状态, 所以,状态模式就两点: // 1、可以通过改变状态来获得不同的行为。 // 2、你的好友能同时看到你的变化 // 相关模式:命令模式 // 灯 type Light struct { State LightState } func(l *Light)PressSwitch(){ if l.State!=nil { l.State.PressSwitch(l) } } // 灯状态 type LightState interface { PressSwitch(light *Light) } type OnLightState struct { } // 开灯 func(ols *OnLightState)PressSwitch(light *Light){ fmt.Println("turn on light") // 下一个状态动作为关灯 light.State=&OffLightState{} } type OffLightState struct { } // 关灯 func(ols *OffLightState)PressSwitch(light *Light){ fmt.Println("turn off light") // 下一个状态动作为开灯 light.State=&OnLightState{} } func StateTest(){ light:=&Light{State:&OnLightState{}} light.PressSwitch() light.PressSwitch() light.PressSwitch() light.PressSwitch() } ================================================ FILE: pattern/Strategy.go ================================================ package pattern import ( "fmt" ) // 策略模式(Strategy Pattern) // 定义一系列的算法,把它们一个个封装起来, // 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。 // 相关模式:工厂模式 type Strategy interface { Do(interface{}) } // 从A到B type AToB struct { // 距离 ABDistance float64 // 到达方式策略 Strategy Strategy } func(ab *AToB) Do(){ if ab.Strategy!=nil { ab.Strategy.Do(ab) } } type BikeStrategy struct { Speed float64 } func(bs *BikeStrategy) Do(ab interface{}){ aTob,ok:=ab.(*AToB) if ok &&bs.Speed<=0.0000001{ return } fmt.Println("方式:自行车 用时:",aTob.ABDistance/bs.Speed) } type BusStrategy struct { Speed float64 } func(bs *BusStrategy) Do(ab interface{}){ aTob,ok:=ab.(*AToB) if ok &&bs.Speed<=0.0000001{ return } fmt.Println("方式:巴士 用时:",aTob.ABDistance/bs.Speed) } type AirStrategy struct { Speed float64 } func(as *AirStrategy) Do(ab interface{}){ aTob,ok:=ab.(*AToB) if ok &&as.Speed<=0.0000001{ return } fmt.Println("方式:飞机 用时:",aTob.ABDistance/as.Speed) } func StrategyTest(){ aTob:=&AToB{ABDistance:600} aTob.Strategy=&BikeStrategy{Speed:15} aTob.Do() aTob.Strategy=&BusStrategy{Speed:90} aTob.Do() aTob.Strategy=&AirStrategy{Speed:500} aTob.Do() } ================================================ FILE: pattern/Template.go ================================================ package pattern import "fmt" // 模板模式(Template Pattern) // 定义一个操作中算法的框架,而将一些步骤延迟到子类中。 // 模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 type Game interface { Start() Playing() End() } type AbsGame struct { } func(ag *AbsGame)Start(){ fmt.Println("start game") } func(ag *AbsGame)Playing(){ fmt.Println("game playing") } func(ag *AbsGame)End(){ fmt.Println("the end") } type FootBall struct { *AbsGame } func(fb *FootBall)Playing(){ fmt.Println("playing FootBall") } type Cricket struct { *AbsGame } func(fb *Cricket )Playing(){ fmt.Println("playing Cricket ") } func RunGame(g Game){ g.Start() g.Playing() g.End() } func TemplateTest(){ RunGame(&FootBall{}) RunGame(&Cricket{}) } ================================================ FILE: pattern/Visitor.go ================================================ package pattern import ( "fmt" "math" ) // 访问者模式(Visitor Pattern) 主要将数据结构与数据操作分离 // // 1、对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。 // 2、需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。 type Visitor interface { Visit(DataStruct) } type DataStruct interface { Accept(Visitor) } type ABData struct { A int B int } func (as *ABData)Accept(vi Visitor){ vi.Visit(as) } type AddVisitor struct { } func (av *AddVisitor)Visit(dataS DataStruct){ data:=dataS.(*ABData) sum:=data.A+data.B fmt.Println("A+B=",sum) } type SubVisitor struct { } func (sv *SubVisitor)Visit(dataS DataStruct){ data:=dataS.(*ABData) sum:=data.A-data.B fmt.Println("abs(A-B)=",math.Abs(float64(sum))) } func VisitorTest(){ Data:=&ABData{A:8,B:10} add:=&AddVisitor{} sub:=&SubVisitor{} Data.Accept(add) Data.Accept(sub) } ================================================ FILE: pattern/doc.go ================================================ // // 开发模式代码实现包 // # 设计模式 // * 创建型 C // * 结构型 J // * 行为型 X // // -AbstractFactory.go : 抽象工厂模式(C) // -Adapter.go : 适配器模式(J) // -Bridge.go : 桥接模式(J) // -Builder.go : 建造者模式(C) // -ChainOfResponsibility.go : 责任链模式(X) // -Command.go : 命令模式(X) // -Composite.go : 组合模式(J) // -Decorator.go : 装饰器模式(J) // -Facade.go : 外观模式(J) // -Factory.go : 工厂模式(C) // -Flyweight.go : 享元模式(J) // -Interpreter.go : 解释器模式(X) // -Iterator.go : 迭代器模式(X) // -Mediator.go : 中介者模式(X) // -Memento.go : 备忘录模式(X) // -Observer.go : 观察者模式(X) // -Prototype.go : 原型模式(C) // -Proxy.go : 代理模式(J) // -Singleton.go : 单例模式(C) // -Singleton2.go : 单例模式(C) // -State.go : 状态模式(X) // -Strategy.go : 策略模式(X) // -Template.go : 模板模式(X) // -Visitor.go : 访问者模式(X) // // package pattern