在现实生活中,我们画画的时候常常会用到两种或多种类型的笔,比如毛笔和蜡笔。假设我们需要大、中、小三种类型的画笔来绘制12种不同的颜色,如果我们使用蜡笔,那么我们需要准备3*12=36支蜡笔;但是如果我们使用毛笔的话,只需要3种型号的毛笔,外加12个颜料盒即可,涉及的对象个数仅为3+12=15。如果新增一种画笔,并且同样需要12种颜色,那么蜡笔需要增加12支,而毛笔却只需要新增1支。
我们来分析一下以上场景:
- 在蜡笔中,颜色和型号两个不同的变化维度耦合在一起,导致无论对任何一个维度进行扩展,都势必会影响另外一个维度
- 在毛笔中,颜色和型号实现了分离,增加新的颜色或者型号都对另外一个维度没有任何影响
1 模式定义
如果软件系统中某个类存在两个独立变化的维度,通过该模式可以将这两个维度分离出来,使两者可以独立扩展,让系统更加符合单一职责原则。桥接模式主要使用抽象关联取代传统的多重继承,将类之间的静态继承关系转换为动态的对象组合关系 ,使得系统更加灵活,并易于扩展,同时有效控制了系统中类的个数。
桥接模式(Bridge),将抽象部分与它的实现部分分离,使它们都可以独立的变化
概念不是很好理解,读者可以这样理解:
实现系统可能有多个维度分类(比如以上的颜色和型号),每一种维度都有可能变化(比如颜色有12种变化,型号有3种变化),那么就吧这种多维度分离出来让它们独立变化,减少它们之间的耦合 。
桥接模式很好的利用了合成-聚合复用原则 ,其实我们在设计软件结构的时候应该优先使用这一原则,而不是类继承。类继承一定要在‘is-a’的关系时考虑使用 ,而不是任何时候去使用。
桥接模式中有4个概念:
- Abstraction(抽象类,图中的BrushPen接口):用于定义抽象类的接口,它与Implementor之间具有关联关系,它既可以包含抽象业务方法, 也可以包含具体业务方法。
- RefinedAbstratction(扩充抽象类,图中的BigBrushPen和SmallBrushPen):扩充由Abstraction定义的接口,通常情况下他不再是抽象类而是具体类,实现了在Abstraction中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。
- Implementor(实现类接口,图中的Color接口):定义实现类的接口,一般而言,它不与Abstraction的接口一致。它只提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。
- ConcreteImplementor(具体实现类,图中的Red、Green、Yellow):具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,ConcreteImplentor将替换其父类对象,提供给抽象类具体的业务操作方法。
2 go语言实现
2.1 定义Implementor接口及实现
type Color interface {
Use()
}
type Red struct{}
func (r Red) Use() {
fmt.Println("Use Red color")
}
type Green struct{}
func (g Green) Use() {
fmt.Println("Use Green color")
}
type Yellow struct{}
func (y Yellow) Use() {
fmt.Println("Use Yellow color")
}
2.2 定义Abstraction及实现
type BrushPen interface {
DrawPicture()
}
type BigBrushPen struct {
Color
}
func (bbp BigBrushPen) DrawPicture() {
fmt.Println("Draw picture with big brush pen")
bbp.Use()
}
type SmallBrushPen struct {
Color
}
func (sbp SmallBrushPen) DrawPicture() {
fmt.Println("Draw picture with small brush pen")
sbp.Use()
}
2.3 定义工厂方法生产具体的BrushPen
func NewBrushPen(t string, color Color) BrushPen {
switch t {
case "BIG":
return BigBrushPen{
Color: color,
}
case "SMALL":
return SmallBrushPen{
Color: color,
}
default:
return nil
}
}
2.4 测试demo
func main() {
var tColor bridge.Color
tColor = bridge.Red{}
tBrushPen := bridge.NewBrushPen("BIG", tColor)
tBrushPen.DrawPicture()
fmt.Println("=========================")
tColor = bridge.Green{}
tBrushPen = bridge.NewBrushPen("SMALL", tColor)
tBrushPen.DrawPicture()
fmt.Println("=========================")
tColor = bridge.Yellow{}
tBrushPen = bridge.NewBrushPen("BIG", tColor)
tBrushPen.DrawPicture()
}
|
请发表评论