【D1n910】第 16 章 照猫画虎 —— 模版方法模式《JavaScript 设计模式》
正常操作,正常分析,大家好,我是D1n910。
今天我继续来学习 《JavaScript 设计模式》的第四篇 行为型设计模式
这是一个连续的读书笔记,所以如果你之前的内容没有看的话,可以去看看(建议直接看书,当然书的例子都比较早了,是2015年之前的代码内容,过了六年了,前端发展了很多,比如类的声明可以直接用 Class 了)。
前 15 章内容:

这里再次感谢 《Javascript 设计模式》及其作者 张荣铭,专栏内容是在它的基础上生成的。
现在会觉得很多设计模式离我们有点遥远,是因为我们现在都在用大佬写好的框架吧,很多设计模式都包含在框架里了。
后面有机会的话,我希望我可以查看目前主流框架的源代码,然后进行讲解。

第四篇 行为型设计模式
行为型设计模式用于不同对象之间职责划分或算法抽象,行为型设计模式不仅仅涉及类和对象,还涉及类或对象之间的交流模式并加以实现。
第 16 章 照猫画虎 —— 模版方法模式
模版方法模式(Template Method): 父类中定义一组操作算法骨架,而将一些实现步骤推迟到子类中,使得子类可以不改变父类的算法结构的同时可重新定义算法中某些实现步骤。
16.1、提示框归一化(P110)
书中给出的场景是项目里的提示框因为是不同的人写的,代码结构乃至最终样式都不太一样,希望能够把这些提示框进行统一。
这些提示框有
普通提示框,只有确认按钮;
操作提示框,有确认、取消按钮;
16.2、美味的蛋糕(P111)
像做蛋糕一样,每一个蛋糕造型不一样,但是它们的模版可以是一样的,都是圆柱体的蛋糕。
模版方法模式也是这样,先创造一个基础模版,然后再在这个基础模版上去继承改造。
16.3、创建基本提示框(P111) 16.4、模版原型方法(P112)
下面的开始用 ES6 类的写法~
class Alert {
constructor(data) {
if (!data) {
return;
}
// 设置内容
this.content = data.content;
// 创建提示框面板
this.panel = document.createElement('div');
// 创建提示内容组件
this.contentNode = document.createElement('p');
// 创建确定按钮组件
this.confirmBtn = document.createElement('div');
// 创建关闭按钮组件
this.closeBtn = document.createElement('b');
// 为提示框面板添加类
this.panel.className = 'alert';
// 为确定按钮组件添加类
this.confirmBtn.className = 'a-confirm';
// 为取消按钮组件添加类
this.closeBtn.className = 'a-close';
this.closeBtn.innerHTML = 'X';
// 为确定按钮添加文案
this.confirmBtn.innerHTML = data.confirm || '确定';
// 为提示内容添加文本
this.contentNode.innerHTML = this.content;
// 点击确定按钮执行方法,如果 data 中有 success 方法则为 success 方法,否则为空函数
this.success = data.success || function () {}
// 点击关闭按钮执行方法
this.fail = data.fail || function () {}
}
init() {
this.panel.appendChild(this.closeBtn);
this.panel.appendChild(this.contentNode);
this.panel.appendChild(this.confirmBtn);
// 插入页面中
document.body.appendChild(this.panel);
// 绑定事件
this.bindEvent();
// 显示提示框
this.show();
}
bindEvent() {
var me = this;
this.closeBtn.onclick = function () {
// 执行关闭方法
me.fail();
// 隐藏弹层
me.hide();
}
this.confirmBtn.onclick = function () {
// 执行确定方法
me.success();
// 隐藏弹层
me.hide();
}
}
// 隐藏弹框的方法
hide() {
this.panel.style.display = 'none';
}
// 展示弹框的方法
show() {
this.panel.style.display = 'block';;
}
}
document.getElementById('showNormalBtn').addEventListener('click', function() {
new Alert({
content: '普通内容'
}).init()
})

16.6、继承类也可以作为模版类
class AlertConfirmCancel extends Alert {
constructor(data) {
super(data);
// 创建取消按钮组件
this.cancelBtn = document.createElement('div');
this.cancelBtn.className = 'a-btn a-cancel';
// 为确定按钮添加文案
this.cancelBtn.innerHTML = data.confirm || '取消';
this.cancelFn = data.cancelFn || function () {}
}
init() {
super.init()
this.panel.appendChild(this.cancelBtn);
}
bindEvent() {
super.bindEvent()
const me = this
this.cancelBtn.onclick = function () {
// 执行徐晓方法
me.cancelFn();
// 隐藏弹层
me.hide();
}
}
}
document.getElementById('showConfirmCancelBtn').addEventListener('click', function() {
new AlertConfirmCancel({
content: '又有取消又有确定'
}).init()
})

模版方法的核心在于对方法的重用,它将核心方法封装在基类中,让子类继承基类的方法实现基类的共享。
我们一般在基类中封装不变的算法或者具有稳定的调用方式。
子类继承基类的时候,可以重写继承的方法,同时也可以复用继承的方法。
本章 End
加油加油
2021年02月23日 D1n910 学习于南山后海