桥接模式
桥接模式是软件设计模式中最复杂的设计模式之一。需要将事物的对象和具体的行为,具体特征分离开来,使其可以各自独立的变化。桥接模式则在中间起类似于总调控的作用。
事物对象是一个较为抽象的概念,如‘圆形’,‘三角形’归于抽象的‘形状’之下,‘画圆形’和‘画三角形’则归于具体行为的‘画图’之下,然后‘形状’这个抽象可以调用‘画图’行为方法。
具体代码示例(来自维基百科):
下语言的代码用于写出两个不同的圆的坐标和半径。
API1.circle at 1:2 7.5
API2.circle at 5:7 27.5
-
/** "Implementor" */
-
interface DrawingAPI
-
{
-
public void drawCircle(double x, double y, double radius);
-
}
-
-
/** "ConcreteImplementor" 1/2 */
-
class DrawingAPI1 implements DrawingAPI
-
{
-
public void drawCircle(double x, double y, double radius)
-
{
-
System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
-
}
-
}
-
-
/** "ConcreteImplementor" 2/2 */
-
class DrawingAPI2 implements DrawingAPI
-
{
-
public void drawCircle(double x, double y, double radius)
-
{
-
System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
-
}
-
}
-
-
/** "Abstraction" */
-
interface Shape
-
{
-
public void draw(); // low-level
-
public void resizeByPercentage(double pct); // high-level
-
}
-
-
/** "Refined Abstraction" */
-
class CircleShape implements Shape
-
{
-
private double x, y, radius;
-
private DrawingAPI drawingAPI;
-
public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI)
-
{
-
this.x = x; this.y = y; this.radius = radius;
-
this.drawingAPI = drawingAPI;
-
}
-
-
// low-level i.e. Implementation specific
-
public void draw()
-
{
-
drawingAPI.drawCircle(x, y, radius);
-
}
-
// high-level i.e. Abstraction specific
-
public void resizeByPercentage(double pct)
-
{
-
radius *= pct;
-
}
-
}
-
-
/** "Client" */
-
class BridgePattern {
-
public static void main(String[] args)
-
{
-
Shape[] shapes = new Shape[2];
-
shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
-
shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());
-
-
for (Shape shape : shapes)
-
{
-
shape.resizeByPercentage(2.5);
-
shape.draw();
-
}
-
}
-
}
JS中的桥接模式
简单的桥接模式,无非就是在设计API的时候可以弱化对象间(对象与类)的耦合程度。
-
function sendInfo( element ){
-
var id = element.id;
-
ajax( "GET","info.json?id="+id, function( result ){
-
...
-
});
-
...
-
}
然后我们在很多地方或者事件中使用了sendInfo的方法,但是很明显该方法内部的 ajax 请求和整体的实现“性质”不太一样,那么将 ajax 请求方法独立出来,创建一个桥接与 ajax 和 回调函数以及其他代码运行的函数,就可以使整体的结构更加清晰合理,降低原有函数内部方法之间调用的耦合度。
那么就需要对他的结构使用最简单的桥接模式的处理下
-
function sendInfo( element ){
-
var id = element.id,
-
callback = function( result ){
-
// ...
-
}
-
sendInfoBridge( id, callback);
-
// ...
-
}
-
-
function sendInfoBridge( id, callback){
-
ajax( "GET","info.json?id="+id, function( result ){
-
callback( result );
-
});
-
// ...
-
}
那么简单的处理后 从结构上来说变得更为清晰,使得 sendInfo 中的部分方法脱离出来形成独立的方法。此处桥接可以看为 ajax 请求 与 id,callback 等的桥接。
桥接模式联结多个类
-
var Class1 = function( a, b, c ){
-
this.a = a;
-
this.bc = b*c;
-
}
-
var Class2 = function( d ){
-
this.d = d;
-
}
-
-
function BridgeClass(a, b, c, d){
-
this.class1 = new Class1(a, b, c);
-
this.class2 = new Class2(d);
-
}
但是 在此的作用并没有降低耦合度什么的,反而使新创建的构造函数依赖于之前的构造函数 Class1 和 Class2,超级类似于门面模式?
其实还是因为这里的实例太过于简单,简单来说,Class1 和 Class2 就是两个“性质”不一样的类,相当于最上面 维基百科 代码示例中的 shape 和 DrawingAPI, 而 BridgeClass 是将两个类联结在一起,使得 shape 可以调用 DrawingAPI 的中间桥接。也不用认为是依赖于之前的构造函数 Class1 和 Class2 因为本身就是实现两者,视为两代码从主程序中独立出来而并非依赖。
该方式与适配器模式和门面模式(外观模式)都有点相似,不过
与适配器模式不同之处 : 没有要求客户提供适配的数据。可以视为一种包装器,对接口进行适配以保证不同环境中兼容。
与门面模式不同之处 : 门面模式仅仅是提供一个简化的接口供客户使用,提供一个高级接口使得子系统更容易使用。而桥接模式中 Class1 和 Class2 是能独立于 BridgeClass 发生改变的,门面模式却不同。
在很多时候,我们会发现可能一些代码构建的太不合理,过于复杂,明明有更简单的方式来处理逻辑。但是也许是我们没有看到这样的处理方式代码的整体的影响。在此不举一些很复杂的例子,因为往往复杂的牛逼哄哄的例子往往都没啥心情学习与了解。
参考资料:
1. 维基百科-桥接模式
2.《JS设计模式》
阅读(4322) | 评论(0) | 转发(0) |