js設計模式--模板方法模式

aoping8發表於2019-01-07

前言

本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。

文章系列

js設計模式--單例模式

js設計模式--策略模式

js設計模式--代理模式

js設計模式--迭代器模式

js設計模式--釋出訂閱模式

js設計模式--命令模式

js設計模式--組合模式

概念

模板方法模式是一種只需使用繼承就可以實現的非常簡單的模式。 模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體的實現子類。通常 在抽象父類中封裝了子類的演算法框架,包括實現一些公共方法以及封裝子類中所有方法的執行順序。子類通過繼承這個抽象類,也繼承了整個演算法結構,並且可以選擇重寫父類的方法。

場景

一般用於可以抽取公共方法,例如泡咖啡和泡茶,我們可以抽取燒水 清洗杯具 沖泡等過程

優缺點

優點

可以複用公共方法,子類也不需要實現演算法部分

例子

模板引擎

我們實現一個簡單的模板引擎:


<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div id="nav"></div>
  <script>
    var formateStr = function (param, data) {
      return param.replace(/\{#(\w+)#\}/g, function (match, key) {
        return typeof data[key] === undefined ? "" : data[key];
      });
    };

    var Nav = function (data) {
      var _this = this;
      _this.item = '<li><a href="{#hrefUrl#}" title="{#title#}" {#sign#}>{#content#}</a></li>';
      _this.html = '<ul>';
      for (var i = 0, l = data.length; i < l; i++) {
        _this.html += formateStr(_this.item, data[i]);
      }
      _this.html += '</ul>';
      return _this.html;
    }


    var objNav = document.getElementById('nav');
    objNav.innerHTML = Nav([{
        hrefUrl: 'http://www.baidu.com',
        content: '百度一下'
      },
      {
        hrefUrl: 'http://www.zhihu.com',
        content: '知乎一下'
      }
    ]);
  </script>
</body>

</html>


複製程式碼

現在產品加了一個需求,想在content後面加個span標籤展示訪問次數

新需求

普通程式設計師就會動手去改Nav方法,但這違背了開放封閉原則,我們也不能確保不影響原來的功能, 其實我們加多一個模板方法就可以規避這樣的問題



<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>

<body>
  <div id="nav"></div>
  <script>
    var formateStr = function (param, data) {
      return param.replace(/\{#(\w+)#\}/g, function (match, key) {
        return typeof data[key] === undefined ? "" : data[key];
      });
    };

    var Nav = function (data) {
      var _this = this;
      _this.item = '<li><a href="{#hrefUrl#}" title="{#title#}" {#sign#}>{#content#}</a></li>';
      _this.html = '<ul>';
      for (var i = 0, l = data.length; i < l; i++) {
        _this.html += formateStr(_this.item, data[i]);
      }
      _this.html += '</ul>';
      return _this.html;
    }

    var infoNav = function (data) {
      var _this = this;
      _this.info = '<span>{#clickNum#}</span>';
      for (var i = data.length - 1; i >= 0; i--) {
        data[i].content += formateStr(_this.info, data[i]);
      };
      return Nav.call(this, data);
    };
    var objNav = document.getElementById('nav');
    objNav.innerHTML = infoNav([{
        hrefUrl: 'http://www.baidu.com',
        content: '百度一下',
        title: '百度',
        clickNum: '10',
        sign: 'sign="1"'
      },
      {
        hrefUrl: 'http://www.zhihu.com',
        content: '知乎一下',
        title: '知乎',
        clickNum: '100',
        sign: 'sign="2"'
      }
    ]);
  </script>
</body>

</html>
複製程式碼

相關文章