【寒江雪】Go实现桥接模式

Bridge Pattern

  Bridge Pattern说的是,当一个系统中,包含一个组件,该组件是可变的,该系统是可变的。这个时候就需要一个桥连接抽象的系统和抽象的组件。

  如果该系统包含多个其他的组件,这些组件都是可变的时候,也需要在该系统和这些组件之间架桥。

  如果该系统包含的某个组件所包含的组件,是可变的,那么递归地重复上述过程。

  也就是说,在桥接模式中存在两个抽象,这两个抽象之间存在组合关系,为了防止类的数量膨胀,将它们分离出来分别实现,但由于存在包含关系,在上级中包含对下级抽象的引用。

  看了很多资料都说的是将抽象与实现进行解耦,通俗地说就是,大系统包含小组件,大系统的某个方法需要依赖小组件的方法,不类型的小组件的实现不一样,但是都能满足大系统的需求,大系统无需关心小组件怎么实现。大系统又分为很多种类,每个种类的大系统都会需要不同的小组件来实现自己的功能,根据需求的变化而变化。

  为了应对这种变化,就需要一个抽象类,表示大系统,其中包含了小组件的抽象类或接口,当我们需要开发新的组件的时候,就直接继承小组件,并实现抽象方法就行了。当我们需要开发新的大系统的时候,就继承大系统,实现相应的抽象方法就行了,桥接模式的优点在这里就体现出来了,我们这时候就可以为不同的大系统与小组件之间做自由组合了。

UML

例子

  举个例子,这个例子优点复杂,其中还用了Builder Pattern来生成AbstractProgram。

  我们设想一下,操作系统和应用程序。操作系统执行应用程序并不需要知道应用程序具体是如何实现的。但是操作系统是由一个个应用程序组成的。

  因此,我们先来设计操作系统的接口,并实现它,同时写两个具体的系统:Windows和Linux。

package bridge

import (
	"fmt"
	"strings"
)

// 命令行和应用程序的映射表
type Registry map[string]IProgram

// 操作系统的通用接口
type IOperation interface {
	Boot()
	ExecuteProgram(cmd string)
	SetupProgram(cmd string, program IProgram)
	Build(program *IProgram)
}

// 抽象的操作系统
type Operation struct {
	reg         Registry
	validSuffix string
}

// 启动
func (this *Operation)Boot(){
	this.reg = make(Registry)
}

// 执行
func (this *Operation) ExecuteProgram(cmd string) {
	program, ok := this.reg[cmd]
	if ok {
		program.Run()
	} else {
		fmt.Println(cmd + " is invalid.")
	}
}

// 安装
func (this *Operation) SetupProgram(cmd string, program IProgram) {
	switch this.validSuffix {
	case "*":
		this.reg[cmd] = program
	default:
		name := program.GetName()
		if strings.HasSuffix(name, this.validSuffix) {
			this.reg[cmd] = program
		} else {
			fmt.Println("Invalid suffix.")
		}
	}
}

// 构建
func (this *Operation) Build(program IProgram){
	cmd := program.CMD()
	if this.validSuffix!="*"{
		program.SetSuffix(this.validSuffix)
	}
	this.SetupProgram(cmd,program)
}

// Windows
type Windows struct {
	Operation
}

// Windows 的启动过程
func (this *Windows) Boot() {
	this.Operation.Boot()
	this.validSuffix = ".exe"
}

// Linux
type Linux struct {
	Operation
}

//	Linux的启动过程
func (this *Linux) Boot() {
	this.Operation.Boot()
	this.validSuffix = "*"
}

  然后我们来设计和实现应用程序

package bridge

import (
	"fmt"
)

//	程序通用接口
type IProgram interface{
	GetName()string
	SetSuffix(suffix string)
	CMD()string
	Run()
}

//	程序的抽象
type AbstractProgram struct{
	Name string
	Cmd string
}

//	获取程序名字
func (this *AbstractProgram)GetName()string{
	return this.Name
}

//	获取程序命令行
func (this *AbstractProgram)CMD()string{
	return this.Cmd
}

//	设置程序后缀名
func (this *AbstractProgram)SetSuffix(suffix string){
	this.Name+=suffix
}

//	执行程序
//	AbstractProgram并不具体实现
//	为了让AbstractProgram看起来实现了IProgram接口
//	如果不写这段就需要子结构强制实现Run接口
func (this *AbstractProgram)Run(){

}

type Sing struct{
	AbstractProgram
	Word string
}

func (this *Sing)Run(){
	fmt.Println("I want to sing:"+this.Word)
}


type Dog struct{
	AbstractProgram
}

func (this *Dog)Run(){
	fmt.Println("Wang!")
}

  最后,多余的一步,希望更逼近现实情况,我们需要构建应用程序,就需要一些工具了,这里使用了Builder Pattern来实现这个工具。

package bridge

type ICoding interface {
	WriteName(string) ICoding
	WriteCmd(string) ICoding
	Compile() AbstractProgram
}

type CodeUtil struct {
	code AbstractProgram
}

func (this CodeUtil) WriteName(name string) ICoding {
	this.code.Name = name
	return this
}

func (this CodeUtil) WriteCmd(cmd string) ICoding {
	this.code.Cmd = cmd
	return this
}

func (this CodeUtil) Compile() AbstractProgram {
	res := AbstractProgram{Name: this.code.Name, Cmd: this.code.Cmd}
	return res
}

func (this CodeUtil) GetSingProgram(word string) Sing {
	res := Sing{}
	res.AbstractProgram = this.WriteName("sing").WriteCmd("sing").Compile()
	res.Word = word
	return res
}

func (this CodeUtil) GetDogProgram() Dog {
	res := Dog{}
	res.AbstractProgram = this.WriteName("dog").WriteCmd("dog").Compile()
	return res
}

使用

func main(){
	// craete windows
	windows := new(bridge.Windows)
	windows.Boot()

	// create linux
	linux := new(bridge.Linux)
	linux.Boot()

	// Code util
	ide := bridge.CodeUtil{}

	// write programs
	sing := ide.GetSingProgram("Hello World")
	dog := ide.GetDogProgram()

	windows.Build(&sing)
	windows.Build(&dog)
	linux.Build(&sing)
	linux.Build(&dog)

	windows.ExecuteProgram("dog")
	windows.ExecuteProgram("sing")
	linux.ExecuteProgram("sing")
	linux.ExecuteProgram("dog")
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值