【博客390】设计模式之:桥接模式

内容:记录桥接模式的学习

桥接模式:

桥接是用于把抽象化与实现化解偶,使得二者可以独立变化。这种类型的设计模式属于结构型模式,
它通过提供抽象化和实现化之间的桥接结构,来实现二者的解偶。

这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变
而互不影响。


意图:将抽象部分与实现部分分离,使他们都可以独立的变化。

主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。

何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。

如何解决:把这种多角度分类分离出来,让他们独立变化,减少他们之间的耦合。

关键代码:抽象类依赖实现类。

优点:抽象和实现的分离、优秀的扩展能力、实现细节与客户透明

缺点:桥接模式的引用会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,
      要求开发者针对抽象进行设计与编程。

使用场景:作用于两个独立变化的纬度
 
举例:
电器是一个抽象类(灯泡和风扇是它的具体实现类)
开关是另一个抽象类(圆形开关和方形开关是它的具体实现类)

这两个抽象类通过桥接的形式连接在一起(线路),在这种情况下,我们可以替换抽象类中的任意一个而让
整体系统不受到影响。

一个使用桥接与不使用桥接的例子:

在现实生活中,我们画画的时候常常会用到两种或多种类型的笔,比如毛笔和蜡笔。

假设我们需要大、中、小三种类型的画笔来绘制12种不同的颜色:

不使用桥接模式:
相当于我们使用蜡笔,那么我们需要准备3*12=36支蜡笔;

使用桥接模式:
相当于我们使用毛笔,那么我们只需要3种型号的毛笔,外加12个颜料盒即可,涉及的对象个数仅为3+12=15。

差异:
如果新增一种画笔,并且同样需要12种颜色,那么蜡笔需要增加12支,而毛笔却只需要新增1支。

分析:
在蜡笔中,颜色和型号两个不同的变化维度耦合在一起,导致无论对任何一个维度进行扩展,都势必会影响
另外一个维度
在毛笔中,颜色和型号实现了分离,增加新的颜色或者型号都对另外一个维度没有任何影响

通用结构示意图:
在这里插入图片描述
上述画笔例子示意图:
在这里插入图片描述
桥接模式中的概念:

Abstraction(抽象类,图中的BrushPen接口):
用于定义抽象类的接口,它与Implementor之间具有关联关系,它既可以包含抽象业务方法,
也可以包含具体业务方法。

RefinedAbstratction(扩充抽象类,图中的BigBrushPen和SmallBrushPen):
扩充由Abstraction定义的接口,通常情况下他不再是抽象类而是具体类,实现了在Abstraction
中声明的抽象业务方法,在RefinedAbstraction中可以调用在Implementor中定义的业务方法。

Implementor(实现类接口,图中的Color接口):
定义实现类的接口,一般而言,它不与Abstraction的接口一致。它只提供基本操作,而Abstraction
定义的接口可能会做更多更复杂的操作。

ConcreteImplementor(具体实现类,图中的Red、Green、Yellow):
具体实现Implementor接口,在不同的ConcreteImplementor中提供基本操作的不同实现,在程序运行时,
ConcreteImplentor将替换其父类对象,提供给抽象类具体的业务操作方法。

上述画笔例子的桥接模式示例:

## 定义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")
}

## 定义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()
}

## 定义工厂方法生产具体的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
	}
}

## 使用
func main() {
	var tColor bridge.Color
	tColor = bridge.Red{}
	tBrushPen := bridge.NewBrushPen("BIG", tColor)
	tBrushPen.DrawPicture()

	tColor = bridge.Green{}
	tBrushPen = bridge.NewBrushPen("SMALL", tColor)
	tBrushPen.DrawPicture()
	
	tColor = bridge.Yellow{}
	tBrushPen = bridge.NewBrushPen("BIG", tColor)
	tBrushPen.DrawPicture()
}

桥接模式和适配器模式:

桥接模式和适配器模式的区别:


共同点:
桥接和适配器都是让两个模块配合工作 

不同点:  
适配器:改变已有的两个接口,使之相互兼容
桥接模式:分离抽象化和实现,使两者的接口可以不同,目的是分离。  

如何选择:
如果你拿到两个已有模块,想让他们同时工作,那么你使用的适配器。 
如果你还什么都没有,但是想分开实现,那么桥接是一个选择。  

依赖的先后顺序:
桥接是先有桥,才有两端的东西 适配是先有两边的东西,才有适配器 。
桥接是在桥好了之后,两边的东西还可以变化。 

作用的先后顺序:
适配器模式是当发现以前的东西不适用了才去做一个弥补的措施。
桥模式相对来说所做的改变比适配器模式早,它可以适用于有两个甚至两个以上维度的变化。

总结:

1.Bridgen模式使用“对象间的组合关系”解耦了抽象与现实之间固有的绑定关系,使得抽象和实现
可以沿着各自的维度来变化。

2.Bridge模式的应用一般在“两个非常强的变化维度”,有时候即使有两个变化的维度,但是某个方向
的变化维度并不剧烈-换而言之两个变化不会导致纵横交错的结果,并不一定要使用Bridge模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值