Golang与设计模式-Adapter适配器模式

适配器模式是我们在工作中会经常使用到的结构性设计模式。比如对接口升级的同时,又要保证对旧借口的兼容。

场景

生活中我们会遇到这种情况,我们常用的插线板三插孔(10A)与空调插头(16A)的大小不一样,虽然都是三插孔。当我们买了空调,安装时发现空调插头并不能插入我们原有(10A)的插孔时,我们可以买一个插头转换器,如下图。

 我们可以把10A的反面插头插入我们正常的10A三插孔,再将空调的插头插入正面的16A三插孔即可。这里,我们的插头转换器扮演的就是 适配器(Adapter)的角色。

接下来我会以这个插头转换器应用为例,以代码的形式表达适配器模式。虽然演示代码很多,但是却很有代表性,请认真阅读哦

基础接口

这里我们先定义三个接口

电器设备(Appliances)接口

定义了一个返回电器名称的方法GetName(),所有家用电器都需要实现这个接口

// 电器设备接口
type Appliances interface {
	GetName() string
}

10A插头的电器设备(Appliances10A)接口 

组合(Golang没有继承的概念)Appliances接口,并定义了一个方法Plug10A(),用来实现该接口,所有10A插头的电器都需要实现这个接口

// 10A插头电器接口,所有10A插头的电器设备都要实现该接口
type Appliances10A interface {
	// 组合电器设备接口
	Appliances
	// 插头是10A的,实现该接口
	Plug10A()
}

16A插头的电器设备(Appliances16A)接口

跟 Appliances10A基本一样,组合Appliances接口,并定义了实现该接口的方法Plug16A(),所有16A插头的电器都需要实现这个接口

// 16A插头电器接口,所有16A插头的电器设备都要实现该接口
type Appliances16A interface {
	Appliances
	// 插头是16A的,实现该接口
	Plug16A()
}

电器设备的实现

10A插头的电器-电视机(TV)

TV是一个10A插头的电器设备,所以TV类型需要实现Appliances的GetName()方法,以及Plug10A()方法

// 电视机
type TV struct {
	// 电器名称,比如: 空调,电视,冰箱
	Name string
}

func (tv *TV) GetName() string {
	return tv.Name
}

// 电视机是10A的插头
func (tv *TV) Plug10A() {}

16A插头的电器-空调(HVAC)

HVAC是一个16A插头的电器设备,所以也实现Appliances的GetName()方法和 Plug16A()方法

// 空调
type HVAC struct {
	Name string
}

func (hvac *HVAC) GetName() string {
	return hvac.Name
}

// 空调是16A的插头
func (hvac *HVAC) Plug16A() {}

基础设施

标准10A插孔的插线板(PlugBoard)

因为是10A的插孔,所以定义了一个插入 10A插头电器的方法Insert10A(),入参必须是一个 10A插头的电器类型,

// 插线板(10A)
type PlugBoard struct {
	// 电器集合
	Appliances []Appliances
}

// 插入 10A插头的电器设备
func (p *PlugBoard) Insert10A(app Appliances10A) {
	p.Appliances = append(p.Appliances, app)
}

// 插线板通电,那么在插线板上的电器都通上电了
func (p *PlugBoard) TransferCurrent() {
	for _, app := range p.Appliances {
		fmt.Printf("%s 已通电 \n", app.GetName())
	}
}

适配器(Adapter)

Adapter是可以被认为是一个 10A插头的电器设备,所以实现了 Plug10A(),但因为是个转换器,背面还有一个16A的插孔,所以定了一个插入 16A插头电器的方法

// 适配器
type Adapter struct {
	// 正面(10A)插入的插线板
	PB PlugBoard
	// 反面(16A)接入的电器设备
	APP Appliances16A
}
// 适配器能够插入插线板,且能通电,所以本身也是一个电器设备
func (a *Adapter) GetName() string{
	return a.APP.GetName()
}

// 正面是 10A的插头
func (a *Adapter) Plug10A() {}

// 背面有 16A的插孔,所以可以插入一个16A插头的设备
func (a *Adapter) Insert16A(app Appliances16A) {
	a.APP = app
	a.PB.Insert10A(a)
}

测试

func main() {
	// 电视机
	tv := TV{Name: "电视机"}
	// 空调
	hvac := HVAC{Name: "空调"}
	//插线板
	pb := PlugBoard{}

	// 插线板上插入 电视机插头
	pb.Insert10A(&tv)

	// 适配器
	adapter := Adapter{}

	//插线板上插入 适配器插头
	pb.Insert10A(&adapter)

	// 适配器上插入 空调插头
	adapter.Insert16A(&hvac)

	// 给插线板通电
	pb.TransferCurrent()
}

运行结果

代码已上传Github:LyonNee/design_patterns_with_go: 基于Golang实现的设计模式代码 (github.com)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是几种常见的Golang设计模式: 1. 工厂模式(Factory Pattern):用于创建对象的模式,通过定义一个创建对象的接口来实现对象的实例化。 ```go type Shape interface { Draw() } type Circle struct{} func (c *Circle) Draw() { fmt.Println("Drawing a circle") } type Rectangle struct{} func (r *Rectangle) Draw() { fmt.Println("Drawing a rectangle") } type ShapeFactory struct{} func (sf *ShapeFactory) GetShape(shapeType string) Shape { if shapeType == "circle" { return &Circle{} } else if shapeType == "rectangle" { return &Rectangle{} } return nil } func main() { factory := &ShapeFactory{} circle := factory.GetShape("circle") circle.Draw() // 输出:Drawing a circle rectangle := factory.GetShape("rectangle") rectangle.Draw() // 输出:Drawing a rectangle } ``` 2. 单例模式(Singleton Pattern):确保一个类只有一个实例,并提供一个全局访问点。 ```go type Singleton struct{} var instance *Singleton func GetInstance() *Singleton { if instance == nil { instance = &Singleton{} } return instance } func main() { singleton1 := GetInstance() singleton2 := GetInstance() fmt.Println(singleton1 == singleton2) // 输出:true } ``` 3. 观察者模式(Observer Pattern):定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。 ```go type Subject struct { observers []Observer } func (s *Subject) Attach(observer Observer) { s.observers = append(s.observers, observer) } func (s *Subject) Notify() { for _, observer := range s.observers { observer.Update() } } type Observer interface { Update() } type ConcreteObserver struct{} func (co *ConcreteObserver) Update() { fmt.Println("Observer is updated") } func main() { subject := &Subject{} observer := &ConcreteObserver{} subject.Attach(observer) subject.Notify() // 输出:Observer is updated } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值