mirror of
https://github.com/Estom/notes.git
synced 2026-03-23 05:30:09 +08:00
go知识重新整理
This commit is contained in:
67
Go/DesignPattern/Iterator/iterator.go
Normal file
67
Go/DesignPattern/Iterator/iterator.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package iterator
|
||||
|
||||
import "fmt"
|
||||
|
||||
//迭代器模式:使用相同的方式 迭代不同类型的集合 或者隐藏集合类型的具体实现
|
||||
|
||||
//聚合
|
||||
type Aggregate interface {
|
||||
Iterator() Iterator
|
||||
}
|
||||
|
||||
type Iterator interface {
|
||||
First()
|
||||
IsDone() bool
|
||||
Next() interface{}
|
||||
}
|
||||
|
||||
//NewNumbers
|
||||
func NewNumbers(start, end int) *Numbers {
|
||||
return &Numbers{
|
||||
start: start,
|
||||
end: end,
|
||||
}
|
||||
}
|
||||
|
||||
type Numbers struct {
|
||||
start, end int
|
||||
}
|
||||
|
||||
//NumbersIterator implement Iterator interface
|
||||
func (n *Numbers) Iterator() Iterator {
|
||||
return &NumbersIterator{
|
||||
numbers: n,
|
||||
next: n.start,
|
||||
}
|
||||
}
|
||||
|
||||
//NumbersIterator
|
||||
type NumbersIterator struct {
|
||||
numbers *Numbers
|
||||
next int
|
||||
}
|
||||
|
||||
func (i *NumbersIterator) First() {
|
||||
i.next = i.numbers.start
|
||||
}
|
||||
|
||||
func (i *NumbersIterator) IsDone() bool {
|
||||
return i.next > i.numbers.start
|
||||
}
|
||||
|
||||
func (i *NumbersIterator) Next() interface{} {
|
||||
if !i.IsDone() {
|
||||
next := i.next
|
||||
i.next++
|
||||
return next
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//迭代打印
|
||||
func IteratorPrint(i Iterator) {
|
||||
for i.First(); !i.IsDone(); {
|
||||
c := i.Next()
|
||||
fmt.Printf("%#v\n", c)
|
||||
}
|
||||
}
|
||||
16
Go/DesignPattern/Iterator/iterator_test.go
Normal file
16
Go/DesignPattern/Iterator/iterator_test.go
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午12:04
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package iterator
|
||||
|
||||
//以相同的方式迭代不同类型的集合
|
||||
|
||||
func ExampleIterator() {
|
||||
var aggregate Aggregate
|
||||
aggregate = NewNumbers(1, 10)
|
||||
|
||||
IteratorPrint(aggregate.Iterator())
|
||||
}
|
||||
41
Go/DesignPattern/adapter/adapter.go
Normal file
41
Go/DesignPattern/adapter/adapter.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package adapter
|
||||
|
||||
//适配器模式
|
||||
//应用最多的是在接口升级,而又需要保证老接口的兼容性,为了让老接口能够继续工作,所以提供了一个中间层,让老接口对外的接口不变
|
||||
//但是实际上调用了新的代码
|
||||
|
||||
//被适配接口的工厂函数
|
||||
func NewAdaptee() Adaptee {
|
||||
return &adapteeImpl{}
|
||||
}
|
||||
|
||||
//被适配的目标接口
|
||||
type Adaptee interface {
|
||||
SpecificRequest() string
|
||||
}
|
||||
|
||||
type adapteeImpl struct {
|
||||
}
|
||||
|
||||
func (*adapteeImpl) SpecificRequest() string {
|
||||
return "adaptee method被适配器方法"
|
||||
}
|
||||
|
||||
func NewAdapter(adaptee Adaptee) Target {
|
||||
return &adapter{
|
||||
Adaptee: adaptee,
|
||||
}
|
||||
}
|
||||
|
||||
//Target是适配的目标接口
|
||||
type Target interface {
|
||||
Request() string
|
||||
}
|
||||
|
||||
type adapter struct {
|
||||
Adaptee
|
||||
}
|
||||
|
||||
func (a *adapter) Request() string {
|
||||
return a.SpecificRequest()
|
||||
}
|
||||
20
Go/DesignPattern/adapter/adapter_test.go
Normal file
20
Go/DesignPattern/adapter/adapter_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午1:52
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package adapter
|
||||
|
||||
import "testing"
|
||||
|
||||
var expect = "adaptee method被适配器方法"
|
||||
|
||||
func TestAdapter(t *testing.T) {
|
||||
adaptee := NewAdaptee()
|
||||
target := NewAdapter(adaptee)
|
||||
res := target.Request()
|
||||
if res != expect {
|
||||
t.Fatalf("expect %s,return %s", expect, res)
|
||||
}
|
||||
}
|
||||
72
Go/DesignPattern/bridging/bridging.go
Normal file
72
Go/DesignPattern/bridging/bridging.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package bridging
|
||||
|
||||
import "fmt"
|
||||
|
||||
//桥接模式:分离抽象部分和是实现部分,使得两部分可以独立变化
|
||||
//桥接模式类似于策略模式,区别于策略模式封装一些列算法,使得算法可以相互替换
|
||||
|
||||
//将抽象部分SendMessage()与具体的实现部分Send()分离
|
||||
|
||||
//抽象部分:SendMessage
|
||||
type AbstractMessage interface {
|
||||
SendMessage(text, to string)
|
||||
}
|
||||
|
||||
//实现部分:Send
|
||||
type MessageImplementer interface {
|
||||
Send(text, to string)
|
||||
}
|
||||
|
||||
//via sms
|
||||
func ViaSMS() MessageImplementer {
|
||||
return &MessageSMS{}
|
||||
}
|
||||
|
||||
type MessageSMS struct {
|
||||
}
|
||||
|
||||
func (*MessageSMS) Send(text, to string) {
|
||||
fmt.Printf("send %s to %s via SMS", text, to)
|
||||
}
|
||||
|
||||
//via email
|
||||
func ViaEmail() MessageImplementer {
|
||||
return &MessageEmail{}
|
||||
}
|
||||
|
||||
type MessageEmail struct {
|
||||
}
|
||||
|
||||
func (MessageEmail) Send(text, to string) {
|
||||
fmt.Printf("send %s to via Email", text, to)
|
||||
}
|
||||
|
||||
//New commonMessage,method can be SMS or email
|
||||
func NewCommonMessage(method MessageImplementer) *CommonMessage {
|
||||
return &CommonMessage{
|
||||
method: method,
|
||||
}
|
||||
}
|
||||
|
||||
type CommonMessage struct {
|
||||
method MessageImplementer
|
||||
}
|
||||
|
||||
func (c *CommonMessage) SendMessage(text, to string) {
|
||||
c.method.Send(text, to)
|
||||
}
|
||||
|
||||
//New UrgencyMessage,method can be SMS or email
|
||||
func NewUrgencyMessage(method MessageImplementer) *UrgencyMessage {
|
||||
return &UrgencyMessage{
|
||||
method: method,
|
||||
}
|
||||
}
|
||||
|
||||
type UrgencyMessage struct {
|
||||
method MessageImplementer
|
||||
}
|
||||
|
||||
func (u *UrgencyMessage) SendMessage(text, to string) {
|
||||
u.method.Send(fmt.Sprintf("[Urgency] %s", text), to)
|
||||
}
|
||||
27
Go/DesignPattern/bridging/bridging_test.go
Normal file
27
Go/DesignPattern/bridging/bridging_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 上午9:32
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package bridging
|
||||
|
||||
func ExampleCommonSMS() {
|
||||
m := NewCommonMessage(ViaSMS())
|
||||
m.SendMessage("sending by sms:have a drink", "boo")
|
||||
}
|
||||
|
||||
func ExampleCommonEmail() {
|
||||
m := NewCommonMessage(ViaEmail())
|
||||
m.SendMessage("sending by email:have a drink", "boo")
|
||||
}
|
||||
|
||||
func ExampleUrgencySMS() {
|
||||
m := NewUrgencyMessage(ViaSMS())
|
||||
m.SendMessage("have a drink", "boo")
|
||||
}
|
||||
|
||||
func ExampleUrgencyEmail() {
|
||||
m := NewUrgencyMessage(ViaEmail())
|
||||
m.SendMessage("have a drink", "boo")
|
||||
}
|
||||
89
Go/DesignPattern/buidler/buidler.go
Normal file
89
Go/DesignPattern/buidler/buidler.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package buidler
|
||||
|
||||
//builder模式适用的场景:无法或者不想一次性把实例的所有属性都给出,而是要分批次、分条件构造
|
||||
|
||||
// 不是这样 a:=SomeStruct{1,2,"hello"}
|
||||
|
||||
//而是这样
|
||||
/*
|
||||
a:=SomeStruct{}
|
||||
a.setAge(1)
|
||||
a.setMonth(2)
|
||||
if(situation){
|
||||
a.setSomething("hello")
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//builder模式除了上边的形式,还有一种变种,那就是链式(在每个函数最后返回实例自身)
|
||||
/*
|
||||
a:=SomeStruct{}
|
||||
a = a.setAge(1).setMonth(2).setSomething("hello")
|
||||
*/
|
||||
|
||||
//生成器接口
|
||||
type Builder interface {
|
||||
Part1()
|
||||
Part2()
|
||||
Part3()
|
||||
}
|
||||
|
||||
//
|
||||
func NewDirector(builder Builder) *Director {
|
||||
return &Director{
|
||||
builder: builder,
|
||||
}
|
||||
}
|
||||
|
||||
type Director struct {
|
||||
builder Builder
|
||||
}
|
||||
|
||||
func (d *Director) Construct() {
|
||||
d.builder.Part1()
|
||||
d.builder.Part2()
|
||||
d.builder.Part3()
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
type Builder1 struct {
|
||||
result string
|
||||
}
|
||||
|
||||
func (b *Builder1) Part1() {
|
||||
b.result += "1"
|
||||
}
|
||||
|
||||
func (b *Builder1) Part2() {
|
||||
b.result += "2"
|
||||
}
|
||||
|
||||
func (b *Builder1) Part3() {
|
||||
b.result += "3"
|
||||
}
|
||||
|
||||
func (b *Builder1) GetResult() string {
|
||||
return b.result
|
||||
}
|
||||
|
||||
//
|
||||
type Builder2 struct {
|
||||
result int
|
||||
}
|
||||
|
||||
func (b *Builder2) Part1() {
|
||||
b.result += 1
|
||||
}
|
||||
|
||||
func (b *Builder2) Part2() {
|
||||
b.result += 2
|
||||
}
|
||||
|
||||
func (b *Builder2) Part3() {
|
||||
b.result += 3
|
||||
}
|
||||
|
||||
func (b *Builder2) GetResult() int {
|
||||
return b.result
|
||||
}
|
||||
30
Go/DesignPattern/buidler/buidler_test.go
Normal file
30
Go/DesignPattern/buidler/buidler_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/13 上午11:31
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package buidler
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestBuilder1(t *testing.T) {
|
||||
builder := &Builder1{}
|
||||
director := NewDirector(builder)
|
||||
director.Construct()
|
||||
res := builder.GetResult()
|
||||
if res != "123" {
|
||||
t.Fatalf("Builder1 fail expect 123 ,return %s", res)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestBuilder2(t *testing.T) {
|
||||
builder := &Builder2{}
|
||||
director := NewDirector(builder)
|
||||
director.Construct()
|
||||
res := builder.GetResult()
|
||||
if res != 6 {
|
||||
t.Fatalf("Buidler2 fail expect 6,return %d", res)
|
||||
}
|
||||
}
|
||||
119
Go/DesignPattern/chain/chain.go
Normal file
119
Go/DesignPattern/chain/chain.go
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午3:46
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package chain
|
||||
|
||||
import "fmt"
|
||||
|
||||
//责任链模式:用于分离不同职责,并且动态组合相关职责
|
||||
//golang因为没有继承的支持,在实现责任链的时候,使用链对象 涵盖 职责的方式,
|
||||
//即:
|
||||
//1、链对象包含当前职责对象以及下一个职责链
|
||||
//2、职责对象提供接口表示 是否能处理对应请求
|
||||
//3、职责对象提供处理函数的相关职责
|
||||
// 同时在职责链类中实现职责接口相关函数,使职责链对象可以当做一般职责对象使用
|
||||
|
||||
type Manager interface {
|
||||
HaveRight(money int) bool
|
||||
HandleFeeRequest(name string, money int) bool
|
||||
}
|
||||
|
||||
//
|
||||
type RequestChain struct {
|
||||
Manager
|
||||
successor *RequestChain
|
||||
}
|
||||
|
||||
//connected r Chain with m Chain
|
||||
func (r *RequestChain) SetSuccessor(m *RequestChain) {
|
||||
r.successor = m
|
||||
}
|
||||
|
||||
func (r *RequestChain) HandleFeeRequest(name string, money int) bool {
|
||||
if r.Manager.HaveRight(money) {
|
||||
return r.Manager.HandleFeeRequest(name, money)
|
||||
}
|
||||
if r.successor != nil {
|
||||
return r.successor.HandleFeeRequest(name, money)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *RequestChain) HaveRight(money int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
//new chain by projectManager
|
||||
//职责:ProjectManager
|
||||
func NewProjectManagerChain() *RequestChain {
|
||||
return &RequestChain{
|
||||
Manager: &ProjectManager{},
|
||||
}
|
||||
}
|
||||
|
||||
type ProjectManager struct {
|
||||
}
|
||||
|
||||
func (p *ProjectManager) HaveRight(money int) bool {
|
||||
return money < 50
|
||||
}
|
||||
|
||||
func (p *ProjectManager) HandleFeeRequest(name string, money int) bool {
|
||||
if name == "bob" {
|
||||
fmt.Printf("Project manager permit %s %d fee request\n", name, money)
|
||||
return true
|
||||
}
|
||||
fmt.Printf("Project manager do not permit %s fee request\n", name, money)
|
||||
return false
|
||||
}
|
||||
|
||||
//new chain by DepManager
|
||||
//职责:DepManager
|
||||
func NewDepManagerChain() *RequestChain {
|
||||
return &RequestChain{
|
||||
Manager: &DepManager{},
|
||||
}
|
||||
}
|
||||
|
||||
type DepManager struct {
|
||||
}
|
||||
|
||||
func (d *DepManager) HaveRight(money int) bool {
|
||||
return money < 5000
|
||||
}
|
||||
|
||||
func (d *DepManager) HandleFeeRequest(name string, money int) bool {
|
||||
if name == "bob" {
|
||||
fmt.Printf("dep manager permit %s %d fee request\n", name, money)
|
||||
return true
|
||||
}
|
||||
fmt.Printf("dep manager do not permit %s fee request\n", name, money)
|
||||
return false
|
||||
}
|
||||
|
||||
//new chain by GeneralManager
|
||||
//职责:GeneralManager
|
||||
func NewGeneralManagerChain() *RequestChain {
|
||||
return &RequestChain{
|
||||
Manager: &GeneralManager{},
|
||||
}
|
||||
}
|
||||
|
||||
type GeneralManager struct {
|
||||
}
|
||||
|
||||
func (g *GeneralManager) HaveRight(money int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *GeneralManager) HandleFeeRequest(name string, money int) bool {
|
||||
if name == "bob" {
|
||||
fmt.Printf("general manager permit %s %d fee request\n", name, money)
|
||||
return true
|
||||
}
|
||||
fmt.Printf("general manager do not permit %s fee request\n", name, money)
|
||||
return false
|
||||
}
|
||||
28
Go/DesignPattern/chain/chain_test.go
Normal file
28
Go/DesignPattern/chain/chain_test.go
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/13 上午9:50
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package chain
|
||||
|
||||
func ExampleChain() {
|
||||
|
||||
//创建好每个节点的Manager
|
||||
chain1 := NewProjectManagerChain()
|
||||
chain2 := NewDepManagerChain()
|
||||
chain3 := NewGeneralManagerChain()
|
||||
|
||||
//connected r Chain with m Chain
|
||||
chain1.SetSuccessor(chain2)
|
||||
chain2.SetSuccessor(chain3)
|
||||
|
||||
var c Manager = chain1
|
||||
|
||||
c.HandleFeeRequest("bob", 400) //Project
|
||||
c.HandleFeeRequest("tom", 1400) //Dep
|
||||
c.HandleFeeRequest("fool", 10000) //General
|
||||
//
|
||||
c.HandleFeeRequest("tony", 300) //Project
|
||||
|
||||
}
|
||||
81
Go/DesignPattern/command/command.go
Normal file
81
Go/DesignPattern/command/command.go
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 上午10:58
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package command
|
||||
|
||||
import "fmt"
|
||||
|
||||
//命令模式:本质是把某个对象的"方法调用"-》封装到对象中,方便传输、存储、调用
|
||||
//使用命令模式还可以用作: 批处理、任务队列、undo,redo等,
|
||||
|
||||
type Command interface {
|
||||
Execute()
|
||||
}
|
||||
|
||||
//MotherBoard
|
||||
type MotherBoard struct {
|
||||
}
|
||||
|
||||
func (*MotherBoard) Start() {
|
||||
fmt.Print("system starting\n")
|
||||
}
|
||||
|
||||
func (*MotherBoard) Reboot() {
|
||||
fmt.Print("system rebooting\n")
|
||||
}
|
||||
|
||||
//NewStart
|
||||
func NewStartCommand(mb *MotherBoard) *StartCommand {
|
||||
return &StartCommand{
|
||||
mb: mb,
|
||||
}
|
||||
}
|
||||
|
||||
// 将启动操作封装到了StartCommand对象中
|
||||
type StartCommand struct {
|
||||
mb *MotherBoard
|
||||
}
|
||||
|
||||
func (s *StartCommand) Execute() {
|
||||
s.mb.Start()
|
||||
}
|
||||
|
||||
//NewReboot
|
||||
func NewRebootCommand(mb *MotherBoard) *RebootCommond {
|
||||
return &RebootCommond{
|
||||
mb: mb,
|
||||
}
|
||||
}
|
||||
|
||||
// 将reboot操作封装到了额RebootCommond对象中
|
||||
type RebootCommond struct {
|
||||
mb *MotherBoard
|
||||
}
|
||||
|
||||
func (r *RebootCommond) Execute() {
|
||||
r.mb.Reboot()
|
||||
}
|
||||
|
||||
//NewBox
|
||||
func NewBox(button1, button2 Command) *Box {
|
||||
return &Box{
|
||||
button1: button1,
|
||||
button2: button2,
|
||||
}
|
||||
}
|
||||
|
||||
type Box struct {
|
||||
button1 Command
|
||||
button2 Command
|
||||
}
|
||||
|
||||
func (b *Box) PressButton1() {
|
||||
b.button1.Execute()
|
||||
}
|
||||
|
||||
func (b *Box) PressButton2() {
|
||||
b.button2.Execute()
|
||||
}
|
||||
29
Go/DesignPattern/command/command_test.go
Normal file
29
Go/DesignPattern/command/command_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 上午11:40
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package command
|
||||
|
||||
//将"方法调用"封装到对象中,方便传输、调用、存储
|
||||
func ExampleCommand() {
|
||||
mb := &MotherBoard{}
|
||||
|
||||
startCommand := NewStartCommand(mb)
|
||||
rebootCommond := NewRebootCommand(mb)
|
||||
|
||||
box1 := NewBox(startCommand, rebootCommond)
|
||||
box1.PressButton1()
|
||||
box1.PressButton2()
|
||||
//output:
|
||||
//system starting
|
||||
//system rebooting
|
||||
|
||||
box2 := NewBox(rebootCommond, startCommand)
|
||||
box2.PressButton1()
|
||||
box2.PressButton2()
|
||||
//output:
|
||||
//system rebooting
|
||||
//system starting
|
||||
}
|
||||
95
Go/DesignPattern/composite/composite.go
Normal file
95
Go/DesignPattern/composite/composite.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package composite
|
||||
|
||||
import "fmt"
|
||||
|
||||
//组合模式:统一对象和对象集,使得使用相同接口操作对象和对象集
|
||||
//组合模式常用于树状结构,用于统一叶子节点和树节点的访问,并且可以用于应用某一操作到所有子节点
|
||||
|
||||
type Component interface {
|
||||
Parent() Component
|
||||
SetParent(Component)
|
||||
Name() string
|
||||
SetName(string)
|
||||
AddChild(Component)
|
||||
Print(string)
|
||||
}
|
||||
|
||||
const (
|
||||
LeafNode = iota
|
||||
CompositeNode
|
||||
)
|
||||
|
||||
//new Component
|
||||
func NewComponent(kind int, name string) Component {
|
||||
var c Component
|
||||
switch kind {
|
||||
case LeafNode:
|
||||
c = NewLeaf()
|
||||
case CompositeNode:
|
||||
c = NewComposite()
|
||||
}
|
||||
c.SetName(name)
|
||||
return c
|
||||
}
|
||||
|
||||
//component 树节点
|
||||
type component struct {
|
||||
parent Component
|
||||
name string
|
||||
}
|
||||
|
||||
func (c *component) Parent() Component {
|
||||
return c.parent
|
||||
}
|
||||
func (c *component) SetParent(parent Component) {
|
||||
c.parent = parent
|
||||
}
|
||||
func (c *component) Name() string {
|
||||
return c.name
|
||||
}
|
||||
func (c *component) SetName(name string) {
|
||||
c.name = name
|
||||
}
|
||||
func (c *component) AddChild(Component) {}
|
||||
func (c *component) Print(string) {
|
||||
}
|
||||
|
||||
//new leaf
|
||||
func NewLeaf() *Leaf {
|
||||
return &Leaf{}
|
||||
}
|
||||
|
||||
//叶子节点
|
||||
type Leaf struct {
|
||||
component
|
||||
}
|
||||
|
||||
func (c *Leaf) Print(pre string) {
|
||||
fmt.Printf("%s-%s\n", pre, c.name)
|
||||
}
|
||||
|
||||
// new 组合
|
||||
func NewComposite() *Composite {
|
||||
return &Composite{
|
||||
childs: make([]Component, 0),
|
||||
}
|
||||
}
|
||||
|
||||
//组合
|
||||
type Composite struct {
|
||||
component
|
||||
childs []Component
|
||||
}
|
||||
|
||||
func (c *Composite) AddChild(child Component) {
|
||||
child.SetParent(c)
|
||||
c.childs = append(c.childs, child)
|
||||
}
|
||||
|
||||
func (c *Composite) Print(pre string) {
|
||||
fmt.Printf("%s+%s\n", pre, c.Name())
|
||||
pre += " "
|
||||
for _, comp := range c.childs {
|
||||
comp.Print(pre)
|
||||
}
|
||||
}
|
||||
7
Go/DesignPattern/composite/composite_test.go
Normal file
7
Go/DesignPattern/composite/composite_test.go
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午2:52
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package composite
|
||||
46
Go/DesignPattern/decorator/decorator.go
Normal file
46
Go/DesignPattern/decorator/decorator.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package decorator
|
||||
|
||||
//装饰模式:使用对象组合的方式,动态改变或增加对象行为
|
||||
|
||||
type Component interface {
|
||||
Calc() int
|
||||
}
|
||||
|
||||
type ConcreteComponent struct{}
|
||||
|
||||
func (*ConcreteComponent) Calc() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
//warp mul
|
||||
func WarpMulDecorator(c Component, num int) Component {
|
||||
return &MulDecorator{
|
||||
Component: c,
|
||||
num: num,
|
||||
}
|
||||
}
|
||||
|
||||
type MulDecorator struct {
|
||||
Component
|
||||
num int
|
||||
}
|
||||
|
||||
func (m *MulDecorator) Calc() int {
|
||||
return m.Component.Calc() * m.num
|
||||
}
|
||||
|
||||
func WarpAddDecrator(c Component, num int) Component {
|
||||
return &AddDecrator{
|
||||
Component: c,
|
||||
num: num,
|
||||
}
|
||||
}
|
||||
|
||||
type AddDecrator struct {
|
||||
Component
|
||||
num int
|
||||
}
|
||||
|
||||
func (d *AddDecrator) Calc() int {
|
||||
return d.Component.Calc() + d.num
|
||||
}
|
||||
22
Go/DesignPattern/decorator/decorator_test.go
Normal file
22
Go/DesignPattern/decorator/decorator_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午3:46
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package decorator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecrator(t *testing.T) {
|
||||
var c Component = &ConcreteComponent{}
|
||||
c = WarpAddDecrator(c, 10)
|
||||
c = WarpMulDecorator(c, 8)
|
||||
res := c.Calc()
|
||||
if res != 80 {
|
||||
t.Fatalf("expect 80 ,return %d", res)
|
||||
}
|
||||
|
||||
}
|
||||
63
Go/DesignPattern/facade/facade.go
Normal file
63
Go/DesignPattern/facade/facade.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package facade
|
||||
|
||||
import "fmt"
|
||||
|
||||
//外观模式:随着项目越来越大,代码之间可能会有一些顺序,如果把他们封装起来,
|
||||
//那么对于调用者而言,
|
||||
//就只需要调用一个函数 ,而并不需要知道这个函数里面具体做了什么,有什么依赖顺序
|
||||
|
||||
//隐藏了内部实现,调用者只需要调用一个函数
|
||||
//New apiImpl
|
||||
func NewAPI() API {
|
||||
return &apiImpl{
|
||||
a: NewAmoudleAPI(),
|
||||
b: NewBMoudleAPI(),
|
||||
}
|
||||
}
|
||||
|
||||
//API是一个外观模式 接口
|
||||
type API interface {
|
||||
Test() string
|
||||
}
|
||||
|
||||
//外观模式实现
|
||||
type apiImpl struct {
|
||||
a AMouduleAPI
|
||||
b BMouduleAPI
|
||||
}
|
||||
|
||||
func (a *apiImpl) Test() string {
|
||||
aRet := a.a.TestA()
|
||||
bRet := a.b.TestB()
|
||||
return fmt.Sprintf("%s\n%s", aRet, bRet)
|
||||
}
|
||||
|
||||
//New aMoudleImpl
|
||||
func NewAmoudleAPI() AMouduleAPI {
|
||||
return &aMouduleImpl{}
|
||||
}
|
||||
|
||||
//AMouduleAPI
|
||||
type AMouduleAPI interface {
|
||||
TestA() string
|
||||
}
|
||||
type aMouduleImpl struct{}
|
||||
|
||||
func (*aMouduleImpl) TestA() string {
|
||||
return "A moudle running"
|
||||
}
|
||||
|
||||
//New bMoudleImpl
|
||||
func NewBMoudleAPI() BMouduleAPI {
|
||||
return &bMoudleImpl{}
|
||||
}
|
||||
|
||||
//BMouduleAPI
|
||||
type BMouduleAPI interface {
|
||||
TestB() string
|
||||
}
|
||||
type bMoudleImpl struct{}
|
||||
|
||||
func (*bMoudleImpl) TestB() string {
|
||||
return "B module running"
|
||||
}
|
||||
13
Go/DesignPattern/facade/facade_test.go
Normal file
13
Go/DesignPattern/facade/facade_test.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package facade
|
||||
|
||||
import "testing"
|
||||
|
||||
var expect = "A moudle running\nB module running"
|
||||
|
||||
func TestFacadeAPI(t *testing.T) {
|
||||
api := NewAPI()
|
||||
ret := api.Test()
|
||||
if ret != expect {
|
||||
t.Fatalf("expect %s,return %s", expect, ret)
|
||||
}
|
||||
}
|
||||
65
Go/DesignPattern/flyWeight/flyWeight.go
Normal file
65
Go/DesignPattern/flyWeight/flyWeight.go
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午2:55
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package flyWeight
|
||||
|
||||
import "fmt"
|
||||
|
||||
// 享元模式:从对象中剥离不发生改变,并且多个实例需要的重复数据,独立出来一个享元,让多个对象来共享,从而节省内存以及减少对象数量
|
||||
|
||||
type ImageFlyWeightFactory struct {
|
||||
maps map[string]*ImageFlyWeight
|
||||
}
|
||||
|
||||
var imageFatory *ImageFlyWeightFactory
|
||||
|
||||
func GetImageFlyFactory() *ImageFlyWeightFactory {
|
||||
if imageFatory == nil {
|
||||
imageFatory = &ImageFlyWeightFactory{
|
||||
maps: make(map[string]*ImageFlyWeight),
|
||||
}
|
||||
}
|
||||
return imageFatory
|
||||
}
|
||||
func (f *ImageFlyWeightFactory) Get(filename string) *ImageFlyWeight {
|
||||
image := f.maps[filename]
|
||||
if image == nil {
|
||||
image = NewImageFlyWeight(filename)
|
||||
f.maps[filename] = image
|
||||
}
|
||||
return image
|
||||
}
|
||||
|
||||
func NewImageFlyWeight(filename string) *ImageFlyWeight {
|
||||
//load image file
|
||||
data := fmt.Sprintf("image data %s", filename)
|
||||
return &ImageFlyWeight{
|
||||
data: data,
|
||||
}
|
||||
}
|
||||
|
||||
type ImageFlyWeight struct {
|
||||
data string
|
||||
}
|
||||
|
||||
func (i *ImageFlyWeight) Data() string {
|
||||
return i.data
|
||||
}
|
||||
|
||||
func NewImageViewr(filename string) *ImageViewer {
|
||||
image := GetImageFlyFactory().Get(filename)
|
||||
return &ImageViewer{
|
||||
ImageFlyWeight: image,
|
||||
}
|
||||
}
|
||||
|
||||
type ImageViewer struct {
|
||||
*ImageFlyWeight
|
||||
}
|
||||
|
||||
func (i *ImageViewer) Display() {
|
||||
fmt.Printf("Display:%s\n", i.Data())
|
||||
}
|
||||
17
Go/DesignPattern/flyWeight/flyweight_test.go
Normal file
17
Go/DesignPattern/flyWeight/flyweight_test.go
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午3:27
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package flyWeight
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFlyWeight(t *testing.T) {
|
||||
viewer1 := NewImageViewr("image1.png")
|
||||
viewer2 := NewImageViewr("image1.png")
|
||||
if viewer1.ImageFlyWeight != viewer2.ImageFlyWeight {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
100
Go/DesignPattern/interpreter/interpreter.go
Normal file
100
Go/DesignPattern/interpreter/interpreter.go
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午3:05
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package interpreter
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//解释器模式:定义了一套语言文法,并设计该语言的解释器。使用户能使用特定文法-》控制解释器的行为
|
||||
//解释器模式的意义在于,它分离多种复杂功能的实现,每个功能只需要关注自身的解释
|
||||
//对于调用者不同关心内部的解释器的具体工作,只需要用简单的方式组合命令就可以了。
|
||||
|
||||
type Node interface {
|
||||
Interpret() int
|
||||
}
|
||||
|
||||
type ValNode struct {
|
||||
val int
|
||||
}
|
||||
|
||||
func (v *ValNode) Interpret() int {
|
||||
return v.val
|
||||
}
|
||||
|
||||
//add
|
||||
type AddNode struct {
|
||||
left, right Node
|
||||
}
|
||||
|
||||
func (a *AddNode) Interpret() int {
|
||||
return a.left.Interpret() + a.right.Interpret()
|
||||
}
|
||||
|
||||
//min
|
||||
type MinNode struct {
|
||||
left, right Node
|
||||
}
|
||||
|
||||
func (m *MinNode) Interpret() int {
|
||||
return m.left.Interpret() - m.right.Interpret()
|
||||
}
|
||||
|
||||
//解析器
|
||||
type Parser struct {
|
||||
exp []string
|
||||
index int
|
||||
prev Node
|
||||
}
|
||||
|
||||
func (p *Parser) Parse(exp string) {
|
||||
p.exp = strings.Split(exp, " ")
|
||||
|
||||
for {
|
||||
if p.index >= len(p.exp) {
|
||||
return
|
||||
}
|
||||
|
||||
switch p.exp[p.index] {
|
||||
case "+":
|
||||
p.prev = p.newAddNode()
|
||||
case "_":
|
||||
p.prev = p.newMinNode()
|
||||
default:
|
||||
p.prev = p.newValNode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) newAddNode() Node {
|
||||
p.index++
|
||||
return &AddNode{
|
||||
left: p.prev,
|
||||
right: p.newValNode(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) newMinNode() Node {
|
||||
p.index++
|
||||
return &MinNode{
|
||||
left: p.prev,
|
||||
right: p.newValNode(),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) newValNode() Node {
|
||||
v, _ := strconv.Atoi(p.exp[p.index])
|
||||
p.index++
|
||||
return &ValNode{
|
||||
val: v,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) Result() Node {
|
||||
return p.prev
|
||||
}
|
||||
19
Go/DesignPattern/interpreter/interpreter_test.go
Normal file
19
Go/DesignPattern/interpreter/interpreter_test.go
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午3:35
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package interpreter
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestInterpreter(t *testing.T) {
|
||||
p := Parser{}
|
||||
p.Parse("1 + 2 + 3 - 4 + 5 - 6")
|
||||
res := p.Result().Interpret()
|
||||
expect := 1
|
||||
if res != expect {
|
||||
t.Fatalf("expect %d got %d", expect, res)
|
||||
}
|
||||
}
|
||||
86
Go/DesignPattern/mediator/mediator.go
Normal file
86
Go/DesignPattern/mediator/mediator.go
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 上午9:52
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package mediator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//中介模式:封装对象之间的交互,使依赖变得简单,并且是复杂交互简单化
|
||||
//例子中的中介者使用单例模式生成
|
||||
|
||||
type CDDriver struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
func (c *CDDriver) ReadData() {
|
||||
c.Data = "music,image"
|
||||
fmt.Printf("CDDriver:reading data %s\n", c.Data)
|
||||
|
||||
}
|
||||
|
||||
type CPU struct {
|
||||
Video string
|
||||
Sound string
|
||||
}
|
||||
|
||||
func (c *CPU) Process(data string) {
|
||||
sp := strings.Split(data, ",")
|
||||
c.Sound = sp[0]
|
||||
c.Video = sp[1]
|
||||
|
||||
fmt.Printf("CPU:split data with Sound %s,Video %s\n", c.Sound, c.Video)
|
||||
GetMediatorInstance().changed(c)
|
||||
}
|
||||
|
||||
type VideoCard struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
func (v *VideoCard) Display(data string) {
|
||||
v.Data = data
|
||||
fmt.Printf("VideoCard:display %s\n", v.Data)
|
||||
GetMediatorInstance().changed(v)
|
||||
}
|
||||
|
||||
type SoundCard struct {
|
||||
Data string
|
||||
}
|
||||
|
||||
func (s *SoundCard) Play(data string) {
|
||||
s.Data = data
|
||||
fmt.Printf("SoundCard:play %s\n", s.Data)
|
||||
GetMediatorInstance().changed(s)
|
||||
}
|
||||
|
||||
//封装Mediator对象
|
||||
type Mediator struct {
|
||||
CD *CDDriver
|
||||
CPU *CPU
|
||||
Video *VideoCard
|
||||
Sound *SoundCard
|
||||
}
|
||||
|
||||
var mediator *Mediator
|
||||
|
||||
func GetMediatorInstance() *Mediator {
|
||||
if mediator == nil {
|
||||
mediator = &Mediator{}
|
||||
}
|
||||
return mediator
|
||||
}
|
||||
|
||||
func (m *Mediator) changed(i interface{}) {
|
||||
switch inst := i.(type) {
|
||||
case *CDDriver:
|
||||
m.CPU.Process(inst.Data)
|
||||
case *CPU:
|
||||
m.Sound.Play(inst.Sound)
|
||||
m.Video.Display(inst.Video)
|
||||
}
|
||||
}
|
||||
37
Go/DesignPattern/mediator/mediator_test.go
Normal file
37
Go/DesignPattern/mediator/mediator_test.go
Normal file
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 上午10:16
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package mediator
|
||||
|
||||
import "testing"
|
||||
|
||||
//中介模式
|
||||
func TestMediator(t *testing.T) {
|
||||
mediator := GetMediatorInstance()
|
||||
mediator.CD = &CDDriver{}
|
||||
mediator.Video = &VideoCard{}
|
||||
mediator.Sound = &SoundCard{}
|
||||
mediator.CPU = &CPU{}
|
||||
|
||||
//run
|
||||
mediator.CD.ReadData()
|
||||
|
||||
if mediator.CD.Data != "music,image" {
|
||||
t.Fatalf("CD unexpect data %s", mediator.CD.Data)
|
||||
}
|
||||
if mediator.CPU.Sound != "music" {
|
||||
t.Fatalf("CPU unexpect data %s", mediator.CPU.Sound)
|
||||
}
|
||||
if mediator.CPU.Video != "image" {
|
||||
t.Fatalf("CPU unexpect data data %s", mediator.CPU.Video)
|
||||
}
|
||||
if mediator.Video.Data != "image" {
|
||||
t.Fatalf("VidelCard unexpect data %s", mediator.Video.Data)
|
||||
}
|
||||
if mediator.Sound.Data != "music" {
|
||||
t.Fatalf("SoundCard unexpect data %s", mediator.Sound.Data)
|
||||
}
|
||||
}
|
||||
10
Go/DesignPattern/memento/memento.go
Normal file
10
Go/DesignPattern/memento/memento.go
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午3:01
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package memento
|
||||
|
||||
//备忘录模式用于保存内部状态到外部,右不希望暴露内部状态的情形
|
||||
//
|
||||
51
Go/DesignPattern/observer/observer.go
Normal file
51
Go/DesignPattern/observer/observer.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package observer
|
||||
|
||||
import "fmt"
|
||||
|
||||
//观察者模式:用于触发联动,一个对象的改变会触发其他观察者的相关动作,而此对象无需关心联动对象的具体实现
|
||||
|
||||
func NewSubject() *Subject {
|
||||
return &Subject{
|
||||
observers: make([]Observer, 0),
|
||||
}
|
||||
}
|
||||
|
||||
type Subject struct {
|
||||
observers []Observer
|
||||
context string
|
||||
}
|
||||
|
||||
type Observer interface {
|
||||
Update(*Subject)
|
||||
}
|
||||
|
||||
func (s *Subject) Attach(o Observer) {
|
||||
s.observers = append(s.observers, o)
|
||||
}
|
||||
|
||||
//notify every observers
|
||||
func (s *Subject) notify() {
|
||||
for _, o := range s.observers {
|
||||
o.Update(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Subject) UpdateContext(context string) {
|
||||
s.context = context
|
||||
//notify all observers
|
||||
s.notify()
|
||||
}
|
||||
|
||||
func NewReader(name string) *Reader {
|
||||
return &Reader{
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
type Reader struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (r *Reader) Update(s *Subject) {
|
||||
fmt.Printf("%s receive %s\n", r.name, s.context)
|
||||
}
|
||||
23
Go/DesignPattern/observer/observer_test.go
Normal file
23
Go/DesignPattern/observer/observer_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 上午10:49
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package observer
|
||||
|
||||
func ExampleObserver() {
|
||||
Subject := NewSubject()
|
||||
|
||||
reader1 := NewReader("reader1")
|
||||
reader2 := NewReader("reader2")
|
||||
reader3 := NewReader("reader3")
|
||||
|
||||
Subject.Attach(reader1)
|
||||
Subject.Attach(reader2)
|
||||
Subject.Attach(reader3)
|
||||
|
||||
//update and notify all obervers
|
||||
Subject.UpdateContext("observer mode")
|
||||
|
||||
}
|
||||
27
Go/DesignPattern/proto/proto.go
Normal file
27
Go/DesignPattern/proto/proto.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package proto
|
||||
|
||||
//原型模式:使对象能复制自身,并暴露到接口中,使客户端面向接口编程时,不知道接口实际对象的情况下可以生成新的对象
|
||||
//原型模式配合管理器使用,通过接口管理器可以在客户端不知道具体类型的情况下,得到新的实例,并且包含部分预设的配置
|
||||
|
||||
type Cloneable interface {
|
||||
Clone() Cloneable
|
||||
}
|
||||
|
||||
//
|
||||
func NewProtoManager() *ProtoManager {
|
||||
return &ProtoManager{
|
||||
protos: make(map[string]Cloneable),
|
||||
}
|
||||
}
|
||||
|
||||
type ProtoManager struct {
|
||||
protos map[string]Cloneable
|
||||
}
|
||||
|
||||
func (p *ProtoManager) Get(name string) Cloneable {
|
||||
return p.protos[name]
|
||||
}
|
||||
|
||||
func (p *ProtoManager) Set(name string, proto Cloneable) {
|
||||
p.protos[name] = proto
|
||||
}
|
||||
56
Go/DesignPattern/proto/proto_test.go
Normal file
56
Go/DesignPattern/proto/proto_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/13 上午11:48
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package proto
|
||||
|
||||
import "testing"
|
||||
|
||||
var manager *ProtoManager
|
||||
|
||||
//
|
||||
type Type1 struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (t *Type1) Clone() Cloneable {
|
||||
//将值放进新的地址中
|
||||
tc := *t
|
||||
return &tc
|
||||
}
|
||||
|
||||
//
|
||||
type Type2 struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (t *Type2) Clone() Cloneable {
|
||||
//将值放进新的地址中
|
||||
tc := *t
|
||||
return &tc
|
||||
}
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
t1 := manager.Get("t1")
|
||||
t2 := t1.Clone()
|
||||
if t1 == t2 {
|
||||
t.Fatal("error, get clone do not working")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCloneFromManager(t *testing.T) {
|
||||
c := manager.Get("t1").Clone()
|
||||
t1 := c.(*Type1)
|
||||
if t1.name != "type1" {
|
||||
t.Fatal("error!")
|
||||
}
|
||||
}
|
||||
func init() {
|
||||
manager = NewProtoManager()
|
||||
t1 := &Type1{
|
||||
name: "type1",
|
||||
}
|
||||
manager.Set("t1", t1)
|
||||
}
|
||||
40
Go/DesignPattern/proxy/proxy.go
Normal file
40
Go/DesignPattern/proxy/proxy.go
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午2:03
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package proxy
|
||||
|
||||
//代理模式:用于延迟处理操作或者进行实际操作前后进行其他处理
|
||||
//代理模式的常见用法:虚代理、COW代理、远程代理、保护代理、Cache代理、防火墙代理、同步代理、智能指引等
|
||||
|
||||
type Subject interface {
|
||||
Do() string
|
||||
}
|
||||
|
||||
type RealSubject struct {
|
||||
}
|
||||
|
||||
func (RealSubject) Do() string {
|
||||
return "going to do something"
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
real RealSubject
|
||||
}
|
||||
|
||||
func (p Proxy) Do() string {
|
||||
var res string
|
||||
|
||||
//在调用想要做的工作之前,做一些事情,如检查缓存、判断权限、实例化真实对象等
|
||||
res += "pre to do :"
|
||||
|
||||
//实际要做的事情
|
||||
res += p.real.Do()
|
||||
|
||||
//调用之后执行的操作,如缓存结果,对结果进行处理等
|
||||
res += ": after to do"
|
||||
|
||||
return res
|
||||
}
|
||||
20
Go/DesignPattern/proxy/proxy_test.go
Normal file
20
Go/DesignPattern/proxy/proxy_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/11 下午2:13
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package proxy
|
||||
|
||||
import "testing"
|
||||
|
||||
var expect = "pre to do :going to do something: after to do"
|
||||
|
||||
func TestProxy(t *testing.T) {
|
||||
var sub Subject
|
||||
sub = &Proxy{}
|
||||
res := sub.Do()
|
||||
if res != expect {
|
||||
t.Fatalf("expect %s ,return %s", expect, res)
|
||||
}
|
||||
}
|
||||
24
Go/DesignPattern/single/single.go
Normal file
24
Go/DesignPattern/single/single.go
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午4:14
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package single
|
||||
|
||||
import "sync"
|
||||
|
||||
//单例模式:使用懒惰模式的单例模式,使用双重检查加锁保证线程安全
|
||||
|
||||
type Singleton struct {
|
||||
}
|
||||
|
||||
var singelton *Singleton
|
||||
var once sync.Once
|
||||
|
||||
func GetInstance() *Singleton {
|
||||
once.Do(func() {
|
||||
singelton = &Singleton{}
|
||||
})
|
||||
return singelton
|
||||
}
|
||||
45
Go/DesignPattern/single/single_test.go
Normal file
45
Go/DesignPattern/single/single_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/13 上午10:48
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package single
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const parCount = 100
|
||||
|
||||
func TestSingleton(t *testing.T) {
|
||||
ins1 := GetInstance()
|
||||
ins2 := GetInstance()
|
||||
if ins1 != ins2 {
|
||||
t.Fatal("instance is not equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParalleSingleton(t *testing.T) {
|
||||
start := make(chan struct{})
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(parCount)
|
||||
instances := [parCount]*Singleton{}
|
||||
for i := 0; i < parCount; i++ {
|
||||
go func(index int) {
|
||||
//等待channel的关闭信号
|
||||
<-start
|
||||
instances[index] = GetInstance()
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
//关闭channel,发送关闭信号
|
||||
close(start)
|
||||
wg.Wait()
|
||||
for i := 1; i < parCount; i++ {
|
||||
if instances[i] != instances[i-1] {
|
||||
t.Fatal("instance is not equal")
|
||||
}
|
||||
}
|
||||
}
|
||||
111
Go/DesignPattern/state/state.go
Normal file
111
Go/DesignPattern/state/state.go
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午2:16
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package state
|
||||
|
||||
import "fmt"
|
||||
|
||||
//状态模式:用于分离 状态和行为
|
||||
|
||||
type Week interface {
|
||||
Today()
|
||||
Next(*DayContext)
|
||||
}
|
||||
|
||||
//
|
||||
func NewTodayContext() *DayContext {
|
||||
return &DayContext{
|
||||
today: &Sunday{},
|
||||
}
|
||||
}
|
||||
|
||||
type DayContext struct {
|
||||
today Week
|
||||
}
|
||||
|
||||
func (d *DayContext) Today() {
|
||||
d.today.Today()
|
||||
}
|
||||
|
||||
func (d *DayContext) Next() {
|
||||
d.today.Next(d)
|
||||
}
|
||||
|
||||
//sunday
|
||||
type Sunday struct {
|
||||
}
|
||||
|
||||
func (*Sunday) Today() {
|
||||
fmt.Print("sunday\n")
|
||||
}
|
||||
|
||||
func (*Sunday) Next(ctx *DayContext) {
|
||||
ctx.today = &Monday{}
|
||||
}
|
||||
|
||||
//Monday
|
||||
type Monday struct {
|
||||
}
|
||||
|
||||
func (*Monday) Today() {
|
||||
fmt.Print("Monday\n")
|
||||
}
|
||||
|
||||
func (*Monday) Next(ctx *DayContext) {
|
||||
ctx.today = &Tuesday{}
|
||||
}
|
||||
|
||||
//Tuesday
|
||||
type Tuesday struct {
|
||||
}
|
||||
|
||||
func (*Tuesday) Today() {
|
||||
fmt.Print("Tuesday\n")
|
||||
}
|
||||
|
||||
func (*Tuesday) Next(ctx *DayContext) {
|
||||
ctx.today = &Wednesday{}
|
||||
}
|
||||
|
||||
type Wednesday struct{}
|
||||
|
||||
func (*Wednesday) Today() {
|
||||
fmt.Printf("Wednesday\n")
|
||||
}
|
||||
|
||||
func (*Wednesday) Next(ctx *DayContext) {
|
||||
ctx.today = &Thursday{}
|
||||
}
|
||||
|
||||
type Thursday struct{}
|
||||
|
||||
func (*Thursday) Today() {
|
||||
fmt.Printf("Thursday\n")
|
||||
}
|
||||
|
||||
func (*Thursday) Next(ctx *DayContext) {
|
||||
ctx.today = &Friday{}
|
||||
}
|
||||
|
||||
type Friday struct{}
|
||||
|
||||
func (*Friday) Today() {
|
||||
fmt.Printf("Friday\n")
|
||||
}
|
||||
|
||||
func (*Friday) Next(ctx *DayContext) {
|
||||
ctx.today = &Saturday{}
|
||||
}
|
||||
|
||||
type Saturday struct{}
|
||||
|
||||
func (*Saturday) Today() {
|
||||
fmt.Printf("Saturday\n")
|
||||
}
|
||||
|
||||
func (*Saturday) Next(ctx *DayContext) {
|
||||
ctx.today = &Sunday{}
|
||||
}
|
||||
20
Go/DesignPattern/state/state_test.go
Normal file
20
Go/DesignPattern/state/state_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午2:53
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package state
|
||||
|
||||
func ExampleWeek() {
|
||||
ctx := NewTodayContext()
|
||||
todayAndNext := func() {
|
||||
ctx.Today()
|
||||
ctx.Next()
|
||||
}
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
todayAndNext()
|
||||
}
|
||||
|
||||
}
|
||||
56
Go/DesignPattern/strategy/strategy.go
Normal file
56
Go/DesignPattern/strategy/strategy.go
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午1:50
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package strategy
|
||||
|
||||
import "fmt"
|
||||
|
||||
//策略模式:定义一系列算法,让这些算法在运行时可以互换,使得算法分离,符合开闭原则
|
||||
|
||||
type PaymentContext struct {
|
||||
Name, CardID string
|
||||
Money int
|
||||
}
|
||||
|
||||
func NewPayment(name, cardID string, money int, strategy PaymentStrategy) *Payment {
|
||||
return &Payment{
|
||||
context: &PaymentContext{
|
||||
Name: name,
|
||||
CardID: cardID,
|
||||
Money: money,
|
||||
},
|
||||
strategy: strategy,
|
||||
}
|
||||
}
|
||||
|
||||
type Payment struct {
|
||||
context *PaymentContext
|
||||
strategy PaymentStrategy
|
||||
}
|
||||
|
||||
func (p *Payment) Pay() {
|
||||
p.strategy.Pay(p.context)
|
||||
}
|
||||
|
||||
type PaymentStrategy interface {
|
||||
Pay(*PaymentContext)
|
||||
}
|
||||
|
||||
//by cash
|
||||
type Cash struct {
|
||||
}
|
||||
|
||||
func (*Cash) Pay(ctx *PaymentContext) {
|
||||
fmt.Printf("Pay $%d to %s by cash", ctx.Money, ctx.Name)
|
||||
}
|
||||
|
||||
//by Bank
|
||||
type Bank struct {
|
||||
}
|
||||
|
||||
func (*Bank) Pay(ctx *PaymentContext) {
|
||||
fmt.Printf("Pay $%d to %s by Bank", ctx.Money, ctx.Name)
|
||||
}
|
||||
20
Go/DesignPattern/strategy/strategy_test.go
Normal file
20
Go/DesignPattern/strategy/strategy_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午2:06
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package strategy
|
||||
|
||||
func ExamplePayByCash() {
|
||||
payment := NewPayment("ad", "808490523", 900, &Cash{})
|
||||
payment.Pay()
|
||||
//Output:
|
||||
//Pay by cash
|
||||
|
||||
}
|
||||
|
||||
func ExamplePayByBank() {
|
||||
payment := NewPayment("tom", "345782345", 900, &Bank{})
|
||||
payment.Pay()
|
||||
}
|
||||
77
Go/DesignPattern/template/template.go
Normal file
77
Go/DesignPattern/template/template.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package template
|
||||
|
||||
import "fmt"
|
||||
|
||||
//模板模式:模板模式使用集成机制,把通用的步骤和通用方法放到父类中,把具体实现延迟到子类中实现。是的实现符合开闭原则
|
||||
//golang中不提供继承,需要使用匿名组合模拟实现继承
|
||||
//此处需要注意:因为父类需要调用子类方法,所以子类需要匿名组合父类的同时,父类需要持有子类的引用
|
||||
|
||||
type Downloader interface {
|
||||
Download(uri string)
|
||||
}
|
||||
|
||||
type implement interface {
|
||||
download()
|
||||
save()
|
||||
}
|
||||
|
||||
//newTemplate
|
||||
func newTemplate(impl implement) *template {
|
||||
return &template{
|
||||
implement: impl,
|
||||
}
|
||||
}
|
||||
|
||||
type template struct {
|
||||
implement
|
||||
uri string
|
||||
}
|
||||
|
||||
func (t *template) Download(uri string) {
|
||||
t.uri = uri
|
||||
fmt.Print("prepare to download\n")
|
||||
|
||||
t.implement.download()
|
||||
t.implement.save()
|
||||
fmt.Print("finish download\n")
|
||||
}
|
||||
|
||||
func (t *template) save() {
|
||||
fmt.Print("default save\n")
|
||||
}
|
||||
|
||||
//NewHTTPDownloader
|
||||
func NewHTTPDownloader() Downloader {
|
||||
downloader := &HTTPDownloader{}
|
||||
template := newTemplate(downloader)
|
||||
downloader.template = template
|
||||
return downloader
|
||||
}
|
||||
|
||||
type HTTPDownloader struct {
|
||||
*template
|
||||
}
|
||||
|
||||
func (h *HTTPDownloader) download() {
|
||||
fmt.Printf("download %s via http\n", h.uri)
|
||||
}
|
||||
|
||||
func (*HTTPDownloader) save() {
|
||||
fmt.Printf("http save\n")
|
||||
}
|
||||
|
||||
//NewFTPDownloader
|
||||
func NewFTPDownloader() Downloader {
|
||||
downloader := &FPTDownloader{}
|
||||
template := newTemplate(downloader)
|
||||
downloader.template = template
|
||||
return downloader
|
||||
}
|
||||
|
||||
type FPTDownloader struct {
|
||||
*template
|
||||
}
|
||||
|
||||
func (f *FPTDownloader) download() {
|
||||
fmt.Printf("download %s via ftp\n", f.uri)
|
||||
}
|
||||
7
Go/DesignPattern/template/template_test.go
Normal file
7
Go/DesignPattern/template/template_test.go
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午1:12
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package template
|
||||
88
Go/DesignPattern/visitor/visitor.go
Normal file
88
Go/DesignPattern/visitor/visitor.go
Normal file
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/12 下午4:12
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package visitor
|
||||
|
||||
import "fmt"
|
||||
|
||||
//访问者模式: 可以给一系列对象透明的添加功能,并且把相关代码封装到一个类中
|
||||
//对象只要预留访问者接口Accept,则在后期为独享添加功能的时候就不需要改动对象了
|
||||
|
||||
type Customer interface {
|
||||
Accept(Visitor)
|
||||
}
|
||||
|
||||
type Visitor interface {
|
||||
Visit(Customer)
|
||||
}
|
||||
|
||||
type CustomerCol struct {
|
||||
customers []Customer
|
||||
}
|
||||
|
||||
func (c *CustomerCol) Add(customer Customer) {
|
||||
c.customers = append(c.customers, customer)
|
||||
}
|
||||
|
||||
func (c *CustomerCol) Accept(visitor Visitor) {
|
||||
for _, customer := range c.customers {
|
||||
customer.Accept(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
//New EnterpriseCustomer
|
||||
func NewEnterpriseCustomer(name string) *EnterpriseCustomer {
|
||||
return &EnterpriseCustomer{
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
type EnterpriseCustomer struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (c *EnterpriseCustomer) Accept(visitor Visitor) {
|
||||
visitor.Visit(c)
|
||||
}
|
||||
|
||||
//New IndividualCustomer
|
||||
func NewIndividualCustomer(name string) *IndividualCustomer {
|
||||
return &IndividualCustomer{
|
||||
name: name,
|
||||
}
|
||||
}
|
||||
|
||||
type IndividualCustomer struct {
|
||||
name string
|
||||
}
|
||||
|
||||
func (i *IndividualCustomer) Accept(visitor Visitor) {
|
||||
visitor.Visit(i)
|
||||
}
|
||||
|
||||
//
|
||||
type ServiceRequestVisitor struct {
|
||||
}
|
||||
|
||||
func (s *ServiceRequestVisitor) Visit(customer Customer) {
|
||||
switch c := customer.(type) {
|
||||
case *EnterpriseCustomer:
|
||||
fmt.Printf("serving enterprise customer %s\n", c.name)
|
||||
case *IndividualCustomer:
|
||||
fmt.Printf("serving Individual customer %s\n", c.name)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
type AnalisisVisitor struct {
|
||||
}
|
||||
|
||||
func (*AnalisisVisitor) Visit(customer Customer) {
|
||||
switch c := customer.(type) {
|
||||
case *EnterpriseCustomer:
|
||||
fmt.Printf("analysis enterprise customer %s\n", c.name)
|
||||
}
|
||||
}
|
||||
31
Go/DesignPattern/visitor/visitor_test.go
Normal file
31
Go/DesignPattern/visitor/visitor_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @Author:zhoutao
|
||||
* @Date:2020/12/13 上午10:31
|
||||
* @Desc:
|
||||
*/
|
||||
|
||||
package visitor
|
||||
|
||||
func ExampleRequestVisitor() {
|
||||
c := CustomerCol{}
|
||||
c.Add(NewEnterpriseCustomer("NO.1"))
|
||||
c.Add(NewEnterpriseCustomer("NO.2"))
|
||||
c.Add(NewIndividualCustomer("bob"))
|
||||
c.Accept(&ServiceRequestVisitor{})
|
||||
//output :
|
||||
// enterprise
|
||||
// enterprise
|
||||
// individual
|
||||
}
|
||||
|
||||
func ExampleAnalisis() {
|
||||
c := CustomerCol{}
|
||||
c.Add(NewEnterpriseCustomer("A"))
|
||||
c.Add(NewIndividualCustomer("B"))
|
||||
c.Add(NewEnterpriseCustomer("C"))
|
||||
c.Accept(&AnalisisVisitor{})
|
||||
//output :
|
||||
// enterprise
|
||||
// enterprise
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user