设计模式——桥接模式【结构型模式】(诸葛韩信总结版)

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

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

桥接模式和适配器模式有点相似,都是接口在抽象化和实现化的一个解耦过程。总得来说桥接模式更在意的是抽象化的全部,是对每一个对象进行一个拼接,成为一个成品;而适配器是为了一个目的,不惜兼容原来的对象,制造一个“接合器”。一个是实现代码前就已经考虑到的方式,一个是为了适配当前的代码不惜制造一个“转换器”。

一、桥接模式的优缺点

优点: 1、抽象和实现的分离。 2、优秀的扩展能力。 3、实现细节对客户透明。
缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
其实,桥接模式在书写js代码的时候,也是经常用到的方式,即便真的是设计上有点难度,但是为了少写代码,我们还是要经常构思桥接模式。何况我们也是经常跨越桥的行者。这么看来,这些缺点就不成为缺点了,只会让入门者更加用功学习。

二、桥接模式的实现

1、插件中常用桥接模式
比如jquery。我们常用的each方法就是典型的桥接模式。我们一般循环一个对象(一般是数组或者是伪数组,当然规范的Object也是可以用for…in…循环的)都会用到js的for循环。而这个时候,我们不想每次循环的时候都调用原生的js,而且还得去判断一下传入的元素的数据类型,那么我们来好好封装一下它。首先,我们定义的“each”方法必须有两个参数,正如jq的写法:

$.each(arr, function( index, value ) { // 遍历一个arr数组
  alert( index + ": " + value );
});

其中,arr就是需要遍历的对象,而function后的内容就是一个回调函数,用来处理每个遍历的内容。
那么很容易实现啦,我们只需要判断一下传入的arr是什么数据类型即可。如下:

// 通过字面量方式实现的函数each
var each =  function(object, callback) {
  var type = (function(){
          switch (object.constructor){
            case Object:
                return 'Object';
                break;
            case Array:
                return 'Array';
                break;
            case NodeList:
                return 'NodeList';
                break;
            default:
                return 'null';
                break;
        }
    })();
    // 为数组或类数组时, 返回: index, value
    if(type === 'Array' || type === 'NodeList'){
        // 由于存在类数组NodeList, 所以不能直接调用every方法
        [].every.call(object, function(v, i){
            return callback.call(v, i, v) === false ? false : true;
        });
    }
    // 为对象格式时,返回:key, value
    else if(type === 'Object'){
        for(var i in object){
            if(callback.call(object[i], i, object[i]) === false){
                break;
            }
        }
    }
}

2、弹框弹出
我们经常会在项目中封装弹框,而弹框的样式有很多种,这个时候如果用桥接模式那就相当明朗了。
我们来试试全屏弹框和局部提示框的写法。
首先我们得写好抽象部分,也就是分配具体项的“中间层”,如下

function fullscreenDialog(status) {
  this.status= status;
}
fullscreenDialog.prototype.display = function () {
  this.status.display ();
}
function partDialog(status) {
  this.status= status;
}
partDialog.prototype.display = function () {
  this.status.display();
}

接下来,我们需要写一个具体方法,就是animation的具体实现,弹框都有居中的、右侧的、左侧的等等,我们来实现一下

function centerDisplay() {
}
centerDisplay.prototype.display= function () {
  console.log("it is center");
}
function rightDisplay() {
}
rightDisplay.prototype.display= function () {
  console.log("it is right");
}
function leftDisplay() {
}
leftDisplay.prototype.display = function () {
  console.log("it is left");
}

这样我们就可以愉快的调用上述的方式了,如下:

var message = new fullscreenDialog(new centerDisplay()); // 先定义一个居中的全屏弹框
message.display(); // it is center

3、元素主动操作
不管是小程序、vue、react、原生js,对某一个按钮点击后的方法,有经验的程序员,一般都会将它们分离出来,即不在点击方法里边糅合过多的方法内容,方便利用。

	<div onclick=“buildBridge”>点击我请求接口</div>
    function doitFn(id,callback) { // 这是具体类,也就是点击了div后具体实现的方法jqRequest理解成jq的接口请求
      jqRequest('POST',`urlgettheresult`,function (res) {
        // 回调 传入返回值
        callback(res.responseText)
      }) 
    }
    
    function buildBridge(e) {
      // 把id作为参数传递给doitFn函数是合情合理的,这里使用一个回调函数把回应结果返回 现在我们将针对接口而不是实现进行编程 
      doitFn(this.id,function (parameter)  {
        console.log(`res.responseText`,parameter )
      })
    }

三、总结

桥接模式的主要作用就是将抽象类和具体类实行严格的分离,抽象类只负责最后的引用,而完全不会理会具体类的实现的方式。
只是有一些地方需要注意,当项目不必要进行分离或者封装其中某些方法的时候,可以不用考虑桥接。因为一座桥不可能够建了就只有一个人走嘛,那不就造成了大量的资源浪费吗?

参考:
1、菜鸟学院——桥接模式 https://www.runoob.com/design-pattern/bridge-pattern.html
2、详解JavaScript设计模式开发中的桥接模式使用 https://www.jb51.net/article/84487.htm
3、原生js实现each方法 https://www.jianshu.com/p/8b9f09fe656b

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值