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

目录

六大原则:

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

最后

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

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

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

相关文章

MMdetection3.x个人笔记

1.在自定义数据集用训练出的权重进行可视化推理 input(jpg文件) model_config 这两个可以不用加前面的形参 然后用 \ 隔开 写上 --weight xx.pth python demo/image_demo.py data/coco_duck/train2017/10640.jpg work_dirs/solov2_r50_fpn_1x_coco/solov2_r50_fpn_1x_coco…

ChatGPT 实际上是如何工作的?

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; ChatGPT 操作的两个主要阶段 我们再用谷歌来打个比方。当你要求谷歌查找某些内容时&#xff0c;你可能知道它不会——在你提出要求的那一刻——出去搜索整个网络来寻找答案。相反&#xff0c;谷歌会在其数…

Git extension 中合并工具kdiff3乱码问题

打开kdiff3合并工具&#xff0c;setting->region settings 设置下面的编码格式为utf-8就可以啦&#xff01; 注意&#xff1a;需要在合并工具中设置编码格式&#xff0c; 在git 中配置编码格式没有效果

LLM之Prompt(一):5个Prompt高效方法在文心一言3.5的测试对比

在Effective Prompt: 编写高质量Prompt的14个有效方法文中我们了解了14个编写Prompt的方法&#xff08;非常感谢原作者&#xff09;&#xff0c;那么这些Prompt在具体大模型中的效果如何呢&#xff1f;本文以百度文心一言3.5版本大模型在其中5个方法上做个测试对比。 第1条&am…

掌动智能:UI自动化测试工具的五大功能

在现代软件开发中&#xff0c;保证应用程序的质量和性能至关重要。UI自动化测试工具是一种关键的资源&#xff0c;它们能够有效地检查应用程序的用户界面&#xff0c;确保它们在各种情况下都能正常运行。本文将探讨UI自动化测试工具的功能有哪些! UI自动化测试工具的五大功能&a…

【SQL篇】一、Flink动态表与流的关系以及DDL语法

文章目录 1、启动SQL客户端2、SQL客户端常用配置3、动态表和持续查询4、将流转为动态表5、用SQL持续查询6、动态表转为流7、时间属性8、DDL-数据库相关9、DDL-表相关 1、启动SQL客户端 启动Flink&#xff08;基于yarn-session模式为例&#xff09;&#xff1a; /opt/module/f…

全自动批量AI改写文章发布软件【软件脚本+技术教程】

项目原理&#xff1a; 利用AI工具将爆款文章改写发布到平台上流量变现,通过播放量赚取收益 软件功能&#xff1a; 1.可以根据你选的文章领域&#xff0c;识别你在网站上抓取的文章链接进来自动洗稿生成过原创的文章&#xff0c;自动配图 2.同时还可以将管理的账号导入进脚本软…

oracle体系结构

oracle数据库主要有三种文件: control,log,dbf文件。 oracle实例是oracle内存和进程的统称。一个数据库一般对应一个实例。 多个实例对用一个数据库就是oracle的rac技术。 这样比如有100个用户连接数据库&#xff0c;可以让50个用户连接实例1&#xff0c; 另外50个用户连接用…

Filter 和 Listener

Filter 表示过滤器。是JavaWeb三大组件&#xff08;Servlet、Filter、Listener&#xff09;之一。 过滤器可以把对资源的请求 拦截 下来。浏览器可以访问服务器上所有的资源&#xff0c;而在访问到这些资源之前可以使用过滤器拦截下来&#xff0c;也就是说在访问资源之前会先经…

Android性能优化--Perfetto用SQL性能分析

Android性能优化–Perfetto用SQL性能分析 文章目录 Android性能优化--Perfetto用SQL性能分析介绍Perfetto SQL 基础使用 Perfetto SQL 进行性能分析总结 本文首发地址 https://blog.csdn.net/CSqingchen/article/details/134167741 最新更新地址 https://gitee.com/chenjim/che…

什么是本地存储的有效期?

前言 本地存储是一种在Web开发中常用的客户端存储数据的方式&#xff0c;它可以让网页应用程序在用户的浏览器中存储和检索数据&#xff0c;而无需依赖服务器来保存信息。本地存储的有效期是指数据存储在用户的设备上可以被访问和保留的时间段。在本地存储中&#xff0c;有两种…

嵌入式发展历史

MPU、MCU、SoC、Application Processors 在一个电子系统中&#xff0c;处理器占据最重要的位置&#xff0c;被称为中央处理器单元&#xff08;CPU&#xff1a;Central Processing Unit&#xff09;。它从IO设备读取数据&#xff0c;处理&#xff0c;然后输出。 CPU的发展历史…

【RabbitMQ】RabbitMQ 消息的可靠性 —— 生产者和消费者消息的确认,消息的持久化以及消费失败的重试机制

文章目录 前言&#xff1a;消息的可靠性问题一、生产者消息的确认1.1 生产者确认机制1.2 实现生产者消息的确认1.3 验证生产者消息的确认 二、消息的持久化2.1 演示消息的丢失2.2 声明持久化的交换机和队列2.3 发送持久化的消息 三、消费者消息的确认3.1 配置消费者消息确认3.2…

系统设计中的缓存技术:完整指南

Image.png 缓存是软件工程中用于提高系统性能和用户体验的基本技术。它通过临时存储频繁访问的数据在缓存中&#xff0c;缓存比数据的原始来源更容易访问。 作为一名软件工程师&#xff0c;了解缓存以及它在不同类型的系统中的工作方式是至关重要的。在本文中&#xff0c;我们将…

基于AOSP源码Android-10.0.0_r41分支编译,framework开发,修改系统默认字体大小

文章目录 基于AOSP源码Android-10.0.0_r41分支编译&#xff0c;framework开发&#xff0c;修改系统默认字体大小 基于AOSP源码Android-10.0.0_r41分支编译&#xff0c;framework开发&#xff0c;修改系统默认字体大小 主要修改一个地方就行 代码源码路径 frameworks/base/co…

旅游业为什么要选择VR全景,VR全景在景区旅游上有哪些应用

引言&#xff1a; VR全景技术的引入为旅游业带来了一场变革。这项先进技术不仅提供了前所未有的互动体验&#xff0c;还为景区旅游文化注入了新的生机。 一&#xff0e;VR全景技术&#xff1a;革新旅游体验 1.什么是VR全景技术&#xff1f; VR全景技术是一种虚拟现实技术&am…

【C++初阶(四)aoto关键字与基于范围的for循环】

本专栏内容为&#xff1a;C学习专栏&#xff0c;分为初阶和进阶两部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握C。 &#x1f493;博主csdn个人主页&#xff1a;小小unicorn ⏩专栏分类&#xff1a;C &#x1f69a;代码仓库&#xff1a;小小unicorn的代码仓库&…

python实现MC协议(SLMP 3E帧)的TCP服务端(篇二)

python实现MC协议&#xff08;SLMP 3E帧&#xff09;的TCP服务端是一件稍微麻烦点的事情。它不像modbusTCP那样&#xff0c;可以使用现成的pymodbus模块去实现。但是&#xff0c;我们可以根据协议帧进行组包&#xff0c;自己去实现帧的格式&#xff0c;而这一切可以基于socket模…

Kotlin 进阶函数式编程技巧

Kotlin 进阶函数式编程技巧 Kotlin 简介 软件开发环境不断变化&#xff0c;要求开发人员不仅适应&#xff0c;更要进化。Kotlin 以其简洁的语法和强大的功能迅速成为许多人进化过程中的信赖伙伴。虽然 Kotlin 的初始吸引力可能是它的简洁语法和与 Java 的互操作性&#xff0c…

每天一点python——day61

#第61天 #字符串的驻留机制字符串&#xff1a;python中基本数据类型&#xff0c;是一个不可变的序列【目前我们学了两个&#xff1a;元组、字符串】 可以使用单引号&#xff0c;双引号&#xff0c;三引号来定义#定义字符串 apython#用单引号&#xff0c;双引号&#xff0c;三引…