桥接模式(Simple Factory Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。
定义解读:桥接模式的核心是两个抽象以组合的形式关联到一起,从而他们的实现就互不依赖了。
如果一个系统存在两个独立变化的维度,而且这两个维度都需要进行扩展的时候比较适合使用桥接模式。
下面来看一下桥接模式的成员和类图。
桥接模式一共只有三个成员:
下面通过类图来看一下各个成员之间的关系:
桥接模式类图
从类图中可以看出
Abstraction
持有Implementor
,但是二者的实现类互不依赖,这就是桥接模式的核心。
创建一些不同的形状,这些形状带有不同的颜色:
三种形状:
三种颜色:
根据上述需求,可能有的朋友会这么设计:
这样的设计确实可以实现上面的需求。但是设想一下,如果后来增加了一种颜色或者形状的话,是不是要多出来很多类?如果形状的种类数是m
,颜色的种类数是n
,以这种方式创建的总类数就是 m*n
,当m或n非常大的时候,它们相乘的结果就会变得很大。
我们观察一下这个场景:形状和颜色这二者的是没有关联性的,二者可以独立扩展和变化,这样的组合比较适合用桥接模式来做。
根据上面提到的桥接模式的成员:
下面我们用代码看一下该如何设计。
首先我们创建形状的基类Shape
:
//================== Shape.h ==================
@interface Shape : NSObject
{
@protected Color *_color;
}
- (void)renderColor:(Color *)color;
- (void)show;
@end
//================== Shape.m ==================
@implementation Shape
- (void)renderColor:(Color *)color{
_color = color;
}
- (void)show{
NSLog(@"Show %@ with %@",[self class],[_color class]);
}
@end
由上面的代码可以看出:
Shape
持有Color
类的实例,二者是以组合的形式结合到一起的。而且Shape
类定义了供外部传入Color
实例的方法renderColor:
:在这个方法里面接收从外部传入的Color
实例并保存起来。show
实际上就是打印这个图形的名称及其所搭配的颜色,便于我们后续验证。接着我们创建三种不同的图形类,它们都继承于Shape
类:
正方形类:
//================== Square.h ==================
@interface Square : Shape
@end
//================== Square.m ==================
@implementation Square
- (void)show{
[super show];
}
@end
长方形类:
//================== Rectangle.h ==================
@interface Rectangle : Shape
@end
//================== Rectangle.m ==================
@implementation Rectangle
- (void)show{
[super show];
}
@end
圆形类:
//================== Circle.h ==================
@interface Circle : Shape
@end
//================== Circle.m ==================
@implementation Circle
- (void)show{
[super show];
}
@end
还记得上面的Shape
类持有的Color
类么?它就是所有颜色类的父类:
//================== Color.h ==================
@interface Color : NSObject
@end
//================== Color.m ==================
@implementation Color
@end
接着我们创建继承这个Color
类的三个颜色类:
红色类:
//================== RedColor.h ==================
@interface RedColor : Color
@end
//================== RedColor.m ==================
@implementation RedColor
@end
绿色类:
//================== GreenColor.h ==================
@interface GreenColor : Color
@end
//================== GreenColor.m ==================
@implementation GreenColor
@end
蓝色类:
//================== BlueColor.h ==================
@interface BlueColor : Color
@end
//================== BlueColor.m ==================
@implementation BlueColor
@end
OK,到现在所有的形状类和颜色类的相关类已经创建好了,我们看一下客户端是如何使用它们来组合成不同的带有颜色的形状的:
//================== client ==================
//create 3 shape instances
Rectangle *rect = [[Rectangle alloc] init];
Circle *circle = [[Circle alloc] init];
Square *square = [[Square alloc] init];
//create 3 color instances
RedColor *red = [[RedColor alloc] init];
GreenColor *green = [[GreenColor alloc] init];
BlueColor *blue = [[BlueColor alloc] init];
//rect & red color
[rect renderColor:red];
[rect show];
//rect & green color
[rect renderColor:green];
[rect show];
//circle & blue color
[circle renderColor:blue];
[circle show];
//circle & green color
[circle renderColor:green];
[circle show];
//square & blue color
[square renderColor:blue];
[square show];
//square & red color
[square renderColor:red];
[square show];
上面的代码里,我们先声明了所有的形状类和颜色类的实例,然后自由搭配,形成不同的形状+颜色的组合。
下面我们通过打印的结果来看一下组合的效果:
Show Rectangle with RedColor
Show Rectangle with GreenColor
Show Circle with BlueColor
Show Circle with GreenColor
Show Square with BlueColor
Show Square with RedColor
从打印的接口可以看出组合的结果是没问题的。
跟上面没有使用桥接模式的设计相比,使用桥接模式需要的类的总和是 m + n
:当m或n的值很大的时候是远小于 m * n
(没有使用桥接,而是使用继承的方式)的。
而且如果后面还要增加形状和颜色的话,使用桥接模式就可以很方便地将原有的形状和颜色和新的形状和颜色进行搭配了,新的类和旧的类互不干扰。
下面我们看一下上面代码所对应的类图:
桥接模式代码示例类图
从 UML 类图可以看出,该设计是由两个抽象层的类
Shape
和Color
构建的,正因为依赖的双方都是抽象类(而不是具体的实现),而且二者是以组合的方式联系到一起的,所以扩展起来非常方便,互不干扰。这对于今后我们对代码的设计有比较好的借鉴意义。
Spring-JDBC
中的DriveManager
通过registerDriver
方法注册不同类型的驱动