切图仔最后的倔强:包教不包会设计模式 - 结构型.md

1. 什么是结构型模式

结构型模式主要用于处理类和对象的组合,对应思维导图:

2. 外观模式: Facade Pattern

对接口二次封装隐藏其复杂性,并简化其使用。
外观模式包含如下角色:

  • Facade: 外观角色
  • SubSystem: 子系统角色


使用时机

当我们将系统分成多个子系统时,我们会降低代码复杂性。编程时的最佳实践是最小化子系统之间的通信和依赖关系。实现这一目标的一个好方法是引入一个facade对象,为子系统提供单一且统一的接口。

1. 跨浏览器监听事件

要保证处理事件的代码在大多数浏览器下一致运行,需要关注冒泡阶段。

在做跨浏览器网站时,你已经不经意间使用了外观模式

var addMyEvent = function( el,ev,fn ){
  if( el.addEventListener ){//存在DOM2级方法,则使用并传入事件类型、事件处理程序函数和第3个参数false(表示冒泡阶段)
        el.addEventListener( ev,fn, false );
  }else if(el.attachEvent){ // 为兼容IE8及更早浏览器,注意事件类型必须加上"on"前缀
        el.attachEvent( "on" + ev, fn );
  }else{
       el["on" + ev] = fn;//其他方法都无效,默认采用DOM0级方法,使用方括号语法将属性名指定为事件处理程序
    }
};

2. jQuery $(document).ready(..)

我们都熟悉$(document).ready(..)。在源码中,这实际上是一个被调用的方法提供的bindReady()

加载事件共用两种方法:window.onload()$(document).ready()

bindReady: function() {
    ...
    if ( document.addEventListener ) {
      // Use the handy event callback
      document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

      // A fallback to window.onload, that will always work
      window.addEventListener( "load", jQuery.ready, false );

    // If IE event model is used
    } else if ( document.attachEvent ) {

      document.attachEvent( "onreadystatechange", DOMContentLoaded );

      // A fallback to window.onload, that will always work
      window.attachEvent( "onload", jQuery.ready );

Facade 外观模式大量应用于 jQuery库以让其更容易被使用。譬如我们使用
jQuery$(el).css()$(el).animate() 等方法 。

使我们不必手动在jQuery 内核中调用很多内部方法以便实现某些行为,也同时避免了手动与 DOM API 交互。

类似的还有D3.js

3. 适配器模式: Adapter Pattern

  • 传统:适配两个及以上类接口不兼容的问题
  • JS: 可额外适配两个及以上代码库、前后端数据等。

使用时机
通常使用适配器的情况:

  • 需要集成新组件并与应用程序中的现有组件一起工作。
  • 重构,程序的哪些部分用改进的接口重写,但旧代码仍然需要原始接口。

1. jQuery.fn.css()规范化显示

// Cross browser opacity:
// opacity: 0.9;  Chrome 4+, FF2+, Saf3.1+, Opera 9+, IE9, iOS 3.2+, Android 2.1+ 
// filter: alpha(opacity=90);  IE6-IE8 
   
// Setting opacity
$( ".container" ).css( { opacity: .5 } );

// Getting opacity
var currentOpacity = $( ".container" ).css('opacity');

内部实现为:

get: function( elem, computed ) {
  return ropacity.test( (
        computed && elem.currentStyle ? 
            elem.currentStyle.filter : elem.style.filter) || "" ) ?
    ( parseFloat( RegExp.$1 ) / 100 ) + "" :
    computed ? "1" : "";
},

set: function( elem, value ) {
  var style = elem.style,
    currentStyle = elem.currentStyle,
    opacity = jQuery.isNumeric( value ) ? 
          "alpha(opacity=" + value * 100 + ")" : "",
    filter = currentStyle && currentStyle.filter || style.filter || "";

  style.zoom = 1;

  // 如果将不透明度设置为1,则移除其他過濾器
  //exist - attempt to remove filter attribute #6652
  if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {
    style.removeAttribute( "filter" );
    if ( currentStyle && !currentStyle.filter ) {
      return;
    }
  }

  // otherwise, set new filter values
  style.filter = ralpha.test( filter ) ?
    filter.replace( ralpha, opacity ) :
    filter + " " + opacity;
}
};

2. Vue中的computed

yck - 《前端面试之道》

Vue 中,我们其实经常使用到适配器模式。

比如父组件传递给子组件一个时间戳属性,组件内部需要将时间戳转为正常的日期显示,一般会使用 computed 来做转换这件事情,这个过程就使用到了适配器模式。

4. 代理模式: Proxy

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值