在不改变原对象的基础上,动态地给该对象添加一些额外的功能,就叫做装饰者模式。
比如,公司网站的登陆页面如下:
只需要输入账号和密码即可登陆。
例子:
<input type="text" name="user_name" value="Tom" /> <input type="password" name="user_password" value="000" /> <button>submit</button> // 取得 Dom 元素 var userName = document.querySelector("[name=user_name]"), userPassword = document.querySelector("[name=user_password]"), btn = document.querySelector("button"); // 提交函数 var submitFn = function () { var data = { name: userName.value, password: userPassword.value, }; // 伪代码:提交数据给后台 (function Ajax(data) { console.log("submit:" + JSON.stringify(data)); })(data); }; //调用提交函数 btn.addEventListener("click", function () { submitFn(); });
后来需求有些变化:用户在提交给后台之前,应该做一些必要的校验,比如验证账号和密码是否为空。直接去修改 submitFn 函数自然是最直接的方法,但也是最差的方法。如果既想不改变原函数的代码,又想给该函数新增校验功能,装饰者模式是很好的选择。
例子:
<input type="text" name="user_name" value="Tom" /> <input type="password" name="user_password" value="000" /> <button>submit</button> // 取得 Dom 元素 var userName = document.querySelector("[name=user_name]"), userPassword = document.querySelector("[name=user_password]"), btn = document.querySelector("button"); // 提交函数:不修改 var submitFn = function () { var data = { name: userName.value, password: userPassword.value, }; (function Ajax(data) { console.log("submit:" + JSON.stringify(data)); })(data); }; // 新增校验函数,也就是装饰者函数 // 将提交函数嵌入到装饰者函数里 // 点击提交时,两个函数都可以依次执行 var checkFn = function (callBack) { var _check = function () { var userNameBool = userName.value === ""? false : true; var userPasswordBool = userPassword.value === ""? false : true; if (userNameBool && userPasswordBool) { return true; } return false; }; return function () { if (!_check()) { console.log("账号和密码不能为空!"); return; } callBack(); }; }; // 将装饰者函数再次赋值给变量 submitFn // 这样可以免于修改调用函数的函数名 submitFn = checkFn(submitFn); // 调用提交函数 // 此时的提交函数已经新增了校验功能 // 但提交函数本身和调用的函数名都不曾改变,不会影响即存的代码 btn.addEventListener("click", function () { submitFn(); });
如有错误,欢迎指正,本人不胜感激。