JavaScript 设计模式之组合模式

组合模式

在我们日常中肯呢个会将一个表单用这种模式来创建

const Car = function () { }
Car.prototype.getName = function () { 
  throw new Error("需要重写该方法")
}
Car.prototype.getPrice = function () {
  throw new Error("需要重写该方法")
}
const Benz = function () { }
// 继承Car
Benz.prototype = new Car()
// 重写getName方法
Benz.prototype.getName = function () {
  return 'Benz'
}
const b = new Benz()
console.log(b.getName()) // Benz
console.log(b.getPrice()) // 需要重写该方法

先写一个基类,再继承该基类

const Benz = function (name, price) {
  Car.call(this)
  this.name = name
  this.price = price
}
Benz.prototype = new Car
Benz.prototype.getPrice = function () {
  return this.price
}
Benz.prototype.getName = function () {
  return this.name
}
const benz = new Benz('奔驰', 50)
console.log(benz.getName()) // 输出:奔驰
console.log(benz.getPrice()) // 输出:50
const bmw = new Benz('宝马', 100)
console.log(bmw.getPrice()) // 输出:100

构建一个 Form 表单

首先我们创建一个基类

定义


const Base = function () { 
  this.children = []
  this.element = null
}
Base.prototype = {
  init: function () {
    throw new Error('必须重写该方法')
  },
  add: function () {
    throw new Error('必须重写该方法')
  },
  remove: function () {
    throw new Error('必须重写该方法')
  },
  get: function () {
    throw new Error('必须重写该方法')
  }
}

接下来创建一个容器


const FormItem = function (id,parent) {
  Base.call(this)
  this.id = id
  this.parent = parent
  this.init()
}
FormItem.prototype = new Base()
FormItem.prototype.init = function () {
  this.element = document.querySelector('#form')
  this.element.id = this.id
}
FormItem.prototype.add = function (child) {
  this.children.push(child)
  this.element.appendChild(child.getDom())
  return this
}
FormItem.prototype.getDom = function () {
  return this.element
}
FormItem.prototype.show = function () { 
  this.parent.appendChild(this. Element)
}

注意,这里的 show 方法就是用来将所有的 dom 追加到页面上

下面创建一系列的 form 相关 item 及一些dom


const FieldsetItem = function (selector, label) {
  Base.call(this)
  this.selector = selector
  this.label = label
  this.init()
}
FieldsetItem.prototype = new Base()
FieldsetItem.prototype.init = function () {
  this.element = document.createElement('fieldset')
  const legend = document.createElement('legend')
  legend.innerHTML = this.label
  this.element.appendChild(legend)
}
FieldsetItem.prototype.add = function (child) {
  this.children.push(child)
  this.element.appendChild(child.getDom())
  return this
}
FieldsetItem.prototype.getDom = function () {
  return this. Element
}


const Group = function () {
  Base.call(this)
  this.init()
}
Group.prototype = new Base()
Group.prototype.init = function () {
  this.element = document.createElement('div')
  this.element.className = 'group'
}
Group.prototype.add = function (child) {
  this.children.push(child)
  this.element.appendChild(child.getDom())
  return this
}
Group.prototype.getDom = function () {
  return this.element
}

const LabelItem = function (name, label) {
  Base.call(this)
  this.name = name
  this.label = label
  this.init()
}
LabelItem.prototype = new Base()
LabelItem.prototype.init = function () {
  this.element = document.createElement('label')
  this.element.innerHTML = this.label
  this.element.htmlFor = this.name
}
LabelItem.prototype.add = function (child) {
  // 这里不需要添加,因为label后面直接跟输入框
  return this
}
LabelItem.prototype.getDom = function () {
  return this.element
}

const InputItem = function (name) {
  Base.call(this)
  this.name = name
  this.init()
}
InputItem.prototype = new Base()
InputItem.prototype.init = function () {
  this.element = document.createElement('input')
  this.element.name = this.name
  this.element.style.marginLeft = '5px'
}
InputItem.prototype.add = function (child) {
  // 这里不需要添加,因为输入框后面直接跟标签
  return this
}
InputItem.prototype.getDom = function () {
  return this.element
}

const CheckboxItem = function (name, value, label) {
  Base.call(this)
  this.name = name
  this.value = value
  this.label = label
  this.init()
}
CheckboxItem.prototype = new Base()
CheckboxItem.prototype.init = function () {
  const span = document.createElement('span')
  this.element = document.createElement('label')
  const input = document.createElement('input')
  input.type = 'checkbox'
  span.innerHTML = this.label
  input.value = this.value
  input.style.marginRight = '5px'
  this.element.appendChild(input)
  this.element.appendChild(span)
}
CheckboxItem.prototype.add = function (child) {
}
CheckboxItem.prototype.getDom = function () {
  return this.element
}

const SpanItem = function (name) {
  Base.call(this)
  this.name = name
  this.init()
}
SpanItem.prototype = new Base()
SpanItem.prototype.init = function () {
  this.element = document.createElement('span')
  this.element.innerHTML = this.name
  this.element.style.marginLeft = '5px'
}
SpanItem.prototype.add = function (child) {
  // 这里不需要添加,因为span前面直接跟输入框
  return this
}
SpanItem.prototype.getDom = function () {
  return this. Element
}

使用 

假使页面中存在 dom 

 <form id="form"></form>
 <div id="content"></div>

js

var form = new FormItem('form', document.querySelector('#content'))
form.add(new FieldsetItem('account', '账号').add(
  new Group().add(
    new LabelItem('user_name', '用户名:')
  ).add(
    new InputItem('user_name')
  ).add(new SpanItem('4 到 6 位数字或字母'))
).add(
  new Group().add(
    new LabelItem('user_pwd', '密&emsp;码:')
  ).add(
    new InputItem('user_pwd')
  ).add(new SpanItem('6 到 12 位数字或字母'))
).add(
  new Group().add(
    new CheckboxItem('remember', true, '是否记住')
  )
))
  .show()

效果

总结 

组合模式能够给我们提供一个清晰的组成结构。组合对象类通过继承同一个父类使其具有统一的方法,这样也方便了我们统一管理与使用,当然此时单体成员与组合体成员行为表现就比较一致了,这也模糊了简单对象与组合对象的区别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/399321.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

K8S临时小结

k8s是什么&#xff1f;能解决什么问题&#xff1f; k8s是容器管理平台&#xff0c;一套复杂的开源系统 如何更好的维护pod&#xff0c;k8s第二大要素&#xff08;pod控制器&#xff09; k8s的很多对容器&#xff08;pod&#xff09;管理的高级特性&#xff0c;都是基于控制器…

HarmonyOS—@Observed装饰器和@ObjectLink嵌套类对象属性变化

Observed装饰器和ObjectLink装饰器&#xff1a;嵌套类对象属性变化 概述 ObjectLink和Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步&#xff1a; 被Observed装饰的类&#xff0c;可以被观察到属性的变化&#xff1b;子组件中ObjectLink装饰器装饰的状…

HCIA-HarmonyOS设备开发认证V2.0-IOT硬件子系统-GPIO

目录 一、GPIO 概述二、GPIO模块相关API三、实例四、GPIO HDF驱动开发4.1、LED驱动程序(待续...)4.2、LED驱动配置(待续...) 坚持就有收获 轻量系统设备通常需要进行外设控制&#xff0c;例如温湿度数据的采集、灯开关的控制&#xff0c;因此在完成内核开发后&#xff0c;需要进…

Rancher实用篇-使用rancher,部署微服务应用

说到rancher&#xff0c;我们必须先了解一下k8s 一、k8s简介 Kubernetes&#xff08;通常简写为 K8s&#xff09;是一个开源的容器管理系统&#xff0c;由Google于2014年发起&#xff0c;并在2015年贡献给Cloud Native Computing Foundation (CNCF)进行维护。它基于Borg项目的…

app逆向-平头哥框架ratel使用

文章目录 一、前言二、实现逻辑1、安装ratel手机端app2、使⽤电脑端进⾏感染目标app3、开发⼀个平头哥插件 一、前言 平头哥&#xff08;ratel&#xff09;是⼀个Android逆向分析⼯具套件&#xff0c;他提供⼀系列渐进式app逆向分析⼯具。同时平头哥也是⼀个app⼆次开发的沙箱…

从0到1的私域流量体系搭建,私域操盘手的底层认知升级

一、教程描述 本套私域操盘手教程&#xff0c;大小4.31G&#xff0c;共有12个文件。 二、教程目录 01第一课、私域能力必修&#xff1a;私域大神熟记于心的高阶私域体系.mp4 02第二课、私域IP打造&#xff1a;那些忍不住靠近的私域IP如何打造的.mp4 03第三课、朋友圈经济&…

秦岭天台山隧道群荣获交通运输部科技示范工程,恒星科通群载波应急广播与无线调度系统产品应用其中

2023年9月12日&#xff0c;全国交通运输科技示范工程现场推进会在河南省平顶山市召开&#xff0c;会上为全国已通过验收的10项科技示范工程进行了授牌&#xff0c;其中由陕西交控集团负责实施的“秦岭天台山超长隧道群安全绿色科技示范工程”名列其中。 该科技示范工程为陕西省…

共享WiFi贴是什么,究竟安不安全?

在现代社会中&#xff0c;移动设备和互联网已经成为我们日常生活中不可或缺的一部分。为了方便我们的网络使用&#xff0c;越来越多的人选择使用公共WiFi&#xff0c;但是安全性成了很大的问题。而随着共享WiFi贴的出现&#xff0c;我们是否可以更加安全便捷地使用WiFi呢&#…

不会这个小技巧,你敢说你会零售营销?

新零售模式是随着科技的不断发展而崭露头角的商业模式之一&#xff0c;其核心理念在于将线上线下融合&#xff0c;通过智能技术提升购物体验和效率。 自动售货机作为新零售模式中的一种典型体现&#xff0c;通过数字化、自动化的手段&#xff0c;为消费者提供更为便捷、个性化的…

【C++】C++11下线程库

C11下线程库 1. thread类的简单介绍2.线程函数参数3.原子性操作库(atomic)4.mutex的种类5. RAII风格加锁解锁5.1Lock_guard5.2unique_lock 6.condition_variable 1. thread类的简单介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如wi…

代码随想录算法训练营29期|day56 任务以及具体安排

第九章 动态规划part13 300.最长递增子序列 class Solution {public int lengthOfLIS(int[] nums) {int[] dp new int[nums.length];int res 0;Arrays.fill(dp, 1);for (int i 1; i < dp.length; i) {for (int j 0; j < i; j) {if (nums[i] > nums[j]) {dp[i] Ma…

【C语言】面试常考----- 内存函数memcpy和memmove的功能区别与模拟实现

1.memcpy 功能&#xff1a;把source指向的前num个字节内容拷贝到destination指向的位置去&#xff0c;可以拷贝任意类型的数据。 注&#xff1a;1.memcpy并不关心\0&#xff0c;毕竟传的也不一定是字符串&#xff0c;因此拷贝过程中遇到\0也不会停下来。 2.num的单位是字节&a…

正大国际期货:银行再掀“压岁钱”争夺战 儿童金融服务还有哪些发力空间

随着春节假期渐入尾声&#xff0c;如何打理过年期间累积的“小金库”成为家长和孩子共同关注的话题&#xff0c;不少银行瞄准这一需求针对压岁钱展开营销。2月20日&#xff0c;北京商报记者调查发现&#xff0c;多家银行通过推出专属存款产品或定制银行卡等方式吸引储户目光。 …

C# CAD交互界面-模态窗体与非模态窗体调用方式

运行环境Visual Studio 2022 c# cad2016 一、模态窗体调用方式&#xff1a; 当一个模态窗体打开时&#xff0c;它会阻塞主窗体的所有输入&#xff0c;直到关闭该模态窗体为止。例如&#xff0c;弹出一个对话框让用户必须完成某些操作后才能继续使用主程序。 [CommandMethod(&q…

击败.helper勒索病毒:恢复被加密的数据文件的方法

导言: 近年来&#xff0c;勒索病毒成为网络安全领域的一大威胁&#xff0c;其中.helper勒索病毒更是备受关注。该类型的勒索软件以其高效的加密算法&#xff0c;能够将用户的文件加密&#xff0c;迫使用户支付赎金才能解密数据。本文将介绍.helper勒索病毒的特点、恢复被加密数…

Howler.js:音频处理的轻量级解决方案

文章目录 Howler.js&#xff1a;音频处理的轻量级解决方案引言一、Howler.js简介1.1 特性概览 二、Howler.js基本使用使用详解2.1 创建一个Howl对象2.2 控制音频播放2.3 监听音频事件 三、进阶功能3.1 音频Sprites3.2 3D音频定位 四、微前端场景下的Howler.js Howler.js&#x…

51_蓝桥杯_独立按键

一 电路 注意&#xff1a;J5跳帽接到2~3引脚&#xff0c;使按键S4-S5四个按键的另外一端接地&#xff0c;从而成为4个独立按键。 二 独立按键工作原理 三 代码 代码1&#xff1a;按下S7点亮L1指示灯&#xff0c;松开按键&#xff0c;指示灯熄灭&#xff0c;按下S6点亮L2指示灯…

Java 绘图

一、坐标体系 二、快速入门&#xff08;画圆&#xff09; import javax.swing.*; import java.awt.*;SuppressWarnings({"all"}) public class DrawCircle extends JFrame { //JFrame 对应窗口,可以理解成是一个画框private MyPanel mp null; //定义一个面板pu…

Google的firebase简介

文章目录 firebase简介firebase的一些特点 firebase简介 Firebase是一项由Google提供的云服务&#xff0c;旨在帮助开发者构建高质量的应用程序。Firebase 提供了各种工具和服务&#xff0c;涵盖了应用开发的多个方面&#xff0c;包括实时数据库、认证、云存储、云函数、推送通…

stable diffusion官方版本复现

踩了一些坑&#xff0c;来记录下 环境 CentOS Linux release 7.5.1804 (Core) 服务器RTX 3090 复现流程 按照Stable Diffusion的readme下载模型权重、我下载的是stable-diffusion-v1-4 版本的 1 因为服务器没法上huggingface&#xff0c;所以得把权重下载到本地&#xff…