首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >修炼内功之JavaScript设计模式(三)

修炼内功之JavaScript设计模式(三)

作者头像
童欧巴
修改于 2020-05-08 09:34:12
修改于 2020-05-08 09:34:12
39600
举报
文章被收录于专栏:前端食堂前端食堂
运行总次数:0

微信搜索【前端食堂】你的前端食堂,记得按时吃饭。

本文已收录在前端食堂 Github https://github.com/Geekhyt/front-end-canteen,感谢Star。 想要成为一名优秀的软件开发人员,要具有强烈的工匠精神。遇到问题,想办法解决问题。大多数人在前期更多的依靠的是激情,中后期则需要一定的耐心。

工作时间久了,自然对软件系统产生自己的思考,还会面临职业生涯的一个挑战。要不要成为一个技术负责人?

技术负责人当然要从更大的角度来考虑问题,那么设计模式便是一门必修课,学习设计模式不仅能够在日常的业务代码中给我们提供解决问题的思路,在架构上的设计也无处不见设计模式的思想。

这是一件高收益值、长半衰期的事,值得你坚持下去。

话不多说,现在开饭!

本文所讲述的是行为型设计模式,包括模板方法模式观察者模式状态模式策略模式职责链模式命令模式访问者模式中介者模式备忘录模式迭代器模式解释器模式

1.模板方法模式 Template Method

概念:父类中定义一组操作算法骨架,而将一些实现步骤延迟到子类中,使得子类可以不改变父类的算法结构的同时可重新定义算法中某些实现步骤。

核心在于对方法的重用,将核心方法封装在基类中,让子类继承基类的方法,实现基类方法的共享,达到方法公用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class canteen {
  eat () {
    eat1();
    eat2();
    eat3();
  }
  eat1 () {
    console.log('海底捞');
  }
  eat2 () {
    console.log('日本料理');
  }
  eat3 () {
    console.log('烧烤');
  }
}

应用实例:

1、“把大象放冰箱需要三步”是一个顶层逻辑,具体实现可能因冰箱大小有所不同。

2、泡咖啡和泡茶。

3、VS CodeWebstorm等一些IDE中的模板代码片段功能。

4、蛋糕模具

2.观察者模式 Observer

概念:又被称作发布-订阅模式或消息机制,定义了一种依赖关系,解决了主体对象与观察者之间功能的耦合。

进一步说,观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

应用实例:

1.拍卖的时候,拍卖师是观察者观察最高竞价,然后通知给其他竞价者竞价。

2.在Nodejs中通过EventEmitter实现了原生的对于这一模式的支持。

3.jquery中的trigger/on

4.MVVM

5.微信公众号推送文章。

拿微信公众号来举个例子吧,你们(不同的观察者)关注了前端食堂(一个主体),当公众号文章更新时(主体更新),你们都能收到我的推送(观察者)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Subject是一个公众号主体,需要维护订阅的观察者数组。
// new Subject()创建一个新的公众号
// addObserver 添加观察者
// removeObserver 删除观察者
// inform 通知观察者
function Subject() {
  this.observers = [];
}
Subject.prototype.addObserver = function (observer) {
  this.observers.push(observer);
}
Subject.prototype.removeObserver = function (observer) {
  let index = this.observers.indexOf(observer);
  if (index > -1) {
    this.observers.splice(index, 1);
  }
}
Subject.prototype.inForm = function () {
  this.observers.forEach(observer=>{
    observer.update();
  })
}
function Observer (name) {
  this.name = name;
  this.update = function () {
    console.log(name + 'update...');
  }
}

let subject = new Subject();
let observer1 = new Observer('fans1');
subject.addObserver(observer1);
let observer2 = new Observer('fans2');
subject.addObserver(observer2);
subject.inForm();

// fans1 update...
// fans2 update...
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 下面是ES6的写法,感谢关注前端食堂的小婊,咳咳,小宝贝们~
class Subject {
  constructor () {
    this.observers = [];
  }
  addObserver (observer) {
    this.observers.push(observer);
  }
  removeObserver (observer) {
    let index = this.observers.indexOf(observer);
    if (index > -1) {
      this.observers.splice(index, 1);
    }
  }
  inForm () {
    this.observers.forEach(observer=> {
      observer.update();
    })
  }
}
class Observer {
  constructor (name) {
    this.name = name;
    this.update = function () {
      console.log(name + '么么...');
    }
  }
}
let subject = new Subject();
let observer1 = new Observer('baby1');
subject.addObserver(observer1);
let observer2 = new Observer('baby2');
subject.addObserver(observer2);
subject.inForm();

// baby1 么么...
// baby2 么么...

3.状态模式 State

概念:当一个对象的内部状态发生改变时,会导致其行为的改变,这看起来像是改变了对象。

状态模式的目的是简化分支判断流程。

应用实例:

1.LOL中英雄技能造成的各种状态如沉默、减速、禁锢、击飞等。

2.文件上传有扫描、正在上传、暂停、上传成功、上传失败等状态。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class HappyYasuo {
  constructor () {
    this._currentState = [];
    this.states = {
      q_key () {console.log('斩钢闪')},
      w_key () {console.log('风之障壁')},
      e_key () {console.log('踏前斩')},
      r_key () {console.log('狂风绝息斩')}
    }
  }

  change (arr) {  // 更改当前动作
    this._currentState = arr;
    return this;
  }

  go () {
    console.log('触发动作');
    this._currentState.forEach(T => this.states[T] && this.states[T]());
    return this;
  }
}

new HappyYasuo()
    .change(['q_key', 'w_key'])
    .go()                      // 触发动作  斩钢闪  风之障壁
    .go()                      // 触发动作  斩钢闪  风之障壁
    .change(['e_key'])
    .go()                      // 触发动作  踏前斩

4.策略模式 Strategy

概念:将定义的一组算法封装起来,使其相互之间可以替换。封装的算法具有一定独立性,不会随客户端变化而变化。

应用实例:

1.诸葛亮的锦囊妙计,每一个锦囊就是一个策略。

2.旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ZhaoYun {
  constructor (type) {
    this.type = type;
  }
  plan () {
    if (this.type === 'first') {
      console.log('打开第一个锦囊');
    } else if (this.type === 'second') {
      console.log('打开第二个锦囊');
    } else if (this.type === 'third') {
      console.log('打开第三个锦囊');
    }
  }
}
var u1 = new ZhaoYun('first');
u1.plan();
var u2 = new ZhaoYun('second');
u2.plan();
var u3 = new ZhaoYun('third');
u3.plan();
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class FirstStep {
  plan () {
    console.log('打开第一个锦囊');
  }
}
class SecondStep {
  plan () {
    console.log('打开第二个锦囊');
  }
}
class ThirdStep {
  plan () {
    console.log('打开第三个锦囊');
  }
}

var u1 = new FirstStep();
u1.plan();
var u2 = new SecondStep();
u2.plan();
var u3 = new ThirdStep();
u3.plan();

5.职责链模式 Chain of Responsibility

概念:解决请求的发送者与请求的接受者之间的耦合,通过指责链上的多个对象对分解请求流程,实现请求在多个对象之间的传递,直到最后一个对象完成请求的处理。

应用实例:

1.JavaScript中的事件冒泡。

2.长安十二时辰中的望楼传信。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 请假审批,需要组长审批、经理审批、最后总监审批
class Action {
  constructor (name) {
    this.name = name;
    this.nextAction = null;
  }
  setNextAction (action) {
    this.nextAction = action;
  }
  handle () {
    console.log(`${this.name} 审批`)
    if (this.nextAction != null) {
      this.nextAction.handle();
    }
  }
}

let a1 = new Action('组长');
let a2 = new Action('经理');
let a3 = new Action('总监');
a1.setNextAction(a2);
a2.setNextAction(a3);
a1.handle();

6.命令模式 Command

概念:将请求与实现解耦并封装成独立对象,从而使不同的请求对客户端的实现参数化。

也就是执行命令时,将发布者和执行者分开,在中间加入命令对象,作为中转站。

应用实例:

命令模式的实例在生活中很常见,这里我们只举一个例子,留给大家想象的空间。

我们去饭店点菜(发布者),无须知道厨师的名字(执行者),只需告诉服务员即可(中转站)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 接受者 厨师
class Receiver {
  go () {
    console.log('接受者执行请求');
  }
}
// 命令对象 服务员
class Command {
  constructor (receiver) {
    this.receiver = receiver;
  }
  action () {
    console.log('命令对象->接受者->对应接口执行');
    this.recerver.go();
  }
}
// 发布者 顾客吃饭点菜
class Invoker {
  constructor (command) {
    this.command = command;
  }
  invoke () {
    console.log('发布者发布请求');
    this.command.action();
  }
}

let cook = new Receiver();
let waiter = new Command(cook);
let Diner = new Invoker(waiter);
Diner.invoke();

7.访问者模式 Visitor

概念:针对于对象结构中的元素,定义在不改变该对象的前提下访问结构中元素的新方法

访问者模式就是将数据操作和数据结构进行分离。

应用实例:

您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。

使用访问者模式,我们可以使对象拥有像数组一样的pushpopsplice方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var Visitor = (function() {
      return {
        splice: function(){
          // splice方法参数,从原参数的第二个参数开始算起
          var args = Array.prototype.splice.call(arguments, 1);
          // 对第一个参数对象执行splice方法
          return Array.prototype.splice.apply(arguments[0], args);
        },
        push: function(){
          // 强化类数组对象,使他拥有length属性
          var len = arguments[0].length || 0;
          // 添加的数据从原参数的第二个参数算起
          var args = this.splice(arguments, 1);
          // 校正length属性
          arguments[0].length = len + arguments.length - 1;
          // 对第一个参数对象执行push方法
          return Array.prototype.push.apply(arguments[0], args);
        },
        pop: function(){
          // 对第一个参数对象执行pop方法
          return Array.prototype.pop.apply(arguments[0]);
        }
      }
    })();

8.中介者模式 Mediator

概念:通过中介者对象封装一系列对象之间的交互,使对象之间不再相互引用,降低他们之间的耦合。

应用实例:

1.中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。

2.机场调度系统。

3.MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Mediator {
  constructor (a, b) {
    this.a = a;
    this.b = b;
  }
  setA () {
    let number = this.b.number;
    this.a.setNumber(number * 100);
  }
  setB () {
    let number = this.a.number;
    this.b.setNumber(number / 100);
  }
}

class A {
  constructor () {
    this.number = 0;
  }
  setNumber (num, m) {
    this.number = num;
    if (m) {
      m.setB();
    }
  }
}

class B {
  constructor () {
    this.number = 0;
  }
  setNumber (num, m) {
    this.number = num;
    if (m) {
      m.setA();
    }
  }
}

9.备忘录模式 Memento

概念:在不破坏对象的封装性的前提下,在对象之外捕获并保存该对象内部的状态以便日后对象使用或者对象恢复到以前的某个状态。

应用实例:

分页组件的时候,点击下一页获取新的数据,但是当点击上一页时,又重新获取数据,造成无谓的流量浪费,这时可以对数据进行缓存。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// Memento 备忘录对象 只供原发器使用 提供状态提取方法
var Memento = function(state){
    var _state = state;
    this.getState = function(){
        return _state;
    }
}
// Originator 原发器
var Originator = function(){
    var _state;
    this.setState = function(state){
        _state = state;
    }
    this.getState = function(){
        return _state;
    }
    // saveStateToMemento 创建一个备忘录 存储当前状态
    this.saveStateToMemento = function(){
        return new Memento(_state);
    }
    this.getStateFromMemento = function(memento){
        _state = memento.getState();
    }
}
// 负责人 负责保存备忘录 但是不能对备忘录内容进行操作或检查
var CareTaker = function(){
    var _mementoList = [];
    this.add = function(memento){
        _mementoList.push(memento);
    }
    this.get = function(index){
        return _mementoList[index];
    }
}

var originator = new Originator();
var careTaker = new CareTaker();
originator.setState("State 1");
originator.setState("State 2");
careTaker.add(originator.saveStateToMemento());
originator.setState("State 3");
careTaker.add(originator.saveStateToMemento());
originator.setState("State 4");

console.log("当前状态: " + originator.getState());
// 当前状态: State 4
originator.getStateFromMemento(careTaker.get(0));
console.log("恢复第一次保存状态: " + originator.getState());
// 恢复第一次保存状态: State 2
originator.getStateFromMemento(careTaker.get(1));
console.log("恢复第二次保存: " + originator.getState());
// 恢复第二次保存: State 3

局限性:备忘录模式对资源的消耗过大。

10.迭代器模式 Iterator

概念:在不暴露对象内部结构的同时,可以顺序地访问聚合对象内部的元素。

这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。

应用实例:

绝大部分语言内置了迭代器。

1.JavaScript的Array.prototype.forEach

2.jQuery中$.each

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$.each([1, 2, 3], function(i ,n){
  console.log('当前下标为:'+ i,'当前值为:' + n);
})
// 下标:0 当前值:1 
// 下标:1 当前值:2  
// 下标:2 当前值:3

还有ES6中的Iterator http://es6.ruanyifeng.com/#docs/iterator

11.解释器模式 Interpreter

概念:对于一种语言,给出其文法表示形式,并定义一种解释器,通过使用这些解释器来解释语言中定义的句子。

这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

应用实例:

1.编译器

2.正则表达式

参考:

《JavaScript设计模式》张容铭

微信搜索【前端食堂】你的前端食堂,记得按时吃饭。

本文已收录在前端食堂 Github https://github.com/Geekhyt/front-end-canteen,感谢Star。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端食堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
python GUI界面设计的那些事(三)
GUI程序其实和普通程序其实就是多了一个界面,而最麻烦的就是用代码实现设计的GUI界面。
叶子陪你玩
2021/04/13
2K0
python GUI界面设计的那些事(三)
python图形用户界面(四):教你实现一个简单实用的计时器
本系列课程是针对无基础的,争取用简单明了的语言来讲解,学习前需要具备基本的电脑操作能力,准备一个已安装python环境的电脑。如果觉得好可以分享转发,有问题的地方也欢迎指出,在此先行谢过。
叶子陪你玩
2020/04/08
2.5K0
python图形用户界面(四):教你实现一个简单实用的计时器
python图形用户界面:教你实现一个gif处理软件(下)
之前写过如何实现gif处理工具的案例,演示了效果和分析了实现的步骤,这篇就来讲讲具体的代码实现。
叶子陪你玩
2020/04/24
8670
python图形用户界面(一):创建第一个GUI图形用户界面
本系列课程是针对无基础的,争取用简单明了的语言来讲解,学习前需要具备基本的电脑操作能力,准备一个已安装python环境的电脑。如果觉得好可以分享转发,有问题的地方也欢迎指出,在此先行谢过。
叶子陪你玩
2020/03/19
2K0
python图形用户界面(一):创建第一个GUI图形用户界面
python图形用户界面(六):可视化给图片添加上文字
本系列课程是针对无基础的,争取用简单明了的语言来讲解,学习前需要具备基本的电脑操作能力,准备一个已安装python环境的电脑。如果觉得好可以分享转发,有问题的地方也欢迎指出,在此先行谢过。
叶子陪你玩
2020/04/08
1.7K0
python图形用户界面(六):可视化给图片添加上文字
Python 图形界面框架 PyQt5 使用指南!
使用Python开发图形界面的软件其实并不多,相对于GUI界面,可能Web方式的应用更受人欢迎。但对于像我一样对其他编程语言比如C#或WPF并不熟悉的人来说,未必不是一个好的工具。
快学Python
2021/12/13
12.6K0
Python 图形界面框架 PyQt5 使用指南!
QT Pyside2 Designer 的基本使用
QT PySide2 是一个用于 Python 编程语言的开源框架,它提供了与 QT C++ 框架的绑定,使得开发者可以使用 Python 进行跨平台的图形用户界面 (GUI) 应用程序开发。QT 是一个功能强大的跨平台应用程序开发框架,具有丰富的 GUI 组件和工具集,以及广泛的应用领域。
EXI-小洲
2023/10/16
1.2K0
QT Pyside2 Designer 的基本使用
python GUI界面设计的那些事
我们知道早期的电脑只能通过命令端输入命令运行,当时能够使用电脑的都是一些比较专业的人,他们需要记住各种各样的命令。比如查看某个路径下有哪些文件,就使用 ls 指令。
叶子陪你玩
2021/04/13
1.3K0
python GUI界面设计的那些事
python群聊工具实现(中)
这里使用的是UDP连接方式。客户端很好理解,就是先给服务端发送一个消息,之后进入主循环等待服务端发送消息过来。
叶子陪你玩
2020/05/20
6450
python GUI界面设计的那些事(二)
python 可以通过 tkinter, pyqt5或者pyside2等工具库实现界面设计。
叶子陪你玩
2021/04/13
3.8K0
python GUI界面设计的那些事(二)
设计了一个简易的Python GUI界面
设计一个支持多个招聘网站的检索,可以通过指定目标城市、检索职业和查询数量,个性化输出检索结果,尔后将结果显示在界面并保存于文档中。
luanhz
2020/03/31
2.3K0
设计了一个简易的Python GUI界面
实战|教你用Python+PyQt5制作一款视频数据下载小工具!
目前,市场上有大量 Python图形用户界面(GUI)开发框架可供选择,如wxpython 、pyqt5、Gtk、Tk等。本文将用Python结合PyQt5制作一款B站视频数据下载器,可以通过输入关键字、页码以及选择存储路径后,下载相应的数据,演示效果如下:
刘早起
2020/11/23
1.5K0
实战|教你用Python+PyQt5制作一款视频数据下载小工具!
挑战任务: PyQt5编写GUI界面
前面我们学习的OpenCV内容都是运行在命令行中的,没有界面,所以本次的拓展挑战内容便是:
CodecWang
2021/12/07
2.5K0
挑战任务: PyQt5编写GUI界面
Python制作gif生成工具,斗图再也不会输啦
在当前无表情包不会聊天的时代,怎么也不能输在表情包数量不足上啊,今天咱们就来制作一个 gif 生成工具,用来制作表情包也太好用啦
周萝卜
2021/11/08
5010
Qt Designer快速入门(python GUI 可视化界面搭建)
Qt designer入门指导,这个主要用来辅助设计界面的,生成的ui文件还是要转成py文件拿到pycharm等编辑器继续开发的。
超级小可爱
2023/02/23
3.6K0
python qtdesigner 拖拽工具
在PyQt中编写UI界面可以直接通过代码来实现,也可以通过Qt Designer来完成。Qt Designer的设计符合MVC的架构,其实现了视图和逻辑的分离,从而实现了开发的便捷。Qt Designer中的操作方式十分灵活,其通过拖拽的方式放置控件可以随时查看控件效果。Qt Designer生成的.ui文件(实质上是XML格式的文件)也可以通过pyuic5工具转换成.py文件。 Qt Designer随PyQt5-tools包一起安装,其安装路径在 “Python安装路径\Lib\site-packages\pyqt5-tools”下。 若要启动Qt Designer可以直接到上述目录下,双击designer.exe打开Qt Designer;或将上述路径加入环境变量,在命令行输入designer打开;或在PyCharm中将其配置为外部工具打开。 下面以PyCharm为例,讲述PyCharm中Qt Designer的配置方法。
用户5760343
2019/07/05
2.7K0
用Python做一个“以图搜番“的应用程序,再也不用愁动漫图片的出处了!
喜欢看动漫的朋友们大概都能体会到一个难受的事情,就是在论坛或者群聊里面看到一张动漫截图,很想知道它的出处,但百度搜了一圈却也没有一个可靠结果,就很郁闷。今天就来带大家用Python做一个简单的“以图搜番”小应用。应用本身的实现不是很难的事情,其实就是调用别人的API接口来实现,主要目的还是通过这个案例来学习以下内容:
全栈程序员站长
2022/11/07
2.8K0
基于PySide6的GUI程序开发全流程(看完就会)
GUI程序的开发方式太多了,这里肯定就是Python语言了,至于为什么,就不多描述了;
MinChess
2023/09/29
18.6K0
基于PySide6的GUI程序开发全流程(看完就会)
在pycharm中使用tensorflow_使用中是什么意思
在PyQt中编写UI界面可以直接通过代码来实现,也可以通过Qt Designer来完成。Qt Designer的设计符合MVC的架构,其实现了视图和逻辑的分离,从而实现了开发的便捷。Qt Designer中的操作方式十分灵活,其通过拖拽的方式放置控件可以随时查看控件效果。Qt Designer生成的.ui文件(实质上是XML格式的文件)也可以通过pyuic5工具转换成.py文件。 Qt Designer随PyQt5-tools包一起安装,其安装路径在 “Python安装路径\Lib\site-packages\pyqt5-tools”下。 若要启动Qt Designer可以直接到上述目录下,双击designer.exe打开Qt Designer;或将上述路径加入环境变量,在命令行输入designer打开;或在PyCharm中将其配置为外部工具打开。 下面以PyCharm为例,讲述PyCharm中Qt Designer的配置方法。
全栈程序员站长
2022/09/27
5.2K0
Python GUI编程:如何运行第一个PySide2的窗体程序
上一章节介绍了PySide2的安装以及如何去启动程序进行页面设计,并且将工具集成到pycharm的扩展工具中去,有2个地方写的不对,用的是pyuic工具,需要改一下,改成pyside2-uic.exe。具体改动点:
小博测试成长之路
2021/07/29
1.1K0
推荐阅读
相关推荐
python GUI界面设计的那些事(三)
更多 >
LV.0
这个人很懒,什么都没有留下~
目录
  • 1.模板方法模式 Template Method
  • 2.观察者模式 Observer
  • 3.状态模式 State
  • 4.策略模式 Strategy
  • 5.职责链模式 Chain of Responsibility
  • 6.命令模式 Command
  • 7.访问者模式 Visitor
  • 8.中介者模式 Mediator
  • 9.备忘录模式 Memento
  • 10.迭代器模式 Iterator
  • 11.解释器模式 Interpreter
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档