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

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心~

说到设计模式,大家想到的就是六大原则,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.构造器模式:抽象了对象实例的变与不变(变的是属性值,不变的是属性名)

js
复制代码
// 需求:给公司员工创建线上基本信息
// 单个员工创建,可以直接使用创建
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. 工厂模式:为创建一组相关或相互依赖的对象提供一个接口,且无须指定它们的具体类

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

js
复制代码
// 需求:公司员工创建完信息后需要为每一个员工创建一个信息名片
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. 单例模式:全局只有一个实例,避免重复创建对象,优化性能

js
复制代码
// 需求:判断一款应用的开闭状态,根据不同状态给出不同提示
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. 适配器模式:适配独立模块,保证模块间的独立解耦且连接兼容

js
复制代码
// 需求:一个港行PS,需要适配插座国标
class HKDevice {
    getPlug() {
        return '港行双圆柱插头'
    }
}

class Target {
    constructor() {
        this.plug = new HKDevice()
    }
    getPlug() {
        return this.plug.getPlug() + '+港行双圆柱转换器'
    }
}

const target = new Target()
target.getPlug()

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

js
复制代码
// 说回我们之前说的为公司员工创建名片需求,现在追加需求,要给不同工龄的员工,创建不同的类型名片样式
//由于的工厂函数还有其他各种方法,不好直接改动原工厂函数,这时候我们可以使用装饰器模式实现
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. 代理模式:使用代理人来替代原始对象处理更专业的事情

js
复制代码
// 需求:在单例模式中,我们实现了应用状态的判断,现在,我们需要控制这个应用要在登录注册的情况下才能使用,可以通过代理模式,讲这个需求代理给专门拦截的对象进行判断
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. 观察者模式:当一个属性发生变化时,观察者会连续引发所有的相关状态变更

js
复制代码
// 需求:通过智能家居中心一键控制系统
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. 模版模式:在模版中,定义好每个方法的执行步骤。方法本身关注于自己的事情

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

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

js
复制代码
// 需求:游戏角色的控制
// 接受者
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()

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

作者:洪小小
链接:https://juejin.cn/post/7274146202496041018
来源:稀土掘金

结语

我是林三心

  • 一个待过小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司的作死型前端选手;
  • 一个偏前端的全干工程师;
  • 一个不正经的掘金作者;
  • 逗比的B站up主;
  • 不帅的小红书博主;
  • 喜欢打铁的篮球菜鸟;
  • 喜欢历史的乏味少年;
  • 喜欢rap的五音不全弱鸡如果你想一起学习前端,一起摸鱼,一起研究简历优化,一起研究面试进步,一起交流历史音乐篮球rap,可以来俺的摸鱼学习群哈哈,点这个,有7000多名前端小伙伴在等着一起学习哦 --> 

广州的兄弟可以约饭哦,或者约球~我负责打铁,你负责进球,谢谢~

相关推荐

  • private final、@Autowired、@Resource你更喜欢哪个?
  • Vue 已发布 v3.3.6 版本
  • 用 Python 创建词云
  • 为什么 NodeJS 是构建微服务的最佳选择?
  • 周爱民:告前端同学书
  • 万字长文助你搞懂现代网页开发中常见的10种渲染模式
  • 人手一个编程助手!北大最强代码大模型CodeShell-7B开源,性能霸榜,IDE插件全开源
  • RTX 4090也被禁售了?
  • [开源]一个低代码引擎,支持在线实时构建低码平台,支持二次开发
  • "改善标题提升图像生成": OpenAI DALL-E3 论文 精华+完整中文版
  • 1.7K Star开源无线传输利器:实现电脑和手机超大文件之间的极速共享
  • 大模型带动算力需求激增,AI基础设施如何应对新挑战?
  • 1024 程序员节全体大会官宣:院士、技术英雄齐聚,看开源如何启动 AI 新纪元!
  • 你创业的层级决定利润的天花板
  • 【美团】异步加载 JS 脚本时,async 与 defer 有何区别
  • 也看引入自我反思的大模型RAG检索增强生成框架:SELF-RAG的数据构造及基本实现思路
  • Character AI:如何把LLM变成人类想象力引擎?
  • 清华版「AutoGPT」开源,通用智能体XAgent,各种任务都能做
  • 1020.AI日报:DALL·E 3正式上线ChatGPT Plus和企业版
  • 刷到这个“没有译制片腔调的翻译”视频了么?AI可以解决!