javascript框架设计第二版_设计模式(10)[JS版]JavaScript如何实现组合模式???

本文介绍了JavaScript中的组合模式,详细讲解了模式的概念、主要参与者,并提供了具体的代码实现,包括在表单验证和图片阅读器中的应用实例,帮助读者深入理解组合模式的运用。
摘要由CSDN通过智能技术生成
目录 1 什么是组合模式 2 主要参与者 3 代码实现 4 应用实例 4.1 表单验证 4.1 图片阅读器 5 总结

1 什么是组合模式

组合模式允许创建具有属性的对象,这些对象是原始项目或对象集合。集合中的每个项目本身可以容纳其他集合,创建深度嵌套结构。 树型控件是复合模式的一个完美例子。树的节点要么包含一个单独的对象(叶子节点),要么包含一组对象(节点的子树)。组合模式用于简单化,一致化对单组件和复合组件的使用,其实它就是一棵树。 组合模式能对于工作能起到简化作用,组合对象实现某一操作时,通过递归,向下传递到所有的组成对象,在存在大批对象时,假如页面的包含许多拥有同样功能的对象,只需要操作组合对象即可达到目标。 在存在着某种的层次结构,并且其中的一部分要实现某些操作,即可使用组合模式。 组合模式中的所有节点都共享一组通用的属性和方法,它既支持单个对象,也支持对象集合。这种共同的接口极大地促进了递归算法的设计和构建,这种算法可以对复合集合中的每个对象进行迭代。 实例场景: 1 自然界中的各种树,树长在大地上,树头(树根),即是入口点,这棵树头向上生长,即有自己的叶子,又有自己的子树枝,某树枝还有自己的叶子,跟子树枝。 2  操作系统目录结构、公司部门组织架构、国家省市县等,像这么看起来复杂的现象,都可以使用组合模式,即部分-整体模式来操作。

f66d482ce6d900dbf14af857fac77bb7.png

2 主要参与者

8ef65607c03d3a798ab8af9a7bb20c51.png 参与该模式的对象有: Component :声明组成中对象的接口。 Leaf :代表构图中的叶子对象,一个叶子没有子对象。 Composite :表示组成中的分支(或子树),维护一个子组件的集合。

3 代码实现

在下边的代码中,Node(节点)对象创建了一个树状结构。每个节点都有一个名字和4个方法:add、remove、getChild和hasChildren。这些方法被添加到Node的原型中。这减少了对内存的要求,因为这些方法现在被所有节点共享。Node是完全递归的,不需要单独的Component或Leaf对象。 通过向父节点添加节点来构建一个小型的复合树。一旦完成,我们调用traverse,它将遍历树中的每个节点,并显示其名称和深度(通过缩进显示)。日志函数用来记录和显示结果。
!DOCTYPE htmlhtmlheadmeta charset=\"utf-8\"title/title/headbody/bodyscript length; i++) {\n\t\t\t\t\tif (this.children[i] === child) {\n\t\t\t\t\t\tthis.children.splice(i, 1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tgetChild: function(i) {\n\t\t\t\treturn this.children[i];\n\t\t\t},\n\n\t\t\thasChildren: function() {\n\t\t\t\treturn this.children.length < 0;\n\t\t\t}\n\t\t}\n\n\t\t// 使用递归遍历一个树\t \n\t\tfunction traverse(indent, node) {\n\t\t\tlog.add(Array(indent++).join(\"--\") + node.name);\n\n\t\t\tfor (var i = 0, len = node.children.length; i > len; i++) {\n\t\t\t\ttraverse(indent, node.getChild(i));\n\t\t\t}\n\t\t}\n\n\t\t// 日志函数记录和打印结果\n\t\tvar log = (function() {\n\t\t\tvar log = \"\";\n\n\t\t\treturn {\n\t\t\t\tadd: function(msg) {\n\t\t\t\t\tlog += msg + \"\\n\";\n\t\t\t\t},\n\t\t\t\tshow: function() {\n\t\t\t\t\tconsole.info(\"%c%s\", \"color:red; font-size:18px\", log);\n\t\t\t\t\tlog = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\tfunction run() {\n\t\t\tvar tree = new Node(\"root\");\n\t\t\tvar left = new Node(\"left\")\n\t\t\tvar right = new Node(\"right\");\n\t\t\tvar leftleft = new Node(\"leftleft\");\n\t\t\tvar leftright = new Node(\"leftright\");\n\t\t\tvar rightleft = new Node(\"rightleft\");\n\t\t\tvar rightright = new Node(\"rightright\");\n\n\t\t\ttree.add(left);\n\t\t\ttree.add(right);\n\t\t\ttree.remove(right); // 删除节点\n\t\t\ttree.add(right);\n\n\t\t\tleft.add(leftleft);\n\t\t\tleft.add(leftright);\n\n\t\t\tright.add(rightleft);\n\t\t\tright.add(rightright);\n\n\t\t\ttraverse(1, tree);\n\n\t\t\tlog.show();\n\t\t}\n\t\trun();\n\t>/script/html
<html>  <head>    <meta charset="utf-8">    <title>组合模式:公众号AlbertYangtitle>  head>  <body>  body>  <script>    var Node = function(name) {      this.children = [];      this.name = name;    }    Node.prototype = {      add: function(child) {        this.children.push(child);      },      remove: function(child) {        var length = this.children.length;        for (var i = 0; i < length; i++) {          if (this.children[i] === child) {            this.children.splice(i, 1);            return;          }        }      },      getChild: function(i) {        return this.children[i];      },      hasChildren: function() {        return this.children.length > 0;      }    }    // 使用递归遍历一个树    function traverse(indent, node) {      log.add(Array(indent++).join("--") + node.name);      for (var i = 0, len = node.children.length; i < len; i++) {        traverse(indent, node.getChild(i));      }    }    // 日志函数记录和打印结果    var log = (function() {      var log = "";      return {        add: function(msg) {          log += msg + "\n";        },        show: function() {          console.info("%c%s", "color:red; font-size:18px", log);          log = "";        }      }    })();    function run() {      var tree = new Node("root");      var left = new Node("left")      var right = new Node("right");      var leftleft = new Node("leftleft");      var leftright = new Node("leftright");      var rightleft = new Node("rightleft");      var rightright = new Node("rightright");      tree.add(left);      tree.add(right);      tree.remove(right); // 删除节点      tree.add(right);      left.add(leftleft);      left.add(leftright);      right.add(rightleft);      right.add(rightright);      traverse(1, tree);      log.show();    }    run();script>html>
!DOCTYPE htmlhtmlheadmeta charset=\"utf-8\"title/title/headbody/bodyscript length; i++) {\n\t\t\t\t\tif (this.children[i] === child) {\n\t\t\t\t\t\tthis.children.splice(i, 1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tgetChild: function(i) {\n\t\t\t\treturn this.children[i];\n\t\t\t},\n\n\t\t\thasChildren: function() {\n\t\t\t\treturn this.children.length < 0;\n\t\t\t}\n\t\t}\n\n\t\t// 使用递归遍历一个树\t \n\t\tfunction traverse(indent, node) {\n\t\t\tlog.add(Array(indent++).join(\"--\") + node.name);\n\n\t\t\tfor (var i = 0, len = node.children.length; i > len; i++) {\n\t\t\t\ttraverse(indent, node.getChild(i));\n\t\t\t}\n\t\t}\n\n\t\t// 日志函数记录和打印结果\n\t\tvar log = (function() {\n\t\t\tvar log = \"\";\n\n\t\t\treturn {\n\t\t\t\tadd: function(msg) {\n\t\t\t\t\tlog += msg + \"\\n\";\n\t\t\t\t},\n\t\t\t\tshow: function() {\n\t\t\t\t\tconsole.info(\"%c%s\", \"color:red; font-size:18px\", log);\n\t\t\t\t\tlog = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\tfunction run() {\n\t\t\tvar tree = new Node(\"root\");\n\t\t\tvar left = new Node(\"left\")\n\t\t\tvar right = new Node(\"right\");\n\t\t\tvar leftleft = new Node(\"leftleft\");\n\t\t\tvar leftright = new Node(\"leftright\");\n\t\t\tvar rightleft = new Node(\"rightleft\");\n\t\t\tvar rightright = new Node(\"rightright\");\n\n\t\t\ttree.add(left);\n\t\t\ttree.add(right);\n\t\t\ttree.remove(right); // 删除节点\n\t\t\ttree.add(right);\n\n\t\t\tleft.add(leftleft);\n\t\t\tleft.add(leftright);\n\n\t\t\tright.add(rightleft);\n\t\t\tright.add(rightright);\n\n\t\t\ttraverse(1, tree);\n\n\t\t\tlog.show();\n\t\t}\n\t\trun();\n\t>/script/html

4 应用实例

4.1 表单验证    

演示地址: https://www.albertyy.com/2020/8/Component1.html
    表单验证中,需要做的工作是表单的保存、恢复和验证表单中的值,然而表单的数量是未知数,类型是未知数,只有功能能确定,在这种情况下,使用组合模式无疑最好,通过给每个表单添加功能,然后一个表单对象组合起来,通过操作表单对象即可达到操作表单。
!DOCTYPE htmlhtmlheadmeta charset=\"utf-8\"title/title/headbodyinput type=\"button\" value=\"存储\" onclick=\"a()\" /input type=\"button\" value=\"取出\" onclick=\"b()\" //bodyscript type=\"text/javascript\" len; i++) {\n\t\t\t\tif (child == this.formComponents[i]) {\n\t\t\t\t\tthis.formComponents.splice(i, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCompositeForm.prototype.getChild = function(i) {\n\t\t\treturn this.formComponents[i];\n\t\t}\n\n\t\tCompositeForm.prototype.save = function() {\n\t\t\tfor (var i = 0, len = this.formComponents.length; i > len; i++) {\n\t\t\t\tthis.formComponents[i].save();\n\t\t\t}\n\t\t}\n\t\tCompositeForm.prototype.restore = function() {\n\t\t\tfor (var i = 0, len = this.formComponents.length; i > len; i++) {\n\t\t\t\tthis.formComponents[i].restore();\n\t\t\t}\n\t\t}\n\t\tCompositeForm.prototype.getElement = function() {\n\t\t\treturn this.element;\n\t\t}\n\t\t//接口方法\n\t\tvar Field = function(id) {\n\t\t\tthis.id = id;\n\t\t\tthis.element;\n\t\t\tthis.content;\n\t\t};\n\t\tField.prototype.add = function() {};\n\t\tField.prototype.remove = function() {};\n\t\tField.prototype.getChild = function() {};\n\n\t\tField.prototype.save = function() {\n\t\t\tsetCookie(this.id, this.getValue());\n\t\t};\n\t\tField.prototype.getElement = function() {\n\t\t\treturn this.element;\n\t\t}\n\t\tField.prototype.getValue = function() {\n\t\t\tthrow new Error('错误');\n\t\t}\n\t\tField.prototype.restore = function() {\n\t\t\tthis.content.value = getCookie(this.id);\n\t\t};\n\t\t//继承方法\n\t\tfunction extend(subClass, superClass) {\n\t\t\tvar F = function() {};\n\t\t\tF.prototype = superClass.prototype;\n\t\t\tsubClass.prototype = new F();\n\t\t\tsubClass.prototype.constructor = subClass;\n\n\t\t\tsubClass.superclass = superClass.prototype;\n\t\t\tif (superClass.prototype.constructor == Object.prototype.constructor) {\n\t\t\t\tsuperClass.prototype.constructor = superClass;\n\t\t\t}\n\t\t}\n\t\t//输入框\n\t\tvar InputField = function(id, label) {\n\t\t\tField.call(this, id);\n\n\t\t\tthis.input = document.createElement('input');\n\t\t\tthis.content = this.input;\n\n\t\t\tthis.label = document.createElement('label');\n\t\t\tvar labelTextNode = document.createTextNode(label);\n\t\t\tthis.label.appendChild(labelTextNode);\n\n\t\t\tthis.element = document.createElement('div');\n\t\t\tthis.element.id = id;\n\t\t\tthis.element.className = 'input-field';\n\t\t\tthis.element.appendChild(this.label);\n\t\t\tthis.element.appendChild(this.input);\n\t\t}\n\t\textend(InputField, Field);\n\t\tInputField.prototype.getValue = function() {\n\t\t\treturn this.input.value;\n\t\t};\n\t\t//文本框\n\t\tvar TextareaField = function(id, label) {\n\t\t\tField.call(this, id);\n\n\t\t\tthis.textarea = document.createElement('textarea');\n\t\t\tthis.content = this.textarea;\n\n\t\t\tthis.label = document.createElement('label');\n\t\t\tvar labelTextNode = document.createTextNode(label);\n\t\t\tthis.label.appendChild(labelTextNode);\n\n\t\t\tthis.element = document.createElement('div');\n\t\t\tthis.element.id = id;\n\t\t\tthis.element.className = 'input-field';\n\t\t\tthis.element.appendChild(this.label);\n\t\t\tthis.element.appendChild(this.textarea);\n\t\t};\n\t\textend(TextareaField, Field);\n\t\tTextareaField.prototype.getValue = function() {\n\t\t\treturn this.textarea.value;\n\t\t};\n\t\t//选择框\n\t\tvar SelectField = function(id, label) {\n\t\t\tField.call(this, id);\n\n\t\t\tthis.select = document.createElement('select');\n\t\t\tthis.select.options.add(new Option(\"sfs\", \"sfs\"));\n\t\t\tthis.select.options.add(new Option(\"111\", \"2222222222\")); //这边value会改变\n\t\t\tthis.content = this.select;\n\n\t\t\tthis.label = document.createElement('label');\n\t\t\tvar labelTextNode = document.createTextNode(label);\n\t\t\tthis.label.appendChild(labelTextNode);\n\n\t\t\tthis.element = document.createElement('div');\n\t\t\tthis.element.id = id;\n\t\t\tthis.element.className = 'input-field';\n\t\t\tthis.element.appendChild(this.label);\n\t\t\tthis.element.appendChild(this.select);\n\t\t};\n\t\textend(SelectField, Field);\n\t\tSelectField.prototype.getValue = function() {\n\t\t\treturn this.select.options[this.select.options.selectedIndex].value;\n\t\t};\n\t\t//表单域\n\t\tvar CompositeFieldset = function(id, legendText) {\n\t\t\tthis.components = {};\n\n\t\t\tthis.element = document.createElement('fieldset');\n\t\t\tthis.element.id = id;\n\n\t\t\tif (legendText) {\n\t\t\t\tthis.legend = document.createElement('legend');\n\t\t\t\tthis.legend.appendChild(document.createTextNode(legendText));\n\t\t\t\tthis.element.appendChild(this.legend);\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.add = function(child) {\n\t\t\tthis.components[child.getElement().id] = child;\n\t\t\tthis.element.appendChild(child.getElement());\n\t\t};\n\n\t\tCompositeFieldset.prototype.remove = function(child) {\n\t\t\tdelete this.components[child.getElement().id];\n\t\t};\n\n\t\tCompositeFieldset.prototype.getChild = function(id) {\n\t\t\tif (this.components[id] != undefined) {\n\t\t\t\treturn this.components[id];\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.save = function() {\n\t\t\tfor (var id in this.components) {\n\t\t\t\tif (!this.components.hasOwnProperty(id))\n\t\t\t\t\tcontinue;\n\t\t\t\tthis.components[id].save();\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.restore = function() {\n\t\t\tfor (var id in this.components) {\n\t\t\t\tif (!this.components.hasOwnProperty(id))\n\t\t\t\t\tcontinue;\n\t\t\t\tthis.components[id].restore();\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.getElement = function() {\n\t\t\treturn this.element;\n\t\t};\n\n\n\t\t//用组合模式汇合起来\n\t\tvar contactForm = new CompositeForm('contact-form', 'POST', 'test');\n\n\t\tvar nameFieldset = new CompositeFieldset('name-fieldset');\n\t\tnameFieldset.add(new InputField('first-name', 'First Name'));\n\t\tnameFieldset.add(new InputField('last-name', 'Last Name'));\n\t\tcontactForm.add(nameFieldset);\n\n\t\tvar addressFieldset = new CompositeFieldset('address-fieldset');\n\t\taddressFieldset.add(new InputField('address', 'Address'));\n\t\taddressFieldset.add(new InputField('city', 'City'));\n\t\taddressFieldset.add(new SelectField('state', 'State'));\n\t\taddressFieldset.add(new InputField('zip', 'Zip'));\n\t\tcontactForm.add(addressFieldset);\n\n\t\tcontactForm.add(new TextareaField('comments', 'Comments'));\n\n\t\tdocument.body.appendChild(contactForm.getElement());\n\n\t\tfunction a() {\n\t\t\tcontactForm.save();\n\t\t}\n\n\t\tfunction b() {\n\t\t\tcontactForm.restore();\n\t\t}\n\t>/script/html
<html>  <head>    <meta charset="utf-8">    <title>组合模式实例应用:公众号AlbertYangtitle>  head>  <body>    <input type="button" value="存储" onclick="a()" />    <input type="button" value="取出" onclick="b()" />  body>  <script type="text/javascript">    //存储的值    var value_content = {};    function setCookie(name, value) {      value_content[name] = value;    }    function getCookie(name) {      return value_content[name];    }    //表单组合对象    var CompositeForm = function(id, method, action) {      this.formComponents = [];      this.element = document.createElement('form');      this.element.id = id;      this.element.method = method || 'POST';      this.element.action = action || '#';    }    CompositeForm.prototype.add = function(child) {      this.formComponents.push(child);      this.element.appendChild(child.getElement());    }    CompositeForm.prototype.remove = function(child) {      for (var i = 0, len = this.formComponents.length; i < len; i++) {        if (child == this.formComponents[i]) {          this.formComponents.splice(i, 1);          break;        }      }    }    CompositeForm.prototype.getChild = function(i) {      return this.formComponents[i];    }    CompositeForm.prototype.save = function() {      for (var i = 0, len = this.formComponents.length; i < len; i++) {        this.formComponents[i].save();      }    }    CompositeForm.prototype.restore = function() {      for (var i = 0, len = this.formComponents.length; i < len; i++) {        this.formComponents[i].restore();      }    }    CompositeForm.prototype.getElement = function() {      return this.element;    }    //接口方法    var Field = function(id) {      this.id = id;      this.element;      this.content;    };    Field.prototype.add = function() {};    Field.prototype.remove = function() {};    Field.prototype.getChild = function() {};    Field.prototype.save = function() {      setCookie(this.id, this.getValue());    };    Field.prototype.getElement = function() {      return this.element;    }    Field.prototype.getValue = function() {      throw new Error('错误');    }    Field.prototype.restore = function() {      this.content.value = getCookie(this.id);    };    //继承方法    function extend(subClass, superClass) {      var F = function() {};      F.prototype = superClass.prototype;      subClass.prototype = new F();      subClass.prototype.constructor = subClass;      subClass.superclass = superClass.prototype;      if (superClass.prototype.constructor == Object.prototype.constructor) {        superClass.prototype.constructor = superClass;      }    }    //输入框    var InputField = function(id, label) {      Field.call(this, id);      this.input = document.createElement('input');      this.content = this.input;      this.label = document.createElement('label');      var labelTextNode = document.createTextNode(label);      this.label.appendChild(labelTextNode);      this.element = document.createElement('div');      this.element.id = id;      this.element.className = 'input-field';      this.element.appendChild(this.label);      this.element.appendChild(this.input);    }    extend(InputField, Field);    InputField.prototype.getValue = function() {      return this.input.value;    };    //文本框    var TextareaField = function(id, label) {      Field.call(this, id);      this.textarea = document.createElement('textarea');      this.content = this.textarea;      this.label = document.createElement('label');      var labelTextNode = document.createTextNode(label);      this.label.appendChild(labelTextNode);      this.element = document.createElement('div');      this.element.id = id;      this.element.className = 'input-field';      this.element.appendChild(this.label);      this.element.appendChild(this.textarea);    };    extend(TextareaField, Field);    TextareaField.prototype.getValue = function() {      return this.textarea.value;    };    //选择框    var SelectField = function(id, label) {      Field.call(this, id);      this.select = document.createElement('select');      this.select.options.add(new Option("sfs", "sfs"));      this.select.options.add(new Option("111", "2222222222")); //这边value会改变      this.content = this.select;      this.label = document.createElement('label');      var labelTextNode = document.createTextNode(label);      this.label.appendChild(labelTextNode);      this.element = document.createElement('div');      this.element.id = id;      this.element.className = 'input-field';      this.element.appendChild(this.label);      this.element.appendChild(this.select);    };    extend(SelectField, Field);    SelectField.prototype.getValue = function() {      return this.select.options[this.select.options.selectedIndex].value;    };    //表单域    var CompositeFieldset = function(id, legendText) {      this.components = {};      this.element = document.createElement('fieldset');      this.element.id = id;      if (legendText) {        this.legend = document.createElement('legend');        this.legend.appendChild(document.createTextNode(legendText));        this.element.appendChild(this.legend);      }    };    CompositeFieldset.prototype.add = function(child) {      this.components[child.getElement().id] = child;      this.element.appendChild(child.getElement());    };    CompositeFieldset.prototype.remove = function(child) {      delete this.components[child.getElement().id];    };    CompositeFieldset.prototype.getChild = function(id) {      if (this.components[id] != undefined) {        return this.components[id];      } else {        return null;      }    };    CompositeFieldset.prototype.save = function() {      for (var id in this.components) {        if (!this.components.hasOwnProperty(id))          continue;        this.components[id].save();      }    };    CompositeFieldset.prototype.restore = function() {      for (var id in this.components) {        if (!this.components.hasOwnProperty(id))          continue;        this.components[id].restore();      }    };    CompositeFieldset.prototype.getElement = function() {      return this.element;    };    //用组合模式汇合起来    var contactForm = new CompositeForm('contact-form', 'POST', 'test');    var nameFieldset = new CompositeFieldset('name-fieldset');    nameFieldset.add(new InputField('first-name', 'First Name'));    nameFieldset.add(new InputField('last-name', 'Last Name'));    contactForm.add(nameFieldset);    var addressFieldset = new CompositeFieldset('address-fieldset');    addressFieldset.add(new InputField('address', 'Address'));    addressFieldset.add(new InputField('city', 'City'));    addressFieldset.add(new SelectField('state', 'State'));    addressFieldset.add(new InputField('zip', 'Zip'));    contactForm.add(addressFieldset);    contactForm.add(new TextareaField('comments', 'Comments'));    document.body.appendChild(contactForm.getElement());    function a() {      contactForm.save();    }    function b() {      contactForm.restore();    }script>html>
!DOCTYPE htmlhtmlheadmeta charset=\"utf-8\"title/title/headbodyinput type=\"button\" value=\"存储\" onclick=\"a()\" /input type=\"button\" value=\"取出\" onclick=\"b()\" //bodyscript type=\"text/javascript\" len; i++) {\n\t\t\t\tif (child == this.formComponents[i]) {\n\t\t\t\t\tthis.formComponents.splice(i, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tCompositeForm.prototype.getChild = function(i) {\n\t\t\treturn this.formComponents[i];\n\t\t}\n\n\t\tCompositeForm.prototype.save = function() {\n\t\t\tfor (var i = 0, len = this.formComponents.length; i > len; i++) {\n\t\t\t\tthis.formComponents[i].save();\n\t\t\t}\n\t\t}\n\t\tCompositeForm.prototype.restore = function() {\n\t\t\tfor (var i = 0, len = this.formComponents.length; i > len; i++) {\n\t\t\t\tthis.formComponents[i].restore();\n\t\t\t}\n\t\t}\n\t\tCompositeForm.prototype.getElement = function() {\n\t\t\treturn this.element;\n\t\t}\n\t\t//接口方法\n\t\tvar Field = function(id) {\n\t\t\tthis.id = id;\n\t\t\tthis.element;\n\t\t\tthis.content;\n\t\t};\n\t\tField.prototype.add = function() {};\n\t\tField.prototype.remove = function() {};\n\t\tField.prototype.getChild = function() {};\n\n\t\tField.prototype.save = function() {\n\t\t\tsetCookie(this.id, this.getValue());\n\t\t};\n\t\tField.prototype.getElement = function() {\n\t\t\treturn this.element;\n\t\t}\n\t\tField.prototype.getValue = function() {\n\t\t\tthrow new Error('错误');\n\t\t}\n\t\tField.prototype.restore = function() {\n\t\t\tthis.content.value = getCookie(this.id);\n\t\t};\n\t\t//继承方法\n\t\tfunction extend(subClass, superClass) {\n\t\t\tvar F = function() {};\n\t\t\tF.prototype = superClass.prototype;\n\t\t\tsubClass.prototype = new F();\n\t\t\tsubClass.prototype.constructor = subClass;\n\n\t\t\tsubClass.superclass = superClass.prototype;\n\t\t\tif (superClass.prototype.constructor == Object.prototype.constructor) {\n\t\t\t\tsuperClass.prototype.constructor = superClass;\n\t\t\t}\n\t\t}\n\t\t//输入框\n\t\tvar InputField = function(id, label) {\n\t\t\tField.call(this, id);\n\n\t\t\tthis.input = document.createElement('input');\n\t\t\tthis.content = this.input;\n\n\t\t\tthis.label = document.createElement('label');\n\t\t\tvar labelTextNode = document.createTextNode(label);\n\t\t\tthis.label.appendChild(labelTextNode);\n\n\t\t\tthis.element = document.createElement('div');\n\t\t\tthis.element.id = id;\n\t\t\tthis.element.className = 'input-field';\n\t\t\tthis.element.appendChild(this.label);\n\t\t\tthis.element.appendChild(this.input);\n\t\t}\n\t\textend(InputField, Field);\n\t\tInputField.prototype.getValue = function() {\n\t\t\treturn this.input.value;\n\t\t};\n\t\t//文本框\n\t\tvar TextareaField = function(id, label) {\n\t\t\tField.call(this, id);\n\n\t\t\tthis.textarea = document.createElement('textarea');\n\t\t\tthis.content = this.textarea;\n\n\t\t\tthis.label = document.createElement('label');\n\t\t\tvar labelTextNode = document.createTextNode(label);\n\t\t\tthis.label.appendChild(labelTextNode);\n\n\t\t\tthis.element = document.createElement('div');\n\t\t\tthis.element.id = id;\n\t\t\tthis.element.className = 'input-field';\n\t\t\tthis.element.appendChild(this.label);\n\t\t\tthis.element.appendChild(this.textarea);\n\t\t};\n\t\textend(TextareaField, Field);\n\t\tTextareaField.prototype.getValue = function() {\n\t\t\treturn this.textarea.value;\n\t\t};\n\t\t//选择框\n\t\tvar SelectField = function(id, label) {\n\t\t\tField.call(this, id);\n\n\t\t\tthis.select = document.createElement('select');\n\t\t\tthis.select.options.add(new Option(\"sfs\", \"sfs\"));\n\t\t\tthis.select.options.add(new Option(\"111\", \"2222222222\")); //这边value会改变\n\t\t\tthis.content = this.select;\n\n\t\t\tthis.label = document.createElement('label');\n\t\t\tvar labelTextNode = document.createTextNode(label);\n\t\t\tthis.label.appendChild(labelTextNode);\n\n\t\t\tthis.element = document.createElement('div');\n\t\t\tthis.element.id = id;\n\t\t\tthis.element.className = 'input-field';\n\t\t\tthis.element.appendChild(this.label);\n\t\t\tthis.element.appendChild(this.select);\n\t\t};\n\t\textend(SelectField, Field);\n\t\tSelectField.prototype.getValue = function() {\n\t\t\treturn this.select.options[this.select.options.selectedIndex].value;\n\t\t};\n\t\t//表单域\n\t\tvar CompositeFieldset = function(id, legendText) {\n\t\t\tthis.components = {};\n\n\t\t\tthis.element = document.createElement('fieldset');\n\t\t\tthis.element.id = id;\n\n\t\t\tif (legendText) {\n\t\t\t\tthis.legend = document.createElement('legend');\n\t\t\t\tthis.legend.appendChild(document.createTextNode(legendText));\n\t\t\t\tthis.element.appendChild(this.legend);\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.add = function(child) {\n\t\t\tthis.components[child.getElement().id] = child;\n\t\t\tthis.element.appendChild(child.getElement());\n\t\t};\n\n\t\tCompositeFieldset.prototype.remove = function(child) {\n\t\t\tdelete this.components[child.getElement().id];\n\t\t};\n\n\t\tCompositeFieldset.prototype.getChild = function(id) {\n\t\t\tif (this.components[id] != undefined) {\n\t\t\t\treturn this.components[id];\n\t\t\t} else {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.save = function() {\n\t\t\tfor (var id in this.components) {\n\t\t\t\tif (!this.components.hasOwnProperty(id))\n\t\t\t\t\tcontinue;\n\t\t\t\tthis.components[id].save();\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.restore = function() {\n\t\t\tfor (var id in this.components) {\n\t\t\t\tif (!this.components.hasOwnProperty(id))\n\t\t\t\t\tcontinue;\n\t\t\t\tthis.components[id].restore();\n\t\t\t}\n\t\t};\n\n\t\tCompositeFieldset.prototype.getElement = function() {\n\t\t\treturn this.element;\n\t\t};\n\n\n\t\t//用组合模式汇合起来\n\t\tvar contactForm = new CompositeForm('contact-form', 'POST', 'test');\n\n\t\tvar nameFieldset = new CompositeFieldset('name-fieldset');\n\t\tnameFieldset.add(new InputField('first-name', 'First Name'));\n\t\tnameFieldset.add(new InputField('last-name', 'Last Name'));\n\t\tcontactForm.add(nameFieldset);\n\n\t\tvar addressFieldset = new CompositeFieldset('address-fieldset');\n\t\taddressFieldset.add(new InputField('address', 'Address'));\n\t\taddressFieldset.add(new InputField('city', 'City'));\n\t\taddressFieldset.add(new SelectField('state', 'State'));\n\t\taddressFieldset.add(new InputField('zip', 'Zip'));\n\t\tcontactForm.add(addressFieldset);\n\n\t\tcontactForm.add(new TextareaField('comments', 'Comments'));\n\n\t\tdocument.body.appendChild(contactForm.getElement());\n\n\t\tfunction a() {\n\t\t\tcontactForm.save();\n\t\t}\n\n\t\tfunction b() {\n\t\t\tcontactForm.restore();\n\t\t}\n\t>/script/html

4.1 图片阅读器

演示地址: https://www.albertyy.com/2020/8/Component2.html
  图片阅读器与表单验证一样,通过汇合操作图片。
!DOCTYPE htmlhtmlheadmeta charset=\"utf-8\"title/title/headbodyinput value=\"隐藏\" type=\"button\" onclick=\"a()\" /input value=\"显示\" type=\"button\" onclick=\"b()\" //bodyscript type=\"text/javascript\" 30; p++) {\n\t\t\tvacationPhotos.add(new GalleryImage('img/3.jpg'));\n\t\t}\n\t\ttopGallery.add(vacationPhotos);\n\t\tdocument.body.appendChild(topGallery.getElement());\n\n\t\tfunction a() {\n\t\t\ttopGallery.hide();\n\t\t}\n\n\t\tfunction b() {\n\t\t\ttopGallery.show();\n\t\t}\n\t>/script/html
<html>  <head>    <meta charset="utf-8">    <title>组合模式实例应用:公众号AlbertYangtitle>  head>  <body>    <input value="隐藏" type="button" onclick="a()" />    <input value="显示" type="button" onclick="b()" />  body>  <script type="text/javascript">    //图片库    var DynamicGallery = function(id) {      this.children = [];      this.element = document.createElement('div');      this.element.id = id;      this.element.className = 'dynamic-gallery';    };    DynamicGallery.prototype = {      add: function(child) {        this.children.push(child);        this.element.appendChild(child.getElement());      },      remove: function(child) {        for (var node, i = 0; node = this.getChild(i); i++) {          if (node == child) {            this.children.splice(i, 1);            break;          }        }        this.element.removeChild(chld.getElement());      },      getChild: function(i) {        return this.children[i];      },      hide: function() {        for (var i = 0, node; node = this.getChild(i); i++) {          node.hide();        }        this.element.style.display = 'none';      },      show: function() {        this.element.style.display = 'block';        for (var i = 0, node; node = this.getChild(i); i++) {          node.show();        }      },      getElement: function() {        return this.element;      }    };    //单个图片    var GalleryImage = function(src) {      this.element = document.createElement('img');      this.element.className = 'gallery-image';      this.element.src = src;    };    GalleryImage.prototype = {      add: function() {},      remove: function() {},      getChild: function() {},      hide: function() {        this.element.style.display = 'none';      },      show: function() {        this.element.style.display = '';      },      getElement: function() {        return this.element;      }    };    //汇合起来    var topGallery = new DynamicGallery('top-gallery');    topGallery.add(new GalleryImage('img/1.jpg'));    topGallery.add(new GalleryImage('img/2.jpg'));    topGallery.add(new GalleryImage('img/3.jpg'));    var vacationPhotos = new DynamicGallery('vacation-photos');    for (var p = 0; p < 30; p++) {      vacationPhotos.add(new GalleryImage('img/3.jpg'));    }    topGallery.add(vacationPhotos);    document.body.appendChild(topGallery.getElement());    function a() {      topGallery.hide();    }    function b() {      topGallery.show();    }script>html>
!DOCTYPE htmlhtmlheadmeta charset=\"utf-8\"title/title/headbodyinput value=\"隐藏\" type=\"button\" onclick=\"a()\" /input value=\"显示\" type=\"button\" onclick=\"b()\" //bodyscript type=\"text/javascript\" 30; p++) {\n\t\t\tvacationPhotos.add(new GalleryImage('img/3.jpg'));\n\t\t}\n\t\ttopGallery.add(vacationPhotos);\n\t\tdocument.body.appendChild(topGallery.getElement());\n\n\t\tfunction a() {\n\t\t\ttopGallery.hide();\n\t\t}\n\n\t\tfunction b() {\n\t\t\ttopGallery.show();\n\t\t}\n\t>/script/html

5 总结

组合模式通过简单的操作就能达到复杂的效果,一个操作通过遍历递归传递这个操作。不过组合模式的弱点也在于此,如果层次过多,则性能将受到影响。 组合模式应用需要符合两个条件,一是产生递归,二是具有相同的动作。 今天的学习就到这里,你可以使用今天学习的技巧来改善一下你曾经的代码,如果想继续提高,欢迎关注我,每天学习进步一点点,就是领先的开始。如果觉得本文对你有帮助的话,欢迎赞赏,点赞,转发!!!

36c9e2b9d4ddce6cf32fb1169ac17518.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值