桥接模式意图
桥接模式将抽象部分与它的实现部分分离,使它们可以独立变化。
适用性
以下情况适合使用桥接模式:
.不希望在抽象和它的实现部分之间有一个固定的绑定关系。比如这种情况可能是因为在程序运行时刻实现部分应可以被选择或者切换。
.类的抽象以及它的实现应该可以通过生成子类的方法加以扩充。
.对一个抽象的实现部分的修改应对客户不产生影响,即客户的代码不必重新编译。
.一个类型存在两个独立变化的维度,且这两个维度都需要进行扩展。
结构
参与者
.abstractioin
–定义抽象类的接口
–维护一个指向Implementor类型对象的指针
.RefinedAbstraction
–扩充由abstraction定义的接口
.Implementor
–定义实现类的接口,该接口不一定要与abstraction的接口完全一致;事实上这两个接口也可以完全不同。一般来讲,implementor接口仅提供基本操作,而abstraction定义了基于这些操作的较高层次的操作。
.ConcreteImplementor
实现Implementor接口并定义它的具体实现。
桥接模式的作用
桥接模式有以下优点:
1)分离接口及其实现部分:一个实现未必不变地绑定在一个接口上,抽象类的实现可在运行时刻进行配置,一个对象甚至可以在运行时刻改变它的实现。将abstraction与Implementor分离有助于降低对实现部分编译时刻的依赖性,当改变一个实现类时,不需要重新编译abstraction类和客户重新。为了保证一个类库的不同版本之间二进制兼容性,一定要有这个性质。另外,接口和实现分离有助于分层,从而产生更好的结构化系统,系统的高层部分只要知道abstraction和implementor即可。
2)提高可扩展性,可以独立对Abstraction和Implementor层次进行扩展。
3)实现细节对可对客户透明。
缺点:
不容易设计,需不需要分离,如何分离等问题。比较难以拿捏。
实现
package main
import (
"fmt"
)
type Company interface {
Runing()
}
type BigCompany struct {
Worker
}
func (pB *BigCompany) Running() {
fmt.Println("员工都是螺丝钉")
pB.Worker.Leaving()
fmt.Println("员工跑路后随时可以找人顶替")
}
type SmallCompany struct {
Worker
}
func (pS *SmallCompany) Running() {
fmt.Println("随便一个员工都是骨干")
pS.Worker.Leaving()
fmt.Println("员工跑路后,公司运转受阻")
}
type Worker interface {
Leaving()
}
type GoodWorker struct {
}
func (pG *GoodWorker) Leaving() {
fmt.Println("好员工跑路后")
}
type NormalWorker struct {
}
func (pN *NormalWorker) Leaving() {
fmt.Println("普通员工跑路后")
}
func main() {
pgoodworker := &GoodWorker{}
pnormalworker := &NormalWorker{}
pbigCompany := &BigCompany{Worker: pgoodworker}
pbigCompany.Running()
pbigCompany2 := &BigCompany{Worker: pnormalworker}
pbigCompany2.Running()
psmallCompany := &SmallCompany{Worker: pgoodworker}
psmallCompany.Running()
psmallCompany2 := &SmallCompany{Worker: pnormalworker}
psmallCompany2.Running()
return
}
运行结果:
员工都是螺丝钉
好员工跑路后
员工跑路后随时可以找人顶替
员工都是螺丝钉
普通员工跑路后
员工跑路后随时可以找人顶替
随便一个员工都是骨干
好员工跑路后
员工跑路后,公司运转受阻
随便一个员工都是骨干
普通员工跑路后
员工跑路后,公司运转受阻