设计模式之——桥接(Bridge)和策略(strategy)

时间:2022-12-11 21:57:36

之所以把这两个放在一起,是因为他们很相似,但又是完全不同的


先来看看Bridge模式

1)如果客户给了一个需求,故我们实现了类A

2)过了几天客户说这个东东需要有两种算法,故我们派生出 A0, A1

3)然后又过了几天,客户又提出要求说要在不同的操作系统下实现,故我们派生出类A0a, A0b, A1a, A1b

这样我们需要不停的派生,不停的改


Bridge模式就是解决这个问题的, 对象和行为都要不停的改变, 把对象和行为类分开,单独演进,在对象类中包含行为类的变量,这样就可以随意组合,其类图关系如下

设计模式之——桥接(Bridge)和策略(strategy)

其中,Abstraction和 AbstractionImp分别是类和行为的抽象接口,即基类。Bridge用组合而不是继续的方式来处理问题,这是符合面向对象的思想的,能有组合的尽量不用继承,这样使得代码更灵活。

有一篇文章对Bridge讲得特别好,http://www.blogjava.net/lijiajia418/archive/2006/09/18/70268.html


另外说点Bridge和visitor的相似和不同点:

我刚开始看的时候觉得两个模式几乎就是一样的,都是把元素和行为进行分离,然后可以独立演变和组合。但其实他们还是有很大的不同的

1)对于Bridge模式,Abstraction里面要包含AbstractionImp的指针;而对于Visitor而言,Element并不包含Visitor的指针。从这一点上看,Bridge描述的元素和行为的内聚性更高。

2)Bridge的结构使得类的行为与类相对独立,而Visitor则是使得类的某个行为的不同实现之间可以相互独立,并且vistor的行为并不一定属于其处理的对象所应有的行为。Bridge是要解决抽象类与自身行为实现的分离,Vistor要解决的是将对抽象类与其各种外在访问行为的分离。

3) Visitor虽然也有元素和行为分离的思想在里面,但这个模式最重要的是双派发机制,可以用类似emp->accpt(pvisitor)的统一接口来实现双重派发,那么这样就可以把代码写得很简单,特别是在循环里面,没有很多的条件判断,这也是它最大的用处,但是这是建立在元素类稳定,不需要增加的情况下的,如果具体的元素类不稳定,要经常增加,那么所有的具体visitor类都要修改,是不符合OCP的;而Bridge模式的应用场景根本不是这样的,它要解决的元素和行为可以单独演变



我们再来看Strategy模式

其定义也很简单,定义算法簇,分别封装起来,让他们可以动态的相互替换,使用户可以使用不同的算法来实现。它的类图和Bridge非常类似

设计模式之——桥接(Bridge)和策略(strategy)

同样,Context也会包含一个指向Strategy对象的指针,使得Context可以使用不同的策略算法,甚至Context也可以有子类,使得类图和Bridge完全一样。



实际上所有模式可以只分为类模式和对象模式两种,类模式是用继承而对象模式是用委托 ,Bridge模式和Strategy模式相似就是因为他们都将任务委托给了另外一个接口的具体实现。

现在看看他们的区别,搞清楚了区别,也就真正的搞清了这两个设计模式,参考了网上一些比较经典的说明:

一,在形式上,两者还是有一定区别的,对比两幅结构图,我们可以发现,在桥接模式中不仅行为具有变化 ,而且Abstraction也可以发生变化,而且两者的变化是完全独立的,它们仅仅通过Abstraction与 Implementor之间的关系联系起来。而在策略模式中,并不考虑Context的变化,只有算法的可替代性,当然我们说过,其实Context也是可以子类的,这样他们再类图上就是一样的了,但是对于Strategy而言,Context的变化并不是它关心的重点。

二,它们最重要的区别就在于Strategy里面红色的几个词,Strategy主要是封装了算法,使得算法可以动态替换,也就是说,Context中指向Strategy对象的指针的值是可以动态设定的,一般会有一个方法SetStrategy类似的方法在Context里面,所以它是一个行为模式,描述的是行为的变化;而Bridge模式中,指向行为是指针是不能改变的,它主要是要表达一个系统中的元素和行为可以单独变化,随意的组合,但一旦组合上之后是不变的,更多的是描述系统的结构,所以是一种结构模式。 很多模式的实现上都很相似,但它们的应用场景是不一样的,这才是设计模式最重要的内容,模式只是一个实现工具而已。