golang适配器模式

适配器模式用于转换一种接口适配另一种接口。

实际使用中Adaptee一般为接口,并且使用工厂函数生成实例。

在Adapter中匿名组合Adaptee接口,所以Adapter类也拥有SpecificRequest实例方法,又因为Go语言中非入侵式接口特征,其实Adapter也适配Adaptee接口。

adapter.go

package adapter

//Target 是适配的目标接口
type Target interface {
    Request() string
}

//Adaptee 是被适配的目标接口
type Adaptee interface {
    SpecificRequest() string
}

//NewAdaptee 是被适配接口的工厂函数
func NewAdaptee() Adaptee {
    return &adapteeImpl{}
}

//AdapteeImpl 是被适配的目标类
type adapteeImpl struct{}

//SpecificRequest 是目标类的一个方法
func (*adapteeImpl) SpecificRequest() string {
    return "adaptee method"
}

//NewAdapter 是Adapter的工厂函数
func NewAdapter(adaptee Adaptee) Target {
    return &adapter{
        Adaptee: adaptee,
    }
}

//Adapter 是转换Adaptee为Target接口的适配器
type adapter struct {
    Adaptee
}

//Request 实现Target接口
func (a *adapter) Request() string {
    return a.SpecificRequest()
}

adapter_test.go

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, actual: %s", expect, res)
    }
}
### Golang 设计模式的实现与应用 #### 1. **单例模式 (Singleton)** 单例模式确保某个类只有一个实例,并提供全局访问点。在 Go 中可以通过使用 `sync.Once` 来安全地初始化唯一实例[^2]。 ```go package main import ( "sync" ) type Singleton struct{} var instance *Singleton var once sync.Once func GetInstance() *Singleton { once.Do(func() { instance = &Singleton{} }) return instance } ``` --- #### 2. **工厂模式 (Factory)** 工厂模式将对象的创建逻辑集中在一个地方,符合单一职责原则和开闭原则。Go 的工厂模式通常通过函数返回不同类型的接口实例来实现[^4]。 ```go // 定义产品接口 type Product interface { Use() } // 具体产品A type ConcreteProductA struct{} func (p *ConcreteProductA) Use() { println("Using Product A") } // 具体产品B type ConcreteProductB struct{} func (p *ConcreteProductB) Use() { println("Using Product B") } // 工厂函数 func CreateProduct(productType string) Product { if productType == "A" { return new(ConcreteProductA) } else if productType == "B" { return new(ConcreteProductB) } return nil } ``` --- #### 3. **观察者模式 (Observer)** 观察者模式定义了一种一对多的关系,当一个对象状态改变时通知依赖它的其他对象自动更新。Go 可以通过通道和回调函数轻松实现该模式[^2]。 ```go package main import "fmt" type Subject struct { observers []chan int state int } func NewSubject() *Subject { return &Subject{ observers: make([]chan int, 0), } } func (s *Subject) Attach(observer chan<- int) { s.observers = append(s.observers, observer) } func (s *Subject) Notify() { for _, obs := range s.observers { obs <- s.state } } func (s *Subject) SetState(state int) { s.state = state s.Notify() } func main() { subject := NewSubject() observer1 := make(chan int) go func() { for v := range observer1 { fmt.Println("Observer1 received:", v) } }() observer2 := make(chan int) go func() { for v := range observer2 { fmt.Println("Observer2 received:", v) } }() subject.Attach(observer1) subject.Attach(observer2) subject.SetState(10) subject.SetState(20) close(observer1) close(observer2) } ``` --- #### 4. **策略模式 (Strategy)** 策略模式允许动态替换算法或行为。Go 中可以通过接口实现不同的策略并灵活切换。 ```go package main import "fmt" type Strategy interface { Execute(int, int) int } type AddStrategy struct{} func (*AddStrategy) Execute(a, b int) int { return a + b } type SubtractStrategy struct{} func (*SubtractStrategy) Execute(a, b int) int { return a - b } type Context struct { strategy Strategy } func (c *Context) SetStrategy(s Strategy) { c.strategy = s } func (c *Context) ExecuteStrategy(a, b int) int { return c.strategy.Execute(a, b) } func main() { context := &Context{} addStrategy := &AddStrategy{} context.SetStrategy(addStrategy) fmt.Println(context.ExecuteStrategy(5, 3)) // Output: 8 subtractStrategy := &SubtractStrategy{} context.SetStrategy(subtractStrategy) fmt.Println(context.ExecuteStrategy(5, 3)) // Output: 2 } ``` --- #### 5. **适配器模式 (Adapter)** 适配器模式让两个原本不兼容的接口能够协同工作。Go 中可以通过组合现有类型的方式实现适配器[^5]。 ```go package main import "fmt" // Target 接口 type MediaPlayer interface { Play(format, file string) } // Adaptee 类 type AdvancedMediaPlayer struct{} func (a *AdvancedMediaPlayer) PlayVlc(file string) { fmt.Printf("Playing VLC file %s\n", file) } func (a *AdvancedMediaPlayer) PlayMp4(file string) { fmt.Printf("Playing MP4 file %s\n", file) } // Adapter 类 type MediaAdapter struct { player *AdvancedMediaPlayer } func (m *MediaAdapter) Play(format, file string) { switch format { case "vlc": m.player.PlayVlc(file) case "mp4": m.player.PlayMp4(file) default: fmt.Println("Unsupported Format!") } } func main() { mediaPlayer := &MediaAdapter{player: &AdvancedMediaPlayer{}} mediaPlayer.Play("vlc", "example.vlc") // Playing VLC file example.vlc mediaPlayer.Play("mp4", "example.mp4") // Playing MP4 file example.mp4 } ``` --- #### 6. **模板方法模式 (Template Method)** 模板方法模式定义了一个操作的一般步骤,允许子类重写某些具体步骤而不影响整体结构。Go 中可通过嵌入匿名字段实现继承效果[^3]。 ```go package main import "fmt" type TemplateMethod struct {} func (t *TemplateMethod) TemplateFunction() { t.StepOne() t.StepTwo() } func (t *TemplateMethod) StepOne() { fmt.Println("Default implementation of step one.") } func (t *TemplateMethod) StepTwo() { fmt.Println("Default implementation of step two.") } type CustomImplementation struct { TemplateMethod } func (c *CustomImplementation) StepOne() { fmt.Println("Customized implementation of step one.") } func main() { template := &TemplateMethod{} template.TemplateFunction() custom := &CustomImplementation{} custom.TemplateFunction() } ``` --- #### 总结 以上展示了几种常见的设计模式及其在 Golang 中的应用方式。每种模式都有其适用场景以及优缺点,在实际开发中应根据需求合理选用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值