当前位置: 首页 > news >正文

浅谈前端出现率高的设计模式

目录

六大原则:

23 种设计模式分为“创建型”、“行为型”和“结构型”

前端九种设计模式

一、创建型

1.构造器模式:抽象了对象实例的变与不变(变的是属性值,不变的是属性名)

2. 工厂模式:为创建一组相关或相互依赖的对象提供一个接口,且无须指定它们的具体类

3. 单例模式:全局只有一个实例,避免重复创建对象,优化性能

二、结构型

1. 适配器模式:适配独立模块,保证模块间的独立解耦且连接兼容

2. 装饰器模式:动态将责任附加到对象之上

3. 代理模式:使用代理人来替代原始对象处理更专业的事情

三、行为型

1. 观察者模式:当一个属性发生变化时,观察者会连续引发所有的相关状态变更

2. 模版模式:在模版中,定义好每个方法的执行步骤。方法本身关注于自己的事情

3. 命令模式:请求以指令的形式包裹在对象中,并传给调用对象

最后


        说到设计模式,大家想到的就是六大原则,23种模式。这么多模式,并非都要记住,但作为前端开发,对于前端出现率高的设计模式还是有必要了解并掌握的,浅浅掌握9种模式后,整理了这份文章。

        那么,我们先了解六大原则

六大原则:

  • 依赖倒置原则(Dependence Inversion Principle):高层(业务层)不应该直接调用底层(基础层)模块
  • 开闭原则(Open Close Principle):单模块对拓展开放、对修改关闭
  • 单一原则(Single Responsibility Principle):单模块负责的职责必须是单一的
  • 迪米特法则(Law of Demeter):对外暴露接口应该简单
  • 接口隔离原则(Interface Segregation Principle):单个接口(类)都应该按业务隔离开
  • 里氏替换原则(Liskov Substitution Principle):子类可以替换父类

六大原则也可以用六个字替换:高内聚低耦合。

  • 层不直接依赖底层:依赖倒置原则
  • 部修改关闭,外部开放扩展:开闭原则
  • 合单一功能:单一原则
  • 知识接口,对外接口简单:迪米特法则
  • 合多个接口,不如隔离拆分:接口隔离原则
  • 并复用,子类可以替换父类:里氏替换原则

我们采用模式编写时,要尽可能遵守这六大原则

23 种设计模式分为“创建型”、“行为型”和“结构型”

image.png

前端九种设计模式

image.png

一、创建型

创建型从功能上来说就是创建元素,目标是规范元素创建步骤

1.构造器模式:抽象了对象实例的变与不变(变的是属性值,不变的是属性名)

// 需求:给公司员工创建线上基本信息 
// 单个员工创建,可以直接使用创建 
const obj = { name:'张三', age:'20', department:'人力资源部门' 
} 
// 可员工的数量过于多的时候,一个个创建不可行,那么就可以使用构造器模式 
class Person { constructor(obj){this.name = obj.name this.age = obj.age this.department = obj.department } 
} 
const person1 = new Person(obj)

2. 工厂模式:为创建一组相关或相互依赖的对象提供一个接口,且无须指定它们的具体类

即隐藏创建过程、暴露共同接口。

// 需求:公司员工创建完信息后需要为每一个员工创建一个信息名片 
class setPerson { constructor(obj) { this.pesonObj = obj } creatCard() { //创建信息名片 } otherFynction(){ } 
} 
class Person { constructor(obj) { return new setPerson(obj) } 
} 
const person = new Person() 
const card = person.creatCard({ name:'张三', age:'20', department:'人力资源部门' 
})

3. 单例模式:全局只有一个实例,避免重复创建对象,优化性能

// 需求:判断一款应用的开闭状态,根据不同状态给出不同提示 
class applicationStation { constructor() { this.state = 'off' } play() { if (this.state === 'on') { console.log('已打开') return } this.state = 'on' } shutdown() { if (this.state === 'off') { console.log('已关闭') return } this.state = 'off' } 
} 
window.applicationStation = new applicationStation() 
// applicationStation.instance = undefined 
// applicationStation.getInstance = function() { // return function() { // if (!applicationStation.instance) { // 如果全局没有实例再创建 // applicationStation.instance = new applicationStation() // } // return applicationStation.instance // }() 
// } 
// application1和application2拥有同一个applicationStation对象 
const application1 = window.applicationStation 
const application2 = window.applicationStation

二、结构型

结构型从功能上来说就是给元素添加行为的,目标是优化结构的实现方式

1. 适配器模式:适配独立模块,保证模块间的独立解耦且连接兼容

// 需求:一个港行PS,需要适配插座国标 
class HKDevice { getPlug() { return '港行双圆柱插头' } 
} 
class Target { constructor() { this.plug = new HKDevice() } getPlug() { return this.plug.getPlug() + '+港行双圆柱转换器' } 
} 
const target = new Target() 
target.getPlug()

2. 装饰器模式:动态将责任附加到对象之上

// 说回我们之前说的为公司员工创建名片需求,现在追加需求,要给不同工龄的员工,创建不同的类型名片样式
//由于的工厂函数还有其他各种方法,不好直接改动原工厂函数,这时候我们可以使用装饰器模式实现
class setPerson {constructor(obj) {this.pesonObj = obj;}creatCard() {//创建信息名片}otherFynction() {}
}
// 追加
class updatePerson {constructor(obj) {this.pesonObj = obj;}creatCard() {this.pesonObj.creatCard();if (this.pesonObj.seniorityNum < 1) {this.update(this.pesonObj);}}update(pesonObj) {//追加处理}
}
const person = new setPerson();
const newPerson = new updatePerson(person);
newDevice.creatCard();

3. 代理模式:使用代理人来替代原始对象处理更专业的事情

// 需求:在单例模式中,我们实现了应用状态的判断,现在,我们需要控制这个应用要在登录注册的情况下才能使用,可以通过代理模式,讲这个需求代理给专门拦截的对象进行判断
class applicationStation {init() {return "hello";}
}
class User {constructor(loginStatus) {this.loginStatus = loginStatus;}
}
class applicationStationProxy {constructor(user) {this.user = user;}init() {return this.user.loginStatus ? new applicationStation().init() : please Login;}
}
const user = new User(true);
const userProcy = new applicationStationProxy(user);
userProcy.init();

三、行为型

不同对象之间责任的划分和算法的抽象化

1. 观察者模式:当一个属性发生变化时,观察者会连续引发所有的相关状态变更

// 需求:通过智能家居中心一键控制系统
class MediaCenter {constructor() {this.state = "";this.observers = [];}attach(observers) {this.observers.push(observers);}getState() {return this.state;}setState(state) {this.state = state;this.notifyAllobservers();}notifyAllobservers() {this.observers.forEach((ob) => {ob.update();});}
}
class observers {constructor(name, center) {this.name = name;this.center = center;this.center.attach(this);}update() {// 更新状态this.center.getState();}
}

2. 模版模式:在模版中,定义好每个方法的执行步骤。方法本身关注于自己的事情

// 需求:新员工入职,按照规定流程,进行相关培训和办理好员工相关资料
class EntryPath {constructor(obj) {// some code}init() {// 初始化员工信息}creatCard() {// 创建员工名片}inductionTraining() {// 入职培训}trainingExamination() {// 训后测试}personEntry() {this.init();this.creatCard();this.inductionTraining();this.trainingExamination();}
}

3. 命令模式:请求以指令的形式包裹在对象中,并传给调用对象

// 需求:游戏角色的控制
// 接受者
class Receiver {execute() {// 奔跑}
}
// 操控者
class Operator {constructor(command) {this.command = command;}run() {this.command.execute();}
}
// 指令器
class command {constructor(receiver) {this.receiver = receiver;}execute() {// 逻辑 this.receiver.execute()}
}
const soldier = new Receiver();
const order = new command(soldier);
const player = new Operator(order);
player.run();

最后

        很多人看了文章后提到了应用场景。本人在实际开发中遇到的场景,其实都没办法完全严格按照六大原则来设计代码。但能在认知这些设计模式的情况下,设计代码逻辑的思想往这些模式上靠。另外文中很多例子都是比较简单的,一则为了简单理解,二则复杂的不好输出。若大家有优秀的案例可以分享出来,一起交流学习,一起进步~~

相关文章:

  • linux的另一种判断符号【中括号】
  • 使用udevdm查询蓝牙模块的信息
  • K8S知识点(三)
  • Springboot学生就业信息管理系统-计算机毕设 附源码95340
  • 【C语言基础入门】二级指针、一维数组与指针、二维数组与指针
  • 软通杯算法竞赛--周赛题目(一)
  • 【微服务】mysql + elasticsearch数据双写设计与实现
  • 艺术的维度:洞察AI诈骗,优雅防范之艺术
  • C++构造函数
  • docker 下安装mysql8.0
  • ROS学习笔记(4):ROS架构和通讯机制
  • 大数据毕业设计选题推荐-热门旅游景点数据分析-Hadoop-Spark-Hive
  • 解析python爬取Ebay数据的方式
  • C#when关键字
  • uniapp写一个计算器用于记账(微信小程序,APP)
  • [LeetCode] Wiggle Sort
  • 【402天】跃迁之路——程序员高效学习方法论探索系列(实验阶段159-2018.03.14)...
  • docker-consul
  • LeetCode算法系列_0891_子序列宽度之和
  • Netty源码解析1-Buffer
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • thinkphp5.1 easywechat4 微信第三方开放平台
  • 浏览器缓存机制分析
  • 使用 @font-face
  • 说说动画卡顿的解决方案
  • 微信公众号开发小记——5.python微信红包
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • ​LeetCode解法汇总2670. 找出不同元素数目差数组
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • (9)目标检测_SSD的原理
  • (C语言)共用体union的用法举例
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (附源码)apringboot计算机专业大学生就业指南 毕业设计061355
  • (附源码)springboot 校园学生兼职系统 毕业设计 742122
  • (三十五)大数据实战——Superset可视化平台搭建
  • (四)模仿学习-完成后台管理页面查询
  • (一)Neo4j下载安装以及初次使用
  • .NET Core引入性能分析引导优化
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .net访问oracle数据库性能问题
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @RestControllerAdvice异常统一处理类失效原因
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [ 第一章] JavaScript 简史
  • [Android 13]Input系列--获取触摸窗口
  • [Excel]如何找到非固定空白格數列的條件數據? 以月份報價表單為例
  • [HTML]Web前端开发技术12(HTML5、CSS3、JavaScript )——喵喵画网页
  • [iOS]中字体样式设置 API
  • [Kubernetes]4. 借助腾讯云TKE快速创建Pod、Deployment、Service部署k8s项目
  • [Leetcode] 寻找数组的中心索引
  • [MT8766][Android12] 取消WIFI热点超过10分钟没有连接自动关闭设定
  • [NOIP2003 普及组] 乒乓球(模拟)
  • [NOSQL] Redis介绍
  • [one_demo_10]递归解决汉诺塔问题