go知识重新整理

This commit is contained in:
Estom
2021-09-03 05:34:34 +08:00
parent 62309f856a
commit 1bad082e49
291 changed files with 29345 additions and 2 deletions

View 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)
}
}

View 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())
}

View 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()
}

View 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)
}
}

View 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)
}

View 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")
}

View 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
}

View 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)
}
}

View 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
}

View 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
}

View 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()
}

View 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
}

View 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)
}
}

View File

@@ -0,0 +1,7 @@
/**
* @Author:zhoutao
* @Date:2020/12/11 下午2:52
* @Desc:
*/
package composite

View 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
}

View 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)
}
}

View 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"
}

View 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)
}
}

View 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())
}

View 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()
}
}

View 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
}

View 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)
}
}

View 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)
}
}

View 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)
}
}

View File

@@ -0,0 +1,10 @@
/**
* @Author:zhoutao
* @Date:2020/12/12 下午3:01
* @Desc:
*/
package memento
//备忘录模式用于保存内部状态到外部,右不希望暴露内部状态的情形
//

View 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)
}

View 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")
}

View 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
}

View 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)
}

View 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
}

View 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)
}
}

View 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
}

View 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")
}
}
}

View 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{}
}

View 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()
}
}

View 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)
}

View 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()
}

View 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)
}

View File

@@ -0,0 +1,7 @@
/**
* @Author:zhoutao
* @Date:2020/12/12 下午1:12
* @Desc:
*/
package template

View 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)
}
}

View 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
}