桥接模式
发布时间 : 2024-09-16 04:06
阅读 :
Bridge Pattern Bridge Pattern说的是,当一个系统中,包含一个组件,该组件是可变的,该系统是可变的。这个时候就需要一个桥连接抽象的系统和抽象的组件。
如果该系统包含多个其他的组件,这些组件都是可变的时候,也需要在该系统和这些组件之间架桥。
如果该系统包含的某个组件所包含的组件,是可变的,那么递归地重复上述过程。
也就是说,在桥接模式中存在两个抽象,这两个抽象之间存在组合关系,为了防止类的数量膨胀,将它们分离出来分别实现,但由于存在包含关系,在上级中包含对下级抽象的引用。
看了很多资料都说的是将抽象与实现进行解耦,通俗地说就是,大系统包含小组件,大系统的某个方法需要依赖小组件的方法,不类型的小组件的实现不一样,但是都能满足大系统的需求,大系统无需关心小组件怎么实现。大系统又分为很多种类,每个种类的大系统都会需要不同的小组件来实现自己的功能,根据需求的变化而变化。
为了应对这种变化,就需要一个抽象类,表示大系统,其中包含了小组件的抽象类或接口,当我们需要开发新的组件的时候,就直接继承小组件,并实现抽象方法就行了。当我们需要开发新的大系统的时候,就继承大系统,实现相应的抽象方法就行了,桥接模式的优点在这里就体现出来了,我们这时候就可以为不同的大系统与小组件之间做自由组合了。
UML
例子 举个例子,这个例子优点复杂,其中还用了Builder Pattern来生成AbstractProgram。
我们设想一下,操作系统和应用程序。操作系统执行应用程序并不需要知道应用程序具体是如何实现的。但是操作系统是由一个个应用程序组成的。
因此,我们先来设计操作系统的接口,并实现它,同时写两个具体的系统:Windows和Linux。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 package bridgeimport ( "fmt" "strings" ) type Registry map [string ]IProgramtype 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) } type Windows struct { Operation } func (this *Windows) Boot() { this.Operation.Boot() this.validSuffix = ".exe" } type Linux struct { Operation } func (this *Linux) Boot() { this.Operation.Boot() this.validSuffix = "*" }
然后我们来设计和实现应用程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 package bridgeimport ( "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 } 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来实现这个工具。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package bridgetype 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 }
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 func main () { windows := new (bridge.Windows) windows.Boot() linux := new (bridge.Linux) linux.Boot() ide := bridge.CodeUtil{} 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" ) }
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件