├── README.md ├── behavior ├── chain_of_responsibility.go ├── command.go ├── interpreter.go ├── iterator.go ├── mediator.go ├── memento.go ├── observer.go ├── state.go ├── strategy.go ├── template_method.go └── visitor.go ├── concurrency ├── balking.go ├── future.go └── thread_pool.go ├── creation ├── abstract_factory.go ├── builder.go ├── factory_method.go ├── object_pool.go ├── prototype.go └── singleton.go └── structure ├── adapter.go ├── bridge.go ├── composite.go ├── decorator.go ├── facade.go ├── flyweight.go └── proxy.go /README.md: -------------------------------------------------------------------------------- 1 | Go Design Patterns 2 | ================== 3 | 4 | Creational patterns 5 | ------------------- 6 | * Abstract factory 7 | * Builder 8 | * Factory method 9 | * Object pool 10 | * Prototype 11 | * Singleton 12 | 13 | Structural patterns 14 | ------------------- 15 | * Adapter 16 | * Bridge 17 | * Composite 18 | * Decorator 19 | * Facade 20 | * Flyweight 21 | * Proxy 22 | 23 | Behavioral patterns 24 | ------------------- 25 | * Chain of responsibility 26 | * Command 27 | * Interpreter 28 | * Iterator 29 | * Mediator 30 | * Memento 31 | * Observer 32 | * State 33 | * Strategy 34 | * Template method 35 | * Visitor 36 | 37 | Concurrency patterns 38 | -------------------- 39 | * Balking 40 | * Future 41 | * Thread pool 42 | -------------------------------------------------------------------------------- /behavior/chain_of_responsibility.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Handler interface { 8 | Request(flag bool) 9 | } 10 | 11 | type ConcreteHandlerA struct { 12 | next Handler 13 | } 14 | 15 | func (h *ConcreteHandlerA) Request(flag bool) { 16 | fmt.Println("ConcreteHandlerA.Request()") 17 | if flag { 18 | h.next.Request(flag) 19 | } 20 | } 21 | 22 | type ConcreteHandlerB struct { 23 | next Handler 24 | } 25 | 26 | func (h *ConcreteHandlerB) Request(flag bool) { 27 | fmt.Println("ConcreteHandlerB.Request()") 28 | } 29 | 30 | func main() { 31 | handlerA := &ConcreteHandlerA{new(ConcreteHandlerB)} 32 | handlerA.Request(true) 33 | } 34 | -------------------------------------------------------------------------------- /behavior/command.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Command interface { 8 | Execute() 9 | } 10 | 11 | type ConcreteCommandA struct { 12 | receiver *Receiver 13 | } 14 | 15 | func (c *ConcreteCommandA) Execute() { 16 | c.receiver.Action("CommandA") 17 | } 18 | 19 | type ConcreteCommandB struct { 20 | receiver *Receiver 21 | } 22 | 23 | func (c *ConcreteCommandB) Execute() { 24 | c.receiver.Action("CommandB") 25 | } 26 | 27 | type Receiver struct{} 28 | 29 | func (r *Receiver) Action(msg string) { 30 | fmt.Println(msg) 31 | } 32 | 33 | type Invoker struct { 34 | history []Command 35 | } 36 | 37 | func (i *Invoker) StoreAndExecute(cmd Command) { 38 | i.history = append(i.history, cmd) 39 | for i, cmd := range i.history { 40 | fmt.Printf("history%d: ", i) 41 | cmd.Execute() 42 | } 43 | } 44 | 45 | func main() { 46 | receiver := new(Receiver) 47 | commandA := &ConcreteCommandA{receiver} 48 | commandB := &ConcreteCommandB{receiver} 49 | invoker := new(Invoker) 50 | invoker.StoreAndExecute(commandA) 51 | invoker.StoreAndExecute(commandB) 52 | } 53 | -------------------------------------------------------------------------------- /behavior/interpreter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type Expression interface { 9 | Interpret(variables map[string]Expression) int 10 | } 11 | 12 | type Number struct { 13 | number int 14 | } 15 | 16 | func (n *Number) Interpret(variables map[string]Expression) int { 17 | return n.number 18 | } 19 | 20 | type Plus struct { 21 | leftOperand Expression 22 | rightOperand Expression 23 | } 24 | 25 | func (p *Plus) Interpret(variables map[string]Expression) int { 26 | return p.leftOperand.Interpret(variables) + p.rightOperand.Interpret(variables) 27 | } 28 | 29 | type Minus struct { 30 | leftOperand Expression 31 | rightOperand Expression 32 | } 33 | 34 | func (m *Minus) Interpret(variables map[string]Expression) int { 35 | return m.leftOperand.Interpret(variables) - m.rightOperand.Interpret(variables) 36 | } 37 | 38 | type Variable struct { 39 | name string 40 | } 41 | 42 | func (v *Variable) Interpret(variables map[string]Expression) int { 43 | if variables[v.name] == nil { 44 | return 0 45 | } 46 | return variables[v.name].Interpret(variables) 47 | } 48 | 49 | type Evaluator struct { 50 | syntaxTree Expression 51 | } 52 | 53 | func NewEvaluator(expression string) *Evaluator { 54 | expressionStack := new(Stack) 55 | for _, token := range strings.Split(expression, " ") { 56 | if token == "+" { 57 | right := expressionStack.Pop().(Expression) 58 | left := expressionStack.Pop().(Expression) 59 | subExpression := &Plus{left, right} 60 | expressionStack.Push(subExpression) 61 | } else if token == "-" { 62 | right := expressionStack.Pop().(Expression) 63 | left := expressionStack.Pop().(Expression) 64 | subExpression := &Minus{left, right} 65 | expressionStack.Push(subExpression) 66 | } else { 67 | expressionStack.Push(&Variable{token}) 68 | } 69 | } 70 | syntaxTree := expressionStack.Pop().(Expression) 71 | return &Evaluator{syntaxTree} 72 | } 73 | 74 | func (e *Evaluator) Interpret(context map[string]Expression) int { 75 | return e.syntaxTree.Interpret(context) 76 | } 77 | 78 | type Element struct { 79 | value interface{} 80 | next *Element 81 | } 82 | 83 | type Stack struct { 84 | top *Element 85 | size int 86 | } 87 | 88 | func (s *Stack) Push(value interface{}) { 89 | s.top = &Element{value, s.top} 90 | s.size++ 91 | } 92 | 93 | func (s *Stack) Pop() interface{} { 94 | if s.size == 0 { 95 | return nil 96 | } 97 | value := s.top.value 98 | s.top = s.top.next 99 | s.size-- 100 | return value 101 | } 102 | 103 | func main() { 104 | expression := "w x z - +" 105 | sentence := NewEvaluator(expression) 106 | variables := make(map[string]Expression) 107 | variables["w"] = &Number{5} 108 | variables["x"] = &Number{10} 109 | variables["z"] = &Number{42} 110 | result := sentence.Interpret(variables) 111 | fmt.Println(result) 112 | } 113 | -------------------------------------------------------------------------------- /behavior/iterator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Iterator interface { 8 | Next() interface{} 9 | HasNext() bool 10 | } 11 | 12 | type ConcreteIterator struct { 13 | concreteAggregate *ConcreteAggregate 14 | index int 15 | } 16 | 17 | func (i *ConcreteIterator) Next() interface{} { 18 | if i.index >= len(i.concreteAggregate.slice) { 19 | return nil 20 | } 21 | defer func() { 22 | i.index++ 23 | }() 24 | return i.concreteAggregate.slice[i.index] 25 | } 26 | 27 | func (i *ConcreteIterator) HasNext() bool { 28 | return i.index < len(i.concreteAggregate.slice) 29 | } 30 | 31 | type Aggregate interface { 32 | Iterator() Iterator 33 | } 34 | 35 | type ConcreteAggregate struct { 36 | slice []string 37 | } 38 | 39 | func (a *ConcreteAggregate) Iterator() Iterator { 40 | return &ConcreteIterator{concreteAggregate: a} 41 | } 42 | 43 | func main() { 44 | slice := []string{"a", "b", "c", "d"} 45 | aggregate := &ConcreteAggregate{slice} 46 | for i := aggregate.Iterator(); i.HasNext(); { 47 | v := i.Next() 48 | fmt.Println(v) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /behavior/mediator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | type Mediator interface { 9 | AddColleague(colleague Colleague) 10 | Consultation(colleague Colleague) 11 | } 12 | 13 | type ConcreteMediator struct { 14 | colleagues *list.List 15 | } 16 | 17 | func NewConcreteMediator() *ConcreteMediator { 18 | return &ConcreteMediator{list.New()} 19 | } 20 | 21 | func (m *ConcreteMediator) AddColleague(colleague Colleague) { 22 | m.colleagues.PushBack(colleague) 23 | } 24 | 25 | func (m *ConcreteMediator) Consultation(colleague Colleague) { 26 | for e := m.colleagues.Front(); e != nil; e = e.Next() { 27 | if e.Value == colleague { 28 | switch e.Value.(type) { 29 | case *ConcreteColleagueA: 30 | fmt.Println("ConcreteColleagueA consulted") 31 | case *ConcreteColleagueB: 32 | fmt.Println("ConcreteColleagueB consulted") 33 | } 34 | } 35 | } 36 | } 37 | 38 | type Colleague interface { 39 | NeedsAdvice() 40 | } 41 | 42 | type ConcreteColleagueA struct { 43 | mediator Mediator 44 | } 45 | 46 | func (c *ConcreteColleagueA) NeedsAdvice() { 47 | c.mediator.Consultation(c) 48 | } 49 | 50 | type ConcreteColleagueB struct { 51 | mediator Mediator 52 | } 53 | 54 | func (c *ConcreteColleagueB) NeedsAdvice() { 55 | c.mediator.Consultation(c) 56 | } 57 | 58 | func main() { 59 | mediator := NewConcreteMediator() 60 | colleagueA := &ConcreteColleagueA{mediator} 61 | colleagueB := &ConcreteColleagueB{mediator} 62 | mediator.AddColleague(colleagueA) 63 | mediator.AddColleague(colleagueB) 64 | colleagueA.NeedsAdvice() 65 | colleagueB.NeedsAdvice() 66 | } 67 | -------------------------------------------------------------------------------- /behavior/memento.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Originator struct { 8 | state string 9 | } 10 | 11 | func (o *Originator) Set(state string) { 12 | fmt.Println("Setting state to " + state) 13 | o.state = state 14 | } 15 | 16 | func (o *Originator) SaveToMemento() Memento { 17 | fmt.Println("Saving to Memento.") 18 | return Memento{o.state} 19 | } 20 | 21 | func (o *Originator) RestoreFromMemento(memento Memento) { 22 | o.state = memento.GetSavedState() 23 | fmt.Println("State after restoring from Memento: " + o.state) 24 | } 25 | 26 | type Memento struct { 27 | state string 28 | } 29 | 30 | func (m *Memento) GetSavedState() string { 31 | return m.state 32 | } 33 | 34 | func main() { 35 | savedStates := make([]Memento, 0) 36 | originator := new(Originator) 37 | originator.Set("State1") 38 | originator.Set("State2") 39 | savedStates = append(savedStates, originator.SaveToMemento()) 40 | originator.Set("State3") 41 | savedStates = append(savedStates, originator.SaveToMemento()) 42 | originator.Set("State4") 43 | originator.RestoreFromMemento(savedStates[1]) 44 | } 45 | -------------------------------------------------------------------------------- /behavior/observer.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | type Observer interface { 9 | Notify() 10 | } 11 | 12 | type Subject struct { 13 | observerCollection *list.List 14 | } 15 | 16 | func NewSubject() *Subject { 17 | return &Subject{list.New()} 18 | } 19 | 20 | func (s *Subject) RegisterObserver(observer Observer) { 21 | s.observerCollection.PushBack(observer) 22 | } 23 | 24 | func (s *Subject) UnregisterObserver(observer Observer) { 25 | for e := s.observerCollection.Front(); e != nil; e = e.Next() { 26 | if observer == e.Value.(Observer) { 27 | s.observerCollection.Remove(e) 28 | return 29 | } 30 | } 31 | } 32 | 33 | func (s *Subject) NotifyObservers() { 34 | for e := s.observerCollection.Front(); e != nil; e = e.Next() { 35 | observer := e.Value.(Observer) 36 | observer.Notify() 37 | } 38 | } 39 | 40 | type ConcreteObserver struct{} 41 | 42 | func (c *ConcreteObserver) Notify() { 43 | fmt.Println("ConcreteObserver.Notify()") 44 | } 45 | 46 | func main() { 47 | observer := new(ConcreteObserver) 48 | subject := NewSubject() 49 | subject.RegisterObserver(observer) 50 | subject.NotifyObservers() 51 | subject.UnregisterObserver(observer) 52 | subject.NotifyObservers() 53 | } 54 | -------------------------------------------------------------------------------- /behavior/state.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Context struct { 8 | state State 9 | } 10 | 11 | func (c *Context) Request() { 12 | c.state.Handle() 13 | } 14 | 15 | func (c *Context) SetState(state State) { 16 | c.state = state 17 | } 18 | 19 | type State interface { 20 | Handle() 21 | } 22 | 23 | type ConcreteStateA struct{} 24 | 25 | func (s *ConcreteStateA) Handle() { 26 | fmt.Println("ConcreteStateA.Handle()") 27 | } 28 | 29 | type ConcreteStateB struct{} 30 | 31 | func (s *ConcreteStateB) Handle() { 32 | fmt.Println("ConcreteStateB.Handle()") 33 | } 34 | 35 | func main() { 36 | context := Context{new(ConcreteStateA)} 37 | context.Request() 38 | context.SetState(new(ConcreteStateB)) 39 | context.Request() 40 | } 41 | -------------------------------------------------------------------------------- /behavior/strategy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Context struct { 8 | strategy func() 9 | } 10 | 11 | func (c *Context) Execute() { 12 | c.strategy() 13 | } 14 | 15 | func (c *Context) SetStrategy(strategy func()) { 16 | c.strategy = strategy 17 | } 18 | 19 | func main() { 20 | concreteStrategyA := func() { 21 | fmt.Println("concreteStrategyA()") 22 | } 23 | concreteStrategyB := func() { 24 | fmt.Println("concreteStrategyB()") 25 | } 26 | context := Context{concreteStrategyA} 27 | context.Execute() 28 | context.SetStrategy(concreteStrategyB) 29 | context.Execute() 30 | } 31 | -------------------------------------------------------------------------------- /behavior/template_method.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type AbstractClass struct { 8 | template template 9 | } 10 | 11 | func (c *AbstractClass) TemplateMethod() { 12 | c.template.method1() 13 | c.template.method2() 14 | } 15 | 16 | type template interface { 17 | method1() 18 | method2() 19 | } 20 | 21 | type ConcreteClass struct{} 22 | 23 | func (c *ConcreteClass) method1() { 24 | fmt.Println("ConcreteClass.method1()") 25 | } 26 | 27 | func (c *ConcreteClass) method2() { 28 | fmt.Println("ConcreteClass.method2()") 29 | } 30 | 31 | func main() { 32 | abstractClass := AbstractClass{new(ConcreteClass)} 33 | abstractClass.TemplateMethod() 34 | } 35 | -------------------------------------------------------------------------------- /behavior/visitor.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Element interface { 8 | Accept(Visitor) 9 | } 10 | 11 | type ConcreteElementA struct{} 12 | 13 | func (e *ConcreteElementA) Accept(visitor Visitor) { 14 | fmt.Println("ConcreteElementA.Accept()") 15 | visitor.VisitA(e) 16 | } 17 | 18 | type ConcreteElementB struct{} 19 | 20 | func (e *ConcreteElementB) Accept(visitor Visitor) { 21 | fmt.Println("ConcreteElementB.Accept()") 22 | visitor.VisitB(e) 23 | } 24 | 25 | type Visitor interface { 26 | VisitA(*ConcreteElementA) 27 | VisitB(*ConcreteElementB) 28 | } 29 | 30 | type ConcreteVisitor struct{} 31 | 32 | func (v *ConcreteVisitor) VisitA(element *ConcreteElementA) { 33 | fmt.Println("ConcreteVisitor.VisitA()") 34 | } 35 | 36 | func (v *ConcreteVisitor) VisitB(element *ConcreteElementB) { 37 | fmt.Println("ConcreteVisitor.VisitB()") 38 | } 39 | 40 | func main() { 41 | visitor := new(ConcreteVisitor) 42 | elementA := new(ConcreteElementA) 43 | elementB := new(ConcreteElementB) 44 | elementA.Accept(visitor) 45 | elementB.Accept(visitor) 46 | } 47 | -------------------------------------------------------------------------------- /concurrency/balking.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | const ( 10 | num = 5 11 | ) 12 | 13 | var ( 14 | busy bool 15 | m sync.Mutex 16 | wg sync.WaitGroup 17 | ) 18 | 19 | func execute(id int) { 20 | defer wg.Done() 21 | m.Lock() 22 | if busy { 23 | log.Printf("Goroutine-%d: Process is busy!\n", id) 24 | m.Unlock() 25 | return 26 | } 27 | busy = true 28 | m.Unlock() 29 | log.Printf("Goroutine-%d: Now processing...\n", id) 30 | doSomething() 31 | log.Printf("Goroutine-%d: Process is completed.\n", id) 32 | busy = false 33 | } 34 | 35 | func doSomething() { 36 | time.Sleep(1 * time.Second) 37 | } 38 | 39 | func main() { 40 | wg.Add(num) 41 | for i := 0; i < num; i++ { 42 | go execute(i) 43 | } 44 | wg.Wait() 45 | } 46 | -------------------------------------------------------------------------------- /concurrency/future.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "time" 6 | ) 7 | 8 | type Future chan string 9 | 10 | type Executor struct{} 11 | 12 | func (e *Executor) Submit(fn func() string) Future { 13 | future := make(Future) 14 | go func() { 15 | val := fn() 16 | future <- val 17 | }() 18 | return future 19 | } 20 | 21 | func main() { 22 | task := func() string { 23 | log.Println("Task: Now processing...") 24 | time.Sleep(2 * time.Second) 25 | log.Println("Task: Process is completed.") 26 | return "Task has finished!" 27 | } 28 | executor := new(Executor) 29 | future := executor.Submit(task) 30 | log.Printf("Future result: %s\n", <-future) 31 | } 32 | -------------------------------------------------------------------------------- /concurrency/thread_pool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "time" 6 | ) 7 | 8 | var ( 9 | stop Runner 10 | ) 11 | 12 | func init() { 13 | stop = new(stopRunner) 14 | } 15 | 16 | type Runner interface { 17 | Run() 18 | } 19 | 20 | type stopRunner struct{} 21 | 22 | func (r *stopRunner) Run() {} 23 | 24 | type ThreadPool struct { 25 | queue chan Runner 26 | threads []*thread 27 | isRunning bool 28 | } 29 | 30 | func NewThreadPool(maxQueueSize int, numberOfThreads int) *ThreadPool { 31 | queue := make(chan Runner, maxQueueSize) 32 | threads := make([]*thread, numberOfThreads) 33 | for i := 0; i < len(threads); i++ { 34 | threads[i] = newThread(i, queue) 35 | } 36 | return &ThreadPool{queue, threads, false} 37 | } 38 | 39 | func (p *ThreadPool) Start() { 40 | if p.isRunning { 41 | panic("threads have been already started") 42 | } 43 | p.isRunning = true 44 | for _, thread := range p.threads { 45 | thread.start() 46 | } 47 | } 48 | 49 | func (p *ThreadPool) Stop() { 50 | if !p.isRunning { 51 | panic("threads have not been started") 52 | } 53 | for i := 0; i < len(p.threads); i++ { 54 | p.Dispatch(stop) 55 | } 56 | p.isRunning = false 57 | for _, th := range p.threads { 58 | th.join() 59 | } 60 | } 61 | 62 | func (p *ThreadPool) Dispatch(runner Runner) { 63 | if !p.isRunning { 64 | panic("this pool has not been started yet") 65 | } 66 | p.queue <- runner 67 | } 68 | 69 | type thread struct { 70 | id int 71 | queue chan Runner 72 | fin chan bool 73 | } 74 | 75 | func newThread(id int, queue chan Runner) *thread { 76 | return &thread{id, queue, make(chan bool)} 77 | } 78 | 79 | func (t *thread) start() { 80 | log.Printf("Thread-%d start\n", t.id) 81 | go func() { 82 | for { 83 | runner := <-t.queue 84 | if runner == stop { 85 | t.fin <- true 86 | return 87 | } else { 88 | runner.Run() 89 | } 90 | } 91 | }() 92 | } 93 | 94 | func (t *thread) join() { 95 | log.Printf("Thread-%d join\n", t.id) 96 | <-t.fin 97 | } 98 | 99 | type ConcreteRunnerA struct{} 100 | 101 | func (r *ConcreteRunnerA) Run() { 102 | time.Sleep(1 * time.Second) 103 | log.Println("ConcreteRunnerA.Run()") 104 | } 105 | 106 | type ConcreteRunnerB struct{} 107 | 108 | func (r *ConcreteRunnerB) Run() { 109 | time.Sleep(2 * time.Second) 110 | log.Println("ConcreteRunnerB.Run()") 111 | } 112 | 113 | func main() { 114 | runnerA := new(ConcreteRunnerA) 115 | runnerB := new(ConcreteRunnerB) 116 | threadPool := NewThreadPool(1, 3) 117 | threadPool.Start() 118 | threadPool.Dispatch(runnerA) 119 | threadPool.Dispatch(runnerA) 120 | threadPool.Dispatch(runnerB) 121 | threadPool.Stop() 122 | } 123 | -------------------------------------------------------------------------------- /creation/abstract_factory.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type AbstractFactory interface { 8 | CreateProductA() AbstractProductA 9 | CreateProductB() AbstractProductB 10 | } 11 | 12 | type ConcreteFactory1 struct{} 13 | 14 | func (f *ConcreteFactory1) CreateProductA() AbstractProductA { 15 | return new(ProductA1) 16 | } 17 | 18 | func (f *ConcreteFactory1) CreateProductB() AbstractProductB { 19 | return new(ProductB1) 20 | } 21 | 22 | type ConcreteFactory2 struct{} 23 | 24 | func (f *ConcreteFactory2) CreateProductA() AbstractProductA { 25 | return new(ProductA2) 26 | } 27 | 28 | func (f *ConcreteFactory2) CreateProductB() AbstractProductB { 29 | return new(ProductB2) 30 | } 31 | 32 | type AbstractProductA interface{} 33 | type AbstractProductB interface{} 34 | type ProductA1 struct{} 35 | type ProductA2 struct{} 36 | type ProductB1 struct{} 37 | type ProductB2 struct{} 38 | 39 | func main() { 40 | factory1 := new(ConcreteFactory1) 41 | factory2 := new(ConcreteFactory2) 42 | productA1 := factory1.CreateProductA() 43 | productB1 := factory1.CreateProductB() 44 | productA2 := factory2.CreateProductA() 45 | productB2 := factory2.CreateProductB() 46 | fmt.Printf("%T\n", productA1) 47 | fmt.Printf("%T\n", productB1) 48 | fmt.Printf("%T\n", productA2) 49 | fmt.Printf("%T\n", productB2) 50 | } 51 | -------------------------------------------------------------------------------- /creation/builder.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | ) 7 | 8 | type Product struct { 9 | name string 10 | price int 11 | } 12 | 13 | func (p *Product) String() string { 14 | return "Product [name=" + p.name + ", price=" + strconv.Itoa(p.price) + "]" 15 | } 16 | 17 | type Director struct { 18 | builder Builder 19 | } 20 | 21 | func (d *Director) Construct() *Product { 22 | d.builder.SetName() 23 | d.builder.SetPrice() 24 | return d.builder.GetResult() 25 | } 26 | 27 | type Builder interface { 28 | SetName() 29 | SetPrice() 30 | GetResult() *Product 31 | } 32 | 33 | type AppleBuilder struct { 34 | product *Product 35 | } 36 | 37 | func NewAppleBuilder() *AppleBuilder { 38 | return &AppleBuilder{new(Product)} 39 | } 40 | 41 | func (b *AppleBuilder) SetName() { 42 | b.product.name = "apple" 43 | } 44 | 45 | func (b *AppleBuilder) SetPrice() { 46 | b.product.price = 10 47 | } 48 | 49 | func (b *AppleBuilder) GetResult() *Product { 50 | return b.product 51 | } 52 | 53 | type OrangeBuilder struct { 54 | product *Product 55 | } 56 | 57 | func NewOrangeBuilder() *OrangeBuilder { 58 | return &OrangeBuilder{new(Product)} 59 | } 60 | 61 | func (b *OrangeBuilder) SetName() { 62 | b.product.name = "orange" 63 | } 64 | 65 | func (b *OrangeBuilder) SetPrice() { 66 | b.product.price = 20 67 | } 68 | 69 | func (b *OrangeBuilder) GetResult() *Product { 70 | return b.product 71 | } 72 | 73 | func main() { 74 | director1 := &Director{NewAppleBuilder()} 75 | director2 := &Director{NewOrangeBuilder()} 76 | product1 := director1.Construct() 77 | product2 := director2.Construct() 78 | fmt.Println(product1) 79 | fmt.Println(product2) 80 | } 81 | -------------------------------------------------------------------------------- /creation/factory_method.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Creator struct { 8 | factory factory 9 | } 10 | 11 | func (c *Creator) Operation() { 12 | product := c.factory.factoryMethod() 13 | product.method() 14 | } 15 | 16 | type factory interface { 17 | factoryMethod() Product 18 | } 19 | 20 | type ConcreteCreator struct{} 21 | 22 | func (c *ConcreteCreator) factoryMethod() Product { 23 | return new(ConcreteProduct) 24 | } 25 | 26 | type Product interface { 27 | method() 28 | } 29 | 30 | type ConcreteProduct struct{} 31 | 32 | func (p *ConcreteProduct) method() { 33 | fmt.Println("ConcreteProduct.method()") 34 | } 35 | 36 | func main() { 37 | creator := Creator{new(ConcreteCreator)} 38 | creator.Operation() 39 | } 40 | -------------------------------------------------------------------------------- /creation/object_pool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | "strconv" 7 | "sync" 8 | ) 9 | 10 | var ( 11 | uniqueID int 12 | ) 13 | 14 | type PooledObject struct { 15 | id int 16 | } 17 | 18 | func (o *PooledObject) String() string { 19 | return "PooledObject [id=" + strconv.Itoa(o.id) + "]" 20 | } 21 | 22 | type ObjectPool struct { 23 | mu sync.Mutex 24 | idle *list.List 25 | active *list.List 26 | } 27 | 28 | func NewObjectPool() *ObjectPool { 29 | idle := list.New() 30 | active := list.New() 31 | return &ObjectPool{idle: idle, active: active} 32 | } 33 | 34 | func (p *ObjectPool) BorrowObject() *PooledObject { 35 | p.mu.Lock() 36 | defer p.mu.Unlock() 37 | 38 | var object *PooledObject 39 | if p.idle.Len() <= 0 { 40 | object = &PooledObject{uniqueID} 41 | uniqueID++ 42 | } else { 43 | object = p.removeAt(p.idle, 0) 44 | } 45 | fmt.Printf("Borrow: %s\n", object) 46 | p.active.PushBack(object) 47 | return object 48 | } 49 | 50 | func (p *ObjectPool) ReturnObject(object *PooledObject) { 51 | p.mu.Lock() 52 | defer p.mu.Unlock() 53 | 54 | fmt.Printf("Return: %s\n", object) 55 | p.idle.PushBack(object) 56 | p.remove(p.active, object) 57 | } 58 | 59 | func (p *ObjectPool) remove(list *list.List, object *PooledObject) { 60 | for e := list.Front(); e != nil; e = e.Next() { 61 | if object == e.Value.(*PooledObject) { 62 | list.Remove(e) 63 | return 64 | } 65 | } 66 | } 67 | 68 | func (p *ObjectPool) removeAt(list *list.List, index int) *PooledObject { 69 | for e, i := list.Front(), 0; e != nil; e, i = e.Next(), i+1 { 70 | if index == i { 71 | return list.Remove(e).(*PooledObject) 72 | } 73 | } 74 | return nil 75 | } 76 | 77 | func main() { 78 | objectPool := NewObjectPool() 79 | object1 := objectPool.BorrowObject() 80 | objectPool.ReturnObject(object1) 81 | object2 := objectPool.BorrowObject() 82 | object3 := objectPool.BorrowObject() 83 | objectPool.ReturnObject(object2) 84 | objectPool.ReturnObject(object3) 85 | } 86 | -------------------------------------------------------------------------------- /creation/prototype.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Prototype interface { 8 | Clone() 9 | } 10 | 11 | type ConcretePrototype struct { 12 | name string 13 | } 14 | 15 | func (p *ConcretePrototype) Clone() *ConcretePrototype { 16 | return &ConcretePrototype{p.name} 17 | } 18 | 19 | func (p *ConcretePrototype) String() string { 20 | return "ConcretePrototype [name=" + p.name + "]" 21 | } 22 | 23 | func main() { 24 | prototype := &ConcretePrototype{"prototype1"} 25 | fmt.Println(prototype) 26 | fmt.Println(prototype.Clone()) 27 | } 28 | -------------------------------------------------------------------------------- /creation/singleton.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var instance *singleton = new(singleton) 4 | 5 | type singleton struct{} 6 | 7 | func GetInstance() *singleton { 8 | return instance 9 | } 10 | -------------------------------------------------------------------------------- /structure/adapter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Target interface { 8 | RequiredMethod() 9 | } 10 | 11 | type Adaptee struct{} 12 | 13 | func (a *Adaptee) OldMethod() { 14 | fmt.Println("Adaptee.OldMethod()") 15 | } 16 | 17 | type Adapter struct { 18 | adaptee *Adaptee 19 | } 20 | 21 | func NewAdapter() *Adapter { 22 | return &Adapter{new(Adaptee)} 23 | } 24 | 25 | func (a *Adapter) RequiredMethod() { 26 | fmt.Println("Adapter.RequiredMethod()") 27 | a.adaptee.OldMethod() 28 | } 29 | 30 | func main() { 31 | target := NewAdapter() 32 | target.RequiredMethod() 33 | } 34 | -------------------------------------------------------------------------------- /structure/bridge.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type DrawingAPI interface { 8 | DrawCircle(x, y, radius float32) 9 | } 10 | 11 | type DrawingAPI1 struct{} 12 | 13 | func (a *DrawingAPI1) DrawCircle(x, y, radius float32) { 14 | fmt.Printf("API1.circle at %f:%f radius %f\n", x, y, radius) 15 | } 16 | 17 | type DrawingAPI2 struct{} 18 | 19 | func (a *DrawingAPI2) DrawCircle(x, y, radius float32) { 20 | fmt.Printf("API2.circle at %f:%f radius %f\n", x, y, radius) 21 | } 22 | 23 | type Shape interface { 24 | Draw() 25 | ResizeByPercentage(pct float32) 26 | } 27 | 28 | type CircleShape struct { 29 | x, y, radius float32 30 | drawingAPI DrawingAPI 31 | } 32 | 33 | func (s *CircleShape) Draw() { 34 | s.drawingAPI.DrawCircle(s.x, s.y, s.radius) 35 | } 36 | 37 | func (s *CircleShape) ResizeByPercentage(pct float32) { 38 | s.radius *= pct 39 | } 40 | 41 | func main() { 42 | shapes := []Shape{&CircleShape{1, 2, 3, new(DrawingAPI1)}, &CircleShape{5, 7, 11, new(DrawingAPI2)}} 43 | for _, shape := range shapes { 44 | shape.ResizeByPercentage(2.5) 45 | shape.Draw() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /structure/composite.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Component interface { 8 | Operation(int) 9 | } 10 | 11 | type File struct { 12 | name string 13 | } 14 | 15 | func (f *File) Operation(depth int) { 16 | for i := 0; i < depth; i++ { 17 | fmt.Print(" ") 18 | } 19 | fmt.Println("File: " + f.name) 20 | } 21 | 22 | type Directory struct { 23 | components []Component 24 | name string 25 | } 26 | 27 | func (d *Directory) Operation(depth int) { 28 | for i := 0; i < depth; i++ { 29 | fmt.Print(" ") 30 | } 31 | fmt.Println("Directory: " + d.name) 32 | for _, component := range d.components { 33 | component.Operation(depth + 1) 34 | } 35 | } 36 | 37 | func (d *Directory) Add(component Component) { 38 | d.components = append(d.components, component) 39 | } 40 | 41 | func (d *Directory) Remove(component Component) { 42 | for i, v := range d.components { 43 | if v == component { 44 | d.remove(i) 45 | return 46 | } 47 | } 48 | } 49 | 50 | func (d *Directory) remove(i int) { 51 | reslice := append(d.components[:i], d.components[i+1:]...) 52 | newslice := make([]Component, len(reslice)) 53 | copy(newslice, reslice) 54 | d.components = newslice 55 | } 56 | 57 | func (d *Directory) GetChildren() []Component { 58 | return d.components 59 | } 60 | 61 | func main() { 62 | root := &Directory{name: "root"} 63 | usr := &Directory{name: "usr"} 64 | local := &Directory{name: "local"} 65 | home := &Directory{name: "home"} 66 | user1 := &Directory{name: "user1"} 67 | file1 := &File{name: "file1"} 68 | root.Add(usr) 69 | usr.Add(local) 70 | root.Add(home) 71 | home.Add(user1) 72 | user1.Add(file1) 73 | root.Operation(0) 74 | root.Remove(home) 75 | root.Operation(0) 76 | } 77 | -------------------------------------------------------------------------------- /structure/decorator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Component interface { 8 | Operation() string 9 | } 10 | 11 | type ConcreteComponent struct{} 12 | 13 | func (c *ConcreteComponent) Operation() string { 14 | return "ConcreteComponent.Operation()" 15 | } 16 | 17 | type ConcreteDecoratorA struct { 18 | component Component 19 | } 20 | 21 | func (d *ConcreteDecoratorA) Operation() string { 22 | if d.component == nil { 23 | return "ConcreteDecoratorA.Operation()" 24 | } else { 25 | return d.component.Operation() + " and ConcreteDecoratorA.Operation()" 26 | } 27 | } 28 | 29 | type ConcreteDecoratorB struct { 30 | component Component 31 | } 32 | 33 | func (d *ConcreteDecoratorB) Operation() string { 34 | if d.component == nil { 35 | return "ConcreteDecoratorB.Operation()" 36 | } else { 37 | return d.component.Operation() + " and ConcreteDecoratorB.Operation()" 38 | } 39 | } 40 | 41 | func main() { 42 | component := &ConcreteDecoratorA{&ConcreteDecoratorB{new(ConcreteComponent)}} 43 | fmt.Println(component.Operation()) 44 | } 45 | -------------------------------------------------------------------------------- /structure/facade.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | const ( 8 | BOOT_ADDRESS = 0 9 | BOOT_SECTOR = 0 10 | SECTOR_SIZE = 0 11 | ) 12 | 13 | type CPU struct{} 14 | 15 | func (c *CPU) Freeze() { 16 | fmt.Println("CPU.Freeze()") 17 | } 18 | 19 | func (c *CPU) Jump(position int) { 20 | fmt.Println("CPU.Jump()") 21 | } 22 | 23 | func (c *CPU) Execute() { 24 | fmt.Println("CPU.Execute()") 25 | } 26 | 27 | type Memory struct{} 28 | 29 | func (m *Memory) Load(position int, data []byte) { 30 | fmt.Println("Memory.Load()") 31 | } 32 | 33 | type HardDrive struct{} 34 | 35 | func (hd *HardDrive) Read(lba int, size int) []byte { 36 | fmt.Println("HardDrive.Read()") 37 | return make([]byte, 0) 38 | } 39 | 40 | type ComputerFacade struct { 41 | processor *CPU 42 | ram *Memory 43 | hd *HardDrive 44 | } 45 | 46 | func NewComputerFacade() *ComputerFacade { 47 | return &ComputerFacade{new(CPU), new(Memory), new(HardDrive)} 48 | } 49 | 50 | func (c *ComputerFacade) start() { 51 | c.processor.Freeze() 52 | c.ram.Load(BOOT_ADDRESS, c.hd.Read(BOOT_SECTOR, SECTOR_SIZE)) 53 | c.processor.Jump(BOOT_ADDRESS) 54 | c.processor.Execute() 55 | } 56 | 57 | func main() { 58 | computer := NewComputerFacade() 59 | computer.start() 60 | } 61 | -------------------------------------------------------------------------------- /structure/flyweight.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type FlyweightFactory struct { 8 | pool map[string]*Flyweight 9 | } 10 | 11 | func (f *FlyweightFactory) GetFlyweight(str string) *Flyweight { 12 | flyweight := f.pool[str] 13 | if flyweight == nil { 14 | fmt.Println("new: " + str) 15 | f.pool[str] = &Flyweight{str} 16 | } 17 | return flyweight 18 | } 19 | 20 | type Flyweight struct { 21 | str string 22 | } 23 | 24 | func main() { 25 | factory := &FlyweightFactory{make(map[string]*Flyweight)} 26 | factory.GetFlyweight("a") 27 | factory.GetFlyweight("p") 28 | factory.GetFlyweight("p") 29 | factory.GetFlyweight("l") 30 | factory.GetFlyweight("e") 31 | factory.GetFlyweight("!") 32 | factory.GetFlyweight("o") 33 | factory.GetFlyweight("r") 34 | factory.GetFlyweight("a") 35 | factory.GetFlyweight("n") 36 | factory.GetFlyweight("g") 37 | factory.GetFlyweight("e") 38 | factory.GetFlyweight("!") 39 | } 40 | -------------------------------------------------------------------------------- /structure/proxy.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | type Subject interface { 8 | DoAction() 9 | } 10 | 11 | type RealSubject struct{} 12 | 13 | func (s *RealSubject) DoAction() { 14 | fmt.Println("RealSubject.DoAction()") 15 | } 16 | 17 | type Proxy struct { 18 | realSubject *RealSubject 19 | } 20 | 21 | func (p *Proxy) DoAction() { 22 | if p.realSubject == nil { 23 | p.realSubject = new(RealSubject) 24 | } 25 | fmt.Println("Proxy.DoAction()") 26 | p.realSubject.DoAction() 27 | } 28 | 29 | func main() { 30 | subject := new(Proxy) 31 | subject.DoAction() 32 | } 33 | --------------------------------------------------------------------------------