反向装饰器模式在JavaScript中的应用

在本文中,将探讨一种模块化编程风格,即反向装饰器模式,它遵循SOLID原则。已经在组织内部的几个项目中使用了这种模式,并希望得到他人的反馈。为了专注于模式本身,将以一个简单的待办事项应用为例。假设已经阅读并理解了其他两篇文章,本文将仅展示JavaScript中的实现。

一直在探索装饰器模式,并在VB.NET中实现了它,因为这是在工作中使用最多的语言。写了第一篇文章,介绍了装饰器模式,并进行了解释。接下来,写了反向装饰器的文章,同样进行了解释。想在JavaScript中实现这种模式,因为这种语言提供了一些优势。函数不需要在类中编写,对数据对象有更大的灵活性,不需要实现接口。主要想发布这个示例,所以不会重复在其他两篇文章中覆盖的内容。

起点

todo.html文件开始。在HTML中,为待办事项应用创建了基本的用户界面。它引用了Bootstrap CSS。将从两个JavaScript文件开始,以帮助组织项目。todo.js文件是组合动作并运行的地方。在todoAdd.js中,将定义所有函数。发现将函数与组合和运行分开更容易维护。

首先定义函数

将从函数文件todoAdd.js开始。基本函数将采用这种格式:

function functionName(anyPramsHere, next) { return function (dataObj) { // function logic here if (next) { next(dataObj); } }; }

这种格式将允许将函数组合在一起。使用JavaScript而不是VB.NET的一个好处是不必声明一个类。可以使用一个可以返回另一个函数的函数。"next"是下一个函数,"dataObj"是将状态从一个函数传递到下一个函数的类。

对于这个简单的应用,将使用五个函数。它们是:

  • 添加错误处理程序
  • 从表单获取数据
  • 将数据添加到表格
  • 按到期日期对表格进行排序
  • 向用户显示任何错误

这些函数都不是特别惊人,将像这样完成它们:

function getDataFromForm(next) { return function (dataObj) { if (!dataObj.hasError) { dataObj.dtAddDueDate = document.getElementById("dtAddDueDate").value; dataObj.txtAddTask = document.getElementById("txtAddTask").value; } if (next) { next(dataObj); } }; } function addToTable(next) { return function (dataObj) { if (!dataObj.hasError) { var newRow = document.createElement("tr"); var ckCol = document.createElement("td"); var ck = document.createElement("input"); ck.type = "checkbox"; ckCol.appendChild(ck); newRow.appendChild(ckCol); var dtCol = document.createElement("td"); dtCol.innerText = dataObj.dtAddDueDate; newRow.appendChild(dtCol); var taskCol = document.createElement("td"); taskCol.innerText = dataObj.txtAddTask; newRow.appendChild(taskCol); var tblBody = document.getElementById("tblBody"); tblBody.appendChild(newRow); } if (next) { next(dataObj); } }; } function sortTableOnDueDate(next) { return function (dataObj) { var rows = document.getElementById("tblBody").rows; var numSorted; do { numSorted = 0; for (var i = 0; i < rows.length; i++) { var currEl = rows[i]; var nextEl = currEl.nextElementSibling; if (nextEl && new Date(currEl.cells[1].innerText) > new Date(nextEl.cells[1].innerText)) { document.getElementById("tblBody").insertBefore(nextEl, currEl); numSorted++; } } } while (numSorted > 0); if (next) { next(dataObj); } }; } function addErrHandler(next) { return function (dataObj) { dataObj.err = { hasError: false, message: "" }; try { if (next) { next(dataObj); } } catch (err) { dataObj.err.hasError = true; dataObj.err.message = err.message; next(dataObj); } }; } function showErrorToUser(next) { return function (dataObj) { if (dataObj.err.hasError) { alert("ERROR: " + dataObj.err.message); } if (next) { next(dataObj); } }; }

将函数组合在一起

var addToDo = function () { // we compose here: var runMe = null; runMe = showErrorToUser(runMe); runMe = sortTableOnDueDate(runMe); runMe = addToTable(runMe); runMe = getDataFromForm(runMe); runMe = addErrHandler(runMe); dataObj = {}; // run here: runMe(dataObj); };
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485