JavaScript 设计模式之组合模式

news2024/12/26 23:06:26

组合模式

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

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()

效果

总结 

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

05_i2c_controller内核模块

01_basicLinux内核模块-CSDN博客文章浏览阅读304次&#xff0c;点赞3次&#xff0c;收藏3次。环境IDubuntuMakefilemodules:clean:basic.creturn 0;运行效果。https://blog.csdn.net/m0_37132481/article/details/136157384i2c_controller.c rootT:/media/sf_D_DRIVE/kmodule/…

书生·浦语大模型实战营第五节课作业

基础作业 本地部署300字的小故事在这里插入图片描述

Easyx的学习1

使用easys的相关函数需要包含头文件#include<easyx.h>或#include<graphics.h>&#xff08;#include<graphics.h>包含了<easyx.h>和一些不推荐使用的函数&#xff09; 目录 窗口创建背景颜色 基本图形绘制 1.点 2.线 3.矩形 圆角矩形 4. 圆形 椭圆…

一文彻底搞懂Java对象什么时候被垃圾器回收

文章目录 1. 简介2. 引用计数法2.1 优点2.2 缺点 3. 可达性分析算法3.1 虚拟机栈&#xff08;栈帧中的本地变量表&#xff09;中引用的对象3.2 方法区中静态属性引用的对象3.3 方法区中常量引用的对象3.4 本地方法栈中 JNI&#xff08;即一般说的 Native 方法&#xff09;引用的…

Day23--learning English

一、积累 1.straw 2.umami | tangy | bland 3.lactose dairy 4.fatigue 5.stumble | curb 6.pore 7.toll 8.arrear 9.robe 10.stylish 11.dash 12.mischief 13.ranch 14.sponsorship 15.podcast 16.villian 17.clutch 18.envision 二、练习 1.牛津原译 1.straw /strɔː/ 1…

ngnix网站服务详解

一 Nginx的简介 1 Nginx&#xff1a; ①Nginx 是开源、高性能、高可靠的 Web 和反向代理服务器&#xff0c;而且支持热部署&#xff0c;几乎可以做到 7 * 24 小时不间断运行&#xff0c;即使运行几个月也不需要重新启动&#xff0c;还能在不间断服务的情况下对软件版本进行热…

11 个适用于 Windows电脑的最佳免费录制屏幕软件(2024)

屏幕录制软件可让您捕获屏幕以与他人共享并创建与产品相关的视频、教程、课程、演示、网络视频等。该软件使您能够从网络摄像头和屏幕录制视频。 11 个适用于 Windows电脑的最佳免费屏幕录像机 以下是精心挑选的顶级屏幕录像机列表&#xff0c;及其受欢迎的功能和网站链接。该…

Spring Boot与Feign:微服务架构下的优雅通信

1. 前言 本文将详细介绍在Spring Boot框架中如何使用Feign进行微服务之间的优雅通信。我们将从Feign的基本原理讲起&#xff0c;然后逐步展开使用Feign的完整流程和步骤&#xff0c;包括代码示例和详细注释。通过本文&#xff0c;读者将能够轻松掌握Feign在Spring Boot微服务架…

为什么发明个红黑树,这么设计的意义是什么?

1、红黑树是一种自平衡二叉树&#xff0c;查找时算法时间复杂度为O(log n)。 2、 假设你计算机里存有十亿个身份证信息&#xff0c;你要用计算机在这些身份证信息里进行增加、删除、查找等操作&#xff0c;应该怎样设计程序实现这些功能&#xff1f; 最简单的笨办法&#xf…

基于JAVA的智慧社区业务综合平台 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 业务类型模块2.2 基础业务模块2.3 预约业务模块2.4 反馈管理模块2.5 社区新闻模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 业务类型表3.2.2 基础业务表3.2.3 预约业务表3.2.4 反馈表3.2.5 社区新闻表 四、系统展…

超详细shell脚本小练...

1 、判断当前磁盘剩余空间是否有30G&#xff0c;如果小于30G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查-次磁盘剩余空间。 1.1.安装邮件服务 [rootnode ~]# df -m 文件系统 1M-块 已用 可用 已用% 挂载点 devtmpfs 7…

el-button 选择与非选择按钮批量处理

el-button 选择与非选择按钮批量处理 <el-button v-for"(voyage,i) in data[voyages][nowVoyage]":key"i"class"c-work-bts"type"primary":plain"nowWorkSpace!i"click"chooseWorkSpace(i)"size"small&qu…

week04day01(爬虫)

一. 爬虫 只爬取公开的信息&#xff0c;不能爬取未公开的后台数据 1.爬虫的合法性 法无禁止皆可为 -- 属于法律的灰色地带https://www.tencent.com/robots.txt -- 网站/robots.txt 可以查看禁止爬取的内容 2. URL Uniform Resource Locator 统一资源定位符https://www.…

小程序红包服务端请求一直是签名错误如何解决

当小程序红包服务端请求一直显示签名错误时&#xff0c;这可能是由于多种原因导致的&#xff0c;包括密钥错误、参数错误、签名算法错误、时间戳问题以及网络请求问题等。解决这个问题需要细心检查和分析&#xff0c;下面将简单的介绍一下如何针对这些可能的原因进行排查和解决…

获批上市:国产新一代长期型超小人工心脏

文章来源&#xff1a;心未来&#xff1b;编辑&#xff1a;白晓菲 近日&#xff0c;重庆永仁心医疗器械有限公司&#xff08;简称&#xff1a;"永仁心医疗"&#xff09;的新一代人工心脏产品EVA-Pulsar™左心室辅助装置正式获得NMPA医疗器械注册证&#xff0c;成为国…

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

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

(二十)springboot实战——springboot使用redis的订阅发布机制结合SSE实现站内信的功能

前言 在前面的章节内容中&#xff0c;我们介绍了如何使用springboot项目实现基于redis订阅发布机制实现消息的收发&#xff0c;同时也介绍了基于SSE机制的单通道消息推送案例&#xff0c;本节内容结合redis和sse实现一个常用的实战案例——站内信。实现系统消息的实时推送。 …

【C++】 类与对象——流操作符重载,const成员函数

类与对象 流操作符重载1 << 重载2 >> 重载 const 修饰Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读&#xff01;&#xff01;&#xff01;下一篇文章见&#xff01;&#xff01;&#xff01; 流操作符重载 流操作符功能<<输出操作符>>输…

2024 AI 大模型全栈开发知识体系【LLM 技术栈】

2023 年最火的一件事莫过于以 ChatGPT 为代表的 AI 大模型的兴起与应用探索&#xff0c;这一年大模型领域可以说是百花齐放&#xff0c;很多人都惊叹其在各行各业带来的影响。 有很多人说&#xff0c;AI 相对于当年的区块链、元宇宙有过之而无不及。 甚至于 2024 年 sora 的推出…

Python学习-列表1

十二、列表1 1、创建列表及基本运算 1&#xff09;使用中括号&#xff0c;将所有准备放入列表中的元素&#xff0c;包裹起来&#xff0c;不同元素之间使用逗号分隔。 举例&#xff1a; [1,2,3,4,5]2&#xff09;列表可以容纳不同类型的数据。 举例&#xff1a; [1,2,3,4,5,…