Go ——设计模式
Go ——设计模式 simple_factory 简单工厂 package test const ( APITypeHi = iota + 1 APITypeHello ) type Greeting interface { Say(msg string) string } func NewGreeting(t int) Greeting { if t == APITypeHi { return &Hi{} } else if t == APITypeHello { return &Hello{} } return nil } type Hi struct{} func (h *Hi) Say(msg string) string { return "Hi! " + msg } type Hello struct{} func (h *Hello) Say(msg string) string { return "Hello! " + msg } package test import "testing" func TestGreeting(t *testing.T) { tests := []struct { name string apiType int msg string expected string }{ {"HiType", APITypeHi, "2026", "Hi! 2026"}, {"HelloType", APITypeHello, "2026", "Hello! 2026"}, {"NilType", 999, "2026", ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewGreeting(tt.apiType) if g == nil { if tt.expected != "" { t.Errorf("NewGreeting(%d) returned nil, expected non-nil", tt.apiType) } return } out := g.Say(tt.msg) if out != tt.expected { t.Errorf("Say() = %q, want %q", out, tt.expected) } }) } } facade 装饰器 package test type API interface { Test() string } func NewAPI() API { return &apiImpl{ a: NewAImpl(), b: NewBImpl(), } } type apiImpl struct { a AModule b BModule } func (api *apiImpl) Test() string { // 把两部分结果拼接返回 return api.a.TestA() + api.b.TestB() } // --- AModule --- type AModule interface { TestA() string } type AImpl struct{} func NewAImpl() AModule { return &AImpl{} } func (a *AImpl) TestA() string { return "testA ... " } // --- BModule --- type BModule interface { TestB() string } type BImpl struct{} func NewBImpl() BModule { return &BImpl{} } func (b *BImpl) TestB() string { return "testB ... " } package test import "testing" func TestFacade(t *testing.T) { api := NewAPI() out := api.Test() expected := "testA ... testB ... " if out != expected { t.Errorf("API Test() = %q, want %q", out, expected) } } adapter 适配器 package test type Adapter interface { Request() string } func NewAdapter(adaptee Adaptee) Adapter { return &adapter{ adaptee: adaptee, } } type adapter struct { adaptee Adaptee } func (a *adapter) Request() string { return a.adaptee.SpecificRequest() } // --- Adaptee 接口与实现 --- type Adaptee interface { SpecificRequest() string } type adaptee struct{} func NewAdaptee() Adaptee { return &adaptee{} } func (a *adaptee) SpecificRequest() string { return "specific request called" } package test import "testing" func TestAdapter(t *testing.T) { adaptee := NewAdaptee() adapter := NewAdapter(adaptee) out := adapter.Request() expected := "specific request called" if out != expected { t.Errorf("Adapter Request() = %q, want %q", out, expected) } } singleton 单例设计模式 package test import "sync" type Singleton interface { Foo() } type singleton struct{} func (s *singleton) Foo() {} var ( once sync.Once instance Singleton ) func GetSingleton() Singleton { once.Do(func() { instance = &singleton{} }) return instance } package test import ( "sync" "testing" ) const goroutineCount = 1000 // 单线程测试 func TestSingletonSingleThread(t *testing.T) { a := GetSingleton() b := GetSingleton() if a != b { t.Fatalf("Singleton failed: a != b") } } // 并发测试 func TestSingletonConcurrent(t *testing.T) { start := make(chan struct{}) instances := [goroutineCount]Singleton{} wg := sync.WaitGroup{} wg.Add(goroutineCount) for i := 0; i < goroutineCount; i++ { go func(idx int) { <-start instances[idx] = GetSingleton() wg.Done() }(i) } // 同时启动所有 goroutine close(start) wg.Wait() // 验证所有实例都相等 for i := 0; i < goroutineCount-1; i++ { if instances[i] != instances[i+1] { t.Fatalf("Singleton failed: instances[%d] != instances[%d]", i, i+1) } } } factory_method 工厂方法 package test // Operator 接口 type Operator interface { SetA(int) SetB(int) Result() int } // 工厂接口 type OperatorFactory interface { Create() Operator } // OperatorBase 提供公共字段与方法 type OperatorBase struct { a, b int } func (o *OperatorBase) SetA(a int) { o.a = a } func (o *OperatorBase) SetB(b int) { o.b = b } // PlusOperator type PlusOperator struct{ *OperatorBase } func (p *PlusOperator) Result() int { return p.a + p.b } // PlusOperatorFactory type PlusOperatorFactory struct{} func (PlusOperatorFactory) Create() Operator { return &PlusOperator{&OperatorBase{}} } // MinusOperator type MinusOperator struct{ *OperatorBase } func (m *MinusOperator) Result() int { return m.a - m.b } // MinusOperatorFactory type MinusOperatorFactory struct{} func (MinusOperatorFactory) Create() Operator { return &MinusOperator{&OperatorBase{}} } package test import "testing" func TestOperatorFactory(t *testing.T) { tests := []struct { name string factory OperatorFactory a, b int expected int }{ {"Plus", &PlusOperatorFactory{}, 1001, 10, 1011}, {"Minus", &MinusOperatorFactory{}, 1001, 10, 991}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { op := tt.factory.Create() op.SetA(tt.a) op.SetB(tt.b) if got := op.Result(); got != tt.expected { t.Fatalf("expected %v, got %v", tt.expected, got) } }) } } abstract_factory 抽象工厂 package test // OrderMainDAO 为订单主记录 type OrderMainDAO interface { SaveOrderMain() string } // OrderDetailDAO 为订单详情纪录 type OrderDetailDAO interface { SaveOrderDetail() string } // DAOFactory DAO 抽象工厂接口 type DAOFactory interface { CreateOrderMainDAO() OrderMainDAO CreateOrderDetailDAO() OrderDetailDAO } // ------------------ RDB 实现 ------------------ type RDBMainDAO struct{} func (*RDBMainDAO) SaveOrderMain() string { return "rdb main save" } type RDBDetailDAO struct{} func (*RDBDetailDAO) SaveOrderDetail() string { return "rdb detail save" } type RDBDAOFactory struct{} func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO { return &RDBMainDAO{} } func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO { return &RDBDetailDAO{} } // ------------------ XML 实现 ------------------ type XMLMainDAO struct{} func (*XMLMainDAO) SaveOrderMain() string { return "xml main save" } type XMLDetailDAO struct{} func (*XMLDetailDAO) SaveOrderDetail() string { return "xml detail save" } type XMLDAOFactory struct{} func (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO { return &XMLMainDAO{} } func (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO { return &XMLDetailDAO{} } package test import "testing" // GetMainAndDetail 调用工厂生成 DAO 并返回结果 func GetMainAndDetail(factory DAOFactory) (mainResult, detailResult string) { mainResult = factory.CreateOrderMainDAO().SaveOrderMain() detailResult = factory.CreateOrderDetailDAO().SaveOrderDetail() return } func TestAbstractFactory(t *testing.T) { tests := []struct { name string factory DAOFactory expectedMain string expectedDetail string }{ {"RDBFactory", &RDBDAOFactory{}, "rdb main save", "rdb detail save"}, {"XMLFactory", &XMLDAOFactory{}, "xml main save", "xml detail save"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mainResult, detailResult := GetMainAndDetail(tt.factory) if mainResult != tt.expectedMain { t.Errorf("mainResult = %q, want %q", mainResult, tt.expectedMain) } if detailResult != tt.expectedDetail { t.Errorf("detailResult = %q, want %q", detailResult, tt.expectedDetail) } }) } } builder 建造者 package test // Builder 是生成器接口 type Builder interface { Part1() Part2() Part3() } // Director 构建指挥者 type Director struct { builder Builder } // NewDirector ... func NewDirector(builder Builder) *Director { return &Director{builder: builder} } // Construct 构建产品 func (d *Director) Construct() { d.builder.Part1() d.builder.Part2() d.builder.Part3() } // ---------------- Builder1 ---------------- 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 } // ---------------- Builder2 ---------------- 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 } package test import "testing" func TestBuilder(t *testing.T) { tests := []struct { name string builder Builder expected interface{} getRes func() interface{} }{ { name: "Builder1", builder: &Builder1{}, expected: "123", getRes: func() interface{} { return (&Builder1{}).GetResult() }, }, { name: "Builder2", builder: &Builder2{}, expected: 6, getRes: func() interface{} { return (&Builder2{}).GetResult() }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d := NewDirector(tt.builder) d.Construct() var actual interface{} switch b := tt.builder.(type) { case *Builder1: actual = b.GetResult() case *Builder2: actual = b.GetResult() default: t.Fatalf("unsupported builder type") } if actual != tt.expected { t.Fatalf("expected %v, got %v", tt.expected, actual) } }) } } prototype 原型模式 package test // Cloneable 是原型对象需要实现的接口 type Cloneable interface { Clone() Cloneable } type PrototypeManager struct { prototypes map[string]Cloneable } func NewPrototypeManager() *PrototypeManager { return &PrototypeManager{ prototypes: make(map[string]Cloneable), } } // Get 返回指定名称的原型克隆对象 func (p *PrototypeManager) Get(name string) Cloneable { proto, ok := p.prototypes[name] if !ok { return nil } return proto.Clone() } // Set 注册原型对象 func (p *PrototypeManager) Set(name string, prototype Cloneable) { p.prototypes[name] = prototype } package test import "testing" // Type1 原型类型1 type Type1 struct { Name string } func (t *Type1) Clone() Cloneable { tc := *t return &tc } // Type2 原型类型2 type Type2 struct { Name string } func (t *Type2) Clone() Cloneable { tc := *t return &tc } func setupManager() *PrototypeManager { manager := NewPrototypeManager() manager.Set("t1", &Type1{Name: "type1"}) manager.Set("t2", &Type2{Name: "type2"}) return manager } func TestPrototypeClone(t *testing.T) { manager := setupManager() tests := []struct { name string prototype string expected string typeAssert string // 用于类型断言检查 }{ {"Type1 Clone", "t1", "type1", "Type1"}, {"Type2 Clone", "t2", "type2", "Type2"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { obj := manager.Get(tt.prototype) if obj == nil { t.Fatalf("Get(%s) returned nil", tt.prototype) } // 验证克隆对象不是原对象 original := manager.prototypes[tt.prototype] if obj == original { t.Fatalf("Clone returned the same object as original") } // 类型断言并检查字段 switch tt.typeAssert { case "Type1": casted := obj.(*Type1) if casted.Name != tt.expected { t.Fatalf("expected %s, got %s", tt.expected, casted.Name) } case "Type2": casted := obj.(*Type2) if casted.Name != tt.expected { t.Fatalf("expected %s, got %s", tt.expected, casted.Name) } } }) } } proxy 代理 package test type Subject interface { Do() string } type RealSubject struct{} func (RealSubject) Do() string { return "real" } type Proxy struct { real Subject } func NewProxy(real Subject) Subject { return &Proxy{real: real} } func (p *Proxy) Do() string { res := "pre:" res += p.real.Do() res += ":after" return res } package test import "testing" func TestProxy(t *testing.T) { real := &RealSubject{} sub := NewProxy(real) res := sub.Do() if res != "pre:real:after" { t.Fatalf("expect pre:real:after, got %s", res) } } observer 观察者 package test type Subject struct { observers []Observer context string } func NewSubject() *Subject { return &Subject{ observers: make([]Observer, 0), } } type Observer interface { Update(*Subject) } func (s *Subject) Attach(o Observer) { s.observers = append(s.observers, o) } func (s *Subject) notify() { for _, o := range s.observers { o.Update(s) } } func (s *Subject) UpdateContext(context string) { s.context = context s.notify() } func (s *Subject) Context() string { return s.context } type Reader struct { name string received []string } func NewReader(name string) *Reader { return &Reader{ name: name, received: make([]string, 0), } } func (r *Reader) Update(s *Subject) { r.received = append(r.received, s.Context()) } func (r *Reader) Received() []string { return r.received } func (r *Reader) Name() string { return r.name } package test import "testing" func TestObserver(t *testing.T) { subject := NewSubject() r1 := NewReader("reader1") r2 := NewReader("reader2") r3 := NewReader("reader3") subject.Attach(r1) subject.Attach(r2) subject.Attach(r3) subject.UpdateContext("observer mode") readers := []*Reader{r1, r2, r3} for _, r := range readers { received := r.Received() if len(received) != 1 { t.Fatalf("%s expect 1 update got %d", r.Name(), len(received)) } if received[0] != "observer mode" { t.Fatalf("%s expect observer mode got %s", r.Name(), received[0]) } } }