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

发表于 3年以前  | 总阅读数:334 次

想要成为一名优秀的软件开发人员,要具有强烈的工匠精神。遇到问题,想办法解决问题。大多数人在前期更多的依靠的是激情,中后期则需要一定的耐心。

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

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

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

话不多说,现在开饭!

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

1 模板方法模式 Template Method

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

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

class canteen {
  eat () {
    eat1();
    eat2();
    eat3();
  }
  eat1 () {
    console.log('海底捞');
  }
  eat2 () {
    console.log('日本料理');
  }
  eat3 () {
    console.log('烧烤');
  }
}

应用实例:

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

2、泡咖啡和泡茶。

3、<span style="font-size: 17px;">VS Code<span style="font-size: 17px;">Webstorm等一些IDE中的模板代码片段功能。

4、蛋糕模具

2 观察者模式 Observer

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

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

应用实例:

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

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

3.jquery中的trigger/on

4.MVVM

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

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

// 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...
// 下面是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.文件上传有扫描、正在上传、暂停、上传成功、上传失败等状态。

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.旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。

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();
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.<span style="font-size: 17px;">JavaScript中的事件冒泡。

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

// 请假审批,需要组长审批、经理审批、最后总监审批
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

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

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

应用实例:

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

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

// 接受者 厨师
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方法。

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(视图)的中介者。

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

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

应用实例:

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

// 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

$.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.正则表达式

本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/o9ziipqqEVGbxEqhJnATlA

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Java 中验证时间格式的 4 种方法 2年以前  |  3805次阅读
Java经典面试题答案解析(1-80题) 4年以前  |  3587次阅读
CentOS 配置java应用开机自动启动 4年以前  |  2755次阅读
IDEA依赖冲突分析神器—Maven Helper 4年以前  |  2743次阅读
SpringBoot 控制并发登录的人数教程 4年以前  |  2422次阅读
 目录