前言
本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。
文章系列
概念
模板方法模式是一種只需使用繼承就可以實現的非常簡單的模式。 模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體的實現子類。通常 在抽象父類中封裝了子類的演算法框架,包括實現一些公共方法以及封裝子類中所有方法的執行順序。子類通過繼承這個抽象類,也繼承了整個演算法結構,並且可以選擇重寫父類的方法。
場景
一般用於可以抽取公共方法,例如泡咖啡和泡茶,我們可以抽取燒水 清洗杯具 沖泡等過程
優缺點
優點
可以複用公共方法,子類也不需要實現演算法部分
例子
模板引擎
我們實現一個簡單的模板引擎:
<!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>
複製程式碼