前言

本系列文章主要根据《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>

普通程序员
4k 声望811 粉丝

分享IT干货,内推大厂