• 前端常见的设计模式


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

    六大原则:

    • 依赖倒置原则(Dependence Inversion Principle):高层(业务层)不应该直接调用底层(基础层)模块

    • 开闭原则(Open Close Principle):单模块对拓展开放、对修改关闭

    • 单一原则(Single Responsibility Principle):单模块负责的职责必须是单一的

    • 迪米特法则(Law of Demeter):对外暴露接口应该简单

    • 接口隔离原则(Interface Segregation Principle):单个接口(类)都应该按业务隔离开

    • 里氏替换原则(Liskov Substitution Principle):子类可以替换父类

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

    • 层不直接依赖底层:依赖倒置原则

    • 部修改关闭,外部开放扩展:开闭原则

    • 合单一功能:单一原则

    • 知识接口,对外接口简单:迪米特法则

    • 合多个接口,不如隔离拆分:接口隔离原则

    • 并复用,子类可以替换父类:里氏替换原则

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

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

    前端九种设计模式 

    一、创建型

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

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

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

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

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

    1. // 需求:公司员工创建完信息后需要为每一个员工创建一个信息名片
    2. class setPerson {
    3.     constructor(obj) {
    4.         this.pesonObj = obj
    5.     }
    6.     creatCard() {
    7.         //创建信息名片
    8.     }
    9.     otherFynction(){
    10.     
    11.     }
    12. }
    13. class Person {
    14.     constructor(obj) {
    15.         return new setPerson(obj)
    16.     }
    17. }
    18. const person = new Person()
    19. const card = person.creatCard({
    20.     name:'张三',
    21.     age:'20',
    22.     department:'人力资源部门'
    23. })

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

    1. // 需求:判断一款应用的开闭状态,根据不同状态给出不同提示
    2. class applicationStation {
    3.     constructor() {
    4.         this.state = 'off'
    5.     }
    6.     play() {
    7.         if (this.state === 'on') {
    8.             console.log('已打开')
    9.             return
    10.         }
    11.         this.state = 'on'
    12.     }
    13.     shutdown() {
    14.         if (this.state === 'off') {
    15.             console.log('已关闭')
    16.             return
    17.         }
    18.         this.state = 'off'
    19.     }
    20. }
    21. window.applicationStation = new applicationStation()
    22. // applicationStation.instance = undefined
    23. // applicationStation.getInstance = function() {
    24. //    return function() {
    25. //        if (!applicationStation.instance) {  // 如果全局没有实例再创建
    26. //            applicationStation.instance = new applicationStation()
    27. //        }
    28. //        return applicationStation.instance
    29. //    }()
    30. // }
    31. // application1和application2拥有同一个applicationStation对象
    32. const application1 = window.applicationStation
    33. const application2 = window.applicationStation
    34.  

    二、结构型

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

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

    1. // 需求:一个港行PS,需要适配插座国标
    2. class HKDevice {
    3.     getPlug() {
    4.         return '港行双圆柱插头'
    5.     }
    6. }
    7. class Target {
    8.     constructor() {
    9.         this.plug = new HKDevice()
    10.     }
    11.     getPlug() {
    12.         return this.plug.getPlug() + '+港行双圆柱转换器'
    13.     }
    14. }
    15. const target = new Target()
    16. target.getPlug()

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

    1. // 说回我们之前说的为公司员工创建名片需求,现在追加需求,要给不同工龄的员工,创建不同的类型名片样式
    2. //由于的工厂函数还有其他各种方法,不好直接改动原工厂函数,这时候我们可以使用装饰器模式实现
    3. class setPerson {
    4.     constructor(obj) {
    5.         this.pesonObj = obj
    6.     }
    7.     creatCard() {
    8.         //创建信息名片
    9.     }
    10.     otherFynction(){
    11.     
    12.     }
    13. }
    14. // 追加
    15. class updatePerson {
    16.     constructor(obj) {
    17.         this.pesonObj = obj
    18.     }
    19.     creatCard() {
    20.         this.pesonObj.creatCard()
    21.         if(this.pesonObj.seniorityNum<1){
    22.                this.update(this.pesonObj)
    23.         }
    24.     }
    25.     update(pesonObj) {
    26.         //追加处理
    27.     }
    28. }
    29. const person = new setPerson()
    30. const newPerson = new updatePerson(person)
    31. newDevice.creatCard()

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

    1. // 需求:在单例模式中,我们实现了应用状态的判断,现在,我们需要控制这个应用要在登录注册的情况下才能使用,可以通过代理模式,讲这个需求代理给专门拦截的对象进行判断
    2. class applicationStation {
    3.     init() {
    4.         return 'hello'
    5.     }
    6. }
    7. class User {
    8.     constructor(loginStatus) {
    9.         this.loginStatus = loginStatus
    10.     }
    11. }
    12. class applicationStationProxy {
    13.     constructor(user) {
    14.         this.user = user
    15.     }
    16.     init() {
    17.         return this.user.loginStatus ? new applicationStation().init() : please Login
    18.     }
    19. }
    20. const user = new User(true)
    21. const userProcy = new applicationStationProxy(user)
    22. userProcy.init()

    三、行为型

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

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

    1. // 需求:通过智能家居中心一键控制系统
    2. class MediaCenter {
    3.     constructor() {
    4.         this.state = ''
    5.         this.observers = []
    6.     }
    7.     attach(observers) {
    8.         this.observers.push(observers)
    9.     }
    10.     getState() {
    11.         return this.state
    12.     }
    13.     setState(state) {
    14.         this.state = state
    15.         this.notifyAllobservers()
    16.     }
    17.     notifyAllobservers() {
    18.         this.observers.forEach(ob => {
    19.             ob.update()
    20.         })
    21.     }
    22. }
    23. class observers {
    24.     constructor(name, center) {
    25.         this.name = name
    26.         this.center = center
    27.         this.center.attach(this)
    28.     }
    29.     update() {
    30.         // 更新状态
    31.         this.center.getState()
    32.     }
    33. }

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

    1. // 需求:新员工入职,按照规定流程,进行相关培训和办理好员工相关资料
    2. class EntryPath {
    3.     constructor(obj) {
    4.        // some code
    5.     }
    6.     init() {
    7.         // 初始化员工信息
    8.     }
    9.     creatCard() {
    10.         // 创建员工名片
    11.     }
    12.     inductionTraining() {
    13.         // 入职培训
    14.     }
    15.     trainingExamination() {
    16.         // 训后测试
    17.     }
    18.     personEntry() {
    19.         this.init()
    20.         this.creatCard()
    21.         this.inductionTraining()
    22.         this.trainingExamination()
    23.     }
    24. }

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

    1. // 需求:游戏角色的控制
    2. // 接受者
    3. class Receiver {
    4.     execute() {
    5.         // 奔跑
    6.     }
    7. }
    8. // 操控者
    9. class Operator {
    10.     constructor(command) {
    11.         this.command = command
    12.     }
    13.     run() {
    14.         this.command.execute()
    15.     }
    16. }
    17. // 指令器
    18. class command {
    19.     constructor(receiver) {
    20.         this.receiver = receiver
    21.     }
    22.     execute() {
    23.         // 逻辑
    24.         this.receiver.execute()
    25.     }
    26. }
    27. const soldier = new Receiver()
    28. const order = new command(soldier)
    29. const player = new Operator(order)
    30. player.run()

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

  • 相关阅读:
    app小程序手机端Python爬虫实战04-u2自动化工具基本操作-操作设备
    Drools(8):WorkBench使用
    unity的ui怎么显示在鼠标点击位置
    前端例程20221115:文字颜色渐变效果
    洛谷P2158 欧拉函数
    天翼云Serverless边缘容器下沉服务 促进企业聚焦业务创新
    Spring MVC
    百家宴焕新上市,持续深耕100-300元价位段
    GitLab 502问题解决方案
    老绅士才懂的Wallpaper免费使用方法3.0
  • 原文地址:https://blog.csdn.net/qq_53742640/article/details/136128400