Bridge
桥接模式是一种结构型模式,它主要应对的是:由于类型的固有罗辑,使得类型具有两个或两个以上的纬度变化。也就是要求抽象不应依赖于实现细节,实现细节应依赖于抽象。
《设计模式》中说到将抽象部分与实现部分分离,使他们可以独立的变化。
举个例子更清楚些,好像我们平时玩的游戏中有
PS
版的,但是不是大家都有
PS
。这时我们等一段时间,一般会出
PC
版的或其他版本。由于支持游戏的平台不一样,但是如果我们编写的游戏程序为了适应另一种平台就要全部重新编写的话岂不是很麻烦。再加上游戏本身的变动,一句众人皆知的话:“死定了
”
。
现在我们来看看
Bridge
桥接模式,看看它是如何解决类似问题的,首先我们看看
Bridge
模式的结构。
实际上,我们要做到的是把变化的部分提出,对其抽象,使变化独立。那我们如何做呢?通过组合的方式将变化独立出去。将一个事物中的多个纬度变化分离。
下面举一个场景来理解一下,还是用汽车举例,我现在要一辆车(
BMW
或
BORA
)在路(
WaterRoad
或
Cement
)上跑。现在有两个纬度的变化点:汽车和路。也就是上图中的
AbstractChangePoint1
和
AbstractChangePoint2
。
AbstractChangePoint1
中包含有
AbstractChangePoint2
对象成员。。代码实现如下:
abstract
class
AbstractCar
{
public
AbstractRoad road;
public AbstractCar(AbstractRoad road)
{
this.road = road;
}
public
abstract
string Run();
public
abstract
string Stop();
}
abstract
class
AbstractRoad
{
public
abstract
string GetRoadType();
}
以汽车为变化中心,用组装的方式将两个变化点结合起来。使路的变化和汽车隔离。下面来编写路的实现。
class
WaterRoad:AbstractRoad
{
public
override
string GetRoadType()
{
return
"It is WaterRoad";
}
}
class
CementRoad:AbstractRoad
{
public
override
string GetRoadType()
{
return
"It is Cement";
}
}
然后再来编写汽车的实现
class
BMWCar:AbstractCar
{
public BMWCar(AbstractRoad road)
: base(road)
{
}
public
override
string Run()
{
return
"BMW is running";
}
public
override
string Stop()
{
return
"BMW is stopped";
}
}
class
BROACar:AbstractCar
{
public BROACar(AbstractRoad road)
: base(road)
{
}
public
override
string Run()
{
return
"BROA is running";
}
public
override
string Stop()
{
return
"BROA is stopped";
}
}
然后我们在客户代码中调用这些类,首先,我想要这个场景是BMW在WaterRoad上跑,客户端代码如下:
static
void
Main(string[] args)
{
AbstractCar car = newBMWCar(newWaterRoad());
Console.WriteLine(car.road.GetRoadType());
Console.WriteLine(car.Run());
Console.WriteLine(car.Stop());
Console.Read();
}
实现结果如下:
It is WaterRoad
BMW is running
BMW is stopped
如果我现在要一辆BORA在Cement上跑,我们只要稍微修改一下car的实例化就可以,代码如下:
static
void
Main(string[] args)
{
AbstractCar car = newBROACar(newCementRoad());
Console.WriteLine(car.road.GetRoadType());
Console.WriteLine(car.Run());
Console.WriteLine(car.Stop());
Console.Read();
}
实现结果如下:
It is Cement
BROA is running
BROA is stopped
最后我们再来说说
Bridge
模式的要点:
1
、
Bridge
模式使用“对象间的组合关系”解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的纬度来变化。
2
、所谓抽象和实现沿着各自纬度的变化,即“子类化”它们,得到各个子类之后,便可以任意组合它们。
3
、
Bridge
模式有时候类似于多继承方案,但是多继承方案往往违背单一职责原则(即一个类只有一个变化的原因),复用性比较差。
Bridge
模式是比多继承方案更好的解决方法。
4
、
Bridge
模式的应用一般在“两个非常强的变化纬度”,有时候即使有两个变化的纬度,但是某个方向的变化纬度并不剧烈——换言之两个变化不会导致纵横交错的结果,并不一定要使用
Bridge
模式。