手写JavaScript常见5种设计模式

【javascript基础——系列6】常见的5种JavaScript设计模式;发布订阅者模式 文章目录一、常见的5种JavaScript设计模式1.1 工厂模式1.2 构造函数模式1.3 单例模式1.4 发布订阅者模式1.5 观察者模式 一、常见的5种JavaScript设计模式 工厂模式 构造函数模式 单例模式 发布订阅模式 观察者模式 1.1 工厂模式 工厂模式是创建对象的一种最常用的设计模式,不暴露创建对象的具体逻辑,而是将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂。 通过对传递参数的预定,返回不同的对象实例,但是这三种实例的内部构造都非常相似,因此还可以对其进行优化。 阅读详情

想分享的几种设计模式

目前模式:工厂模式,单例模式,适配器模式,装饰者模式,建造者模式

建造者模式

简介:建造者模式(builder pattern)比较简单,它属于创建型模式的一种。

白话:4个部分:有个产品,有个工厂可以造产品,有个设计师指挥造多少,有个人想买产品。

买产品的用户不介意产品制造流程,只需要产品!

function Cola() {
    this.sugar = '50g',
    this.water = '100g'
}
function Packing() { // 第一种打包方式
    this.createPkg = function(){
        console.log('创建可乐外皮')
    }
    this.pushCola = function() {
        console.log('可乐倒进瓶子')
    }
    this.complete = function() {
        var cola = new Cola()
        cola.complete = true
        return cola
    }
    this.init = function() {
        this.createPkg() // 创建外皮
        this.pushCola() // 倒进瓶子
        //还可以增加其他步骤
        return this.complete() // 制作完成
    }
}
function greenPacking() { //绿皮可乐打包方式
    this.createPkg = function(){
        console.log('创建green可乐外皮')
    }
    this.pushCola = function() {
        console.log('可乐倒进green瓶子')
    }
    this.complete = function() {
        var cola = new Cola()
        cola.complete = true
        return cola
    }
    this.init = function() {
        this.createPkg() // 创建外皮
        this.pushCola() // 倒进瓶子
        //还可以增加其他步骤
        return this.complete() // 制作完成
    }
}
function Boss() {
    this.createCola = function(packType) {
        const pack = new window[packType]
        this.product = pack.init() //完整产品产出
    }
    this.getCola = function(packType) {
        this.createCola(packType);
        return this.product
    }
}
const boss = new Boss()
var UserCola = boss.getCola('greenPacking') // UserCola.complete === true

参考 前端进阶面试题详细解答

其他东西都不要,只要最后生产好的Cola,有sugar,有water。

关键在于Boss 函数中,担任一个整合的职责

同样的Boss函数,我可以通过更换Packing函数,打包方式,获得不同样式的Cola。

通过给getCola函数传入不同想要的参数,获得不同的最终产品。实现了可插拔的函数结构。

装饰者模式

装饰者提供比继承更有弹性的替代方案。 装饰者用用于包装同接口的对象,不仅允许你向方法添加行为,而且还可以将方法设置成原始对象调用(例如装饰者的构造函数)。

装饰者用于通过重载方法的形式添加新功能,该模式可以在被装饰者前面或者后面加上自己的行为以达到特定的目的。

好处:

装饰者是一种实现继承的替代方案。当脚本运行时,在子类中增加行为会影响原有类所有的实例,而装饰者却不然。取而代之的是它能给不同对象各自添加新行为。

function iwatch () {
    this.battery = 100;
    this.getBattery = function() {
        console.log(this.battery)
    }
}

iwatch.prototype.getNewPart = function(part) {
    this[part].prototype = this; //把this对象上的属性 指向 新对象的prototype
    return new this[part]; //返回一个新对象,不修改原对象,新增了新对象的属性
}

iwatch.prototype.addNetwork = function() {
    this.network = function() {
        console.log('network')
    }
}

iwatch.prototype.addSwim = function() {
    this.swim = function() {
        console.log('swim')
    }
}

var watch = new iwatch();
watch.getBattery(); // 100

watch = watch.getNewPart('addNetwork'); // 添加新行为,network()
watch = watch.getNewPart('addSwim'); // 既有network方法,也有swim方法

在 ES7 中引入了@decorator 修饰器的提案,参考阮一峰的文章。

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

直接可以使用,装饰器行为

@decorator
class A {}

// 等同于

class A {}
A = decorator(A) || A;

工厂模式

一个工厂能生产好多不同的产品,最常见的工厂函数就是jQ的$()函数,每一个函数的结果都是一个需要的产品。

function Product(name) {
  this.name = name;
}
Product.prototype.init = function () {
  console.log('init');
}
Product.prototype.go = function () {
  console.log('go');
}

function Factory () {
}
Factory.prototype.add = function(name) {
  return new Product(name);
}

//use
let f = new Factory();
let a = f.add('a');

console.log(a.name);
a.init();
a.go();

适配器模式

Adapter,将一个类(对象)的接口(方法或者属性)转化为另一个接口,以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决

function Person () {
}
Person.prototype.Say = function() {
  throw new Error("该方法必须被重写!")
}
Person.prototype.Walk = function() {
  throw new Error("该方法必须被重写!")
}

function Dog () {
}
Dog.prototype.Walk = function() {
  throw new Error("该方法必须被重写!")
}
Dog.prototype.shout = function() {
  throw new Error("该方法必须被重写!")
}

function PersonA () {
  Person.apply(this)
}
PersonA.prototype = new Person()
PersonA.prototype.Say = function() {
  console.log('Person say')
}
PersonA.prototype.Walk = function() {
  console.log('Person Walk')
}

function DogBlack () {
  Dog.apply(this)
}
DogBlack.prototype = new Dog()
DogBlack.prototype.Walk = function() {
  console.log('Dog Walk')
}
DogBlack.prototype.shout = function() {
  console.log('Dog Shout')
}

//现在希望Dog类也可以学会Say,并且多走几步

function DogSayAdapter (DogClass) {
  Dog.apply(this)
  this.DogClass = DogClass
}
DogSayAdapter.prototype = new Dog()
DogSayAdapter.prototype.Say = function() {
  this.DogClass.shout()
}
DogSayAdapter.prototype.Walk = function() {
  this.DogClass.Walk()
  this.DogClass.Walk()
}

var personA = new PersonA()
var dogBlack = new DogBlack()
var dogSay = new DogSayAdapter(dogBlack)

personA.Say()
personA.Walk()
dogBlack.Walk()
dogBlack.shout()

dogSay.Say()
dogSay.Walk()//walk * 2    

适配器不只是函数接口,还有数据格式的适配

在前后端数据传递时,常用到适配器模式,也就是通俗易懂的格式化数据,format函数等等

vue的computed计算属性也是适配器模式的一种实现

const originData = [
    {
        title: 'title',
        age: 18,
        content: ['123',321],
        callback: function(){
            console.log(this)
        }
    },
  {
        title: 'title2',
        age: 1,
        content: ['1',3],
        callback: function(){
            console.log('title2')
        }
    }
]

function dataAdapter(data) {
  return data.map(item => {
    return {
      title: item.title,
      content: item.content.join(','),
      init: item.callback
    }
  })
}

var formatData = dataAdapter(originData)

e.g:原始data 的数据不满足当前的要求,通过适配器,把数据格式化成想要的格式,对原始数据没有改变

单例模式

function Simple (name) {
  this.name = name
}
Simple.prototype.go = function() {
  this.name = 'go'
  console.log(this.name)
}

//static静态方法
Simple.getInstance = (function() {
  var ins
  return function(name){
    if (!ins) {
      ins = new Simple(name)
    }
    return ins
  }
})()

let a = Simple.getInstance('a') // name: a
let b = Simple.getInstance('b') // name: a

b===a//true

非单例模式下,相同的new Simple()构造函数,不相等。

通过闭包只创建一次Simple实例,大家公用一个。

惰性单例模式

惰性和懒加载lazyload相似,延迟加载,或者说需要时再加载,不然一次加载过多,频繁进行操作dom影响性能

尽管上述代码有Simple.getInstance方法,可以在需要时再进行实例化,但仍然不是一个好的实现方式。

可以将惰性加载的部分提取出来。

e.g:

var simple = function(fn) {
    var instance;
    return function() {
        return instance || (instance = fn.apply(this, arguments));
    }
};
// 创建遮罩层
var createMask = function(){
    // 创建div元素
    var mask = document.createElement('div');
    // 设置样式
    mask.style.position = 'fixed';
    mask.style.top = '0';
      ...
    ...
    document.body.appendChild(mask);
    // 单击隐藏遮罩层
    mask.onclick = function(){
        this.style.display = 'none';
    }
    return mask;
};

// 创建登陆窗口
var createLogin = function() {
    // 创建div元素
    var login = document.createElement('div');
    // 设置样式
    login.style.position = 'fixed';
    login.style.top = '50%';
      ...
    ...
    login.innerHTML = 'login it';
    document.body.appendChild(login);

    return login;
};

document.getElementById('btn').onclick = function() {
    var oMask = simple(createMask)();
    oMask.style.display = 'block';
    var oLogin = simple(createLogin)();
    oLogin.style.display = 'block';
}

总结

对五种常见常用的设计模式进行了学习,这几种很多时候都会用到,接下来还会继续学习其他的18种设计模式,可能有的设计模式不一定在实际敲码中使用,学了没坏处,总能用得上嗷!

网上对于设计模式的文章,书籍层出不尽,但看得再多,不如自己理解,并且实际使用。很多时候是几种设计模式融合在一起使用,如果不是自己去写一遍,理解一遍,可能常见的设计模式都理解不了。这样就太可惜了,发现干净整洁的代码,都说不出哪里好,就是看着舒服,顺眼,运行速度快…

JavaScript设计模式详解 设计模式是一种在软件设计中解决常见问题的可重用解决方案。它们是经过验证的、通用的设计思想,提供了一种解决软件设计中反复出现问题的方法。设计模式不是可直接转化成代码的具体算法,而是关于如何解决某一类问题的指导性方案。设计模式的好处包括提高代码的可重用性、可维护性、可扩展性,同时也有助于降低代码的复杂性。 阅读详情

相关推荐

JavaScript 设计模式 —— 接口

接口提供了一种用以说明一个对象应该具有哪些方法的手段。尽管它可以表明(或至少是暗示)这些方法的语义,但它并不规定这些方法应该如何实现。例如,如果一个接口包含有一个名为setName的方法,那么你有理由认为这个方法的实现应该具有一个字符串参数,并且会把这个参数赋给一个name变量。有了这个工具,你就能按对象提供的特性对它们进行分组。

cccloveforever的博客 3158

前端基础拾遗90问,从零基础到精通,收藏这篇就够了!

引用计数:给一个变量赋值引用类型,则该对象的引用次数+1,如果这个变量变成了其他值,那么该对象的引用次数-1,垃圾回收器会回收引用次数为0的对象。但是当对象循环引用时,会导致引用次数永远无法归零,造成内存无法释放。标记清除:垃圾收集器先给内存中所有对象加上标记,然后从根节点开始遍历,去掉被引用的对象和运行环境中对象的标记,剩下的被标记的对象就是无法访问的等待回收的对象。当元素的尺寸或者位置发生了变化,就需要重新计算渲染树,这就是回流DOM元素的几何属性()发生变化时会触发回流。

bigbangbangbang1的博客 1065

从官方例程到实战:AXI Memory Mapped To PCIe 核在FPGA-RC模式下的配置与调试全解析

本文详细解析了AXI Memory Mapped To PCIe核在FPGA-RC模式下的配置与调试方法。从IP核基础结构到实战参数设置,再到例程代码剖析和调试技巧,全面覆盖了AXI与PCIe协议转换的关键技术点,帮助开发者高效实现FPGA与PCIe设备的高速数据交互。

weixin_42550597的博客 268

Javascript常见设计模式

Javascript常见设计模式:单例模式、工厂模式、发布订阅者与观察者模式、代理模式、策略模式

警警的博客 2273

自动控制原理之控制系统的数学模型(类比神经网络学习数学模型)

控制系统的数学模型背景建模方法常用的数学模型时域数学模型的建立建立微分方程的步骤复数域模型的建立传递函数的性质系统的典型环节及传递函数比例环节惯性环节积分环节微分环节理想微分环节一阶微分环节二阶微分环节振荡环节延时环节(时滞环节) 背景 数学模型就像是真实世界的写照,它就像一个虚拟的世界,我们可以通过建模的方式了解这个真实世界的运作规律。 这一点很像强化学习,强化学习需要一个供智能体探索、学习的环境,于是,我们通常会事先建立一个虚拟的仿真环境。举个例子,对于人类来说,可能需要经过不断地尝试,甚至是生命的代价

zbp_12138的博客 6578

java爬虫(爬取银行理财数据)

import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; imp

ROCK 2491

高级前端工程师必备的 JS 设计模式入门教程,常用设计模式案例分享

        什么是设计模式?为什么要有设计模式?单例模式、工厂模式、建造者模式、适配器模式、代理模式、装饰器模式、观察者模式、策略模式、状态模式分别是什么?他们解决了什么样的问题?本文将给您答案。

RenGJ010617的博客 6967

信号与电源完整性5:轨道塌陷噪声/电源轨道噪声分析及降低解决方案

经过上一节关于串扰的分析,我们已经清楚,噪声问题不仅仅来源于信号网络;电源和地网络所产生的噪声,被反馈到其所在的元器件和信号网络时,其破坏力也是巨大的;本节所讨论的轨道塌陷噪声就是一个典型的实例。在经过电源的地网络的电流发生改变时,在电源和地之间的阻抗上将产生一个压降;由于该压降的产生,用电元件的电压将直接被拉低,甚至可能对电路产生功能性的错误。接下来硬小二将详细的分析电源轨道噪声和降低其的解决方法。...

fydar的博客 2243

js-challenges实战教程:10个经典JavaScript手写题详解

js-challenges是一个专注于提升JavaScript编程水平的前端手写题项目,通过一步步挑战JavaScript编程极限,帮助开发者掌握核心概念和实战技能。无论是JavaScript常见手写题、Promise场景题还是原生方法重写,都能在这里找到系统的练习资源。 ## 为什么选择js-challenges提升JavaScript技能? JavaScript作为前端开发的核心语言,掌握

gitblog_00913的博客 486

最强游戏投屏串流搭档Sunshine+Moonlight配置方法

因祸得福的是,sunshine作为开源的self-host的服务端,不仅可以代替Novidia的服务端角色,还拓展了moonlight可以服务的主机,非novidia显卡的PC也可以通过这对搭档实现高质量的游戏窜流投屏了。回到moonlight,点击电脑图表,会给你一个Pincode,到Sunshine控制台,菜单点击Pin,输入moonlight给出的pin码。高质量的图像: Moonlight支持高清(HD)和甚至4K分辨率的投屏,同时还提供了对音频的传输支持,确保用户可以享受到高质量的视频和音频。

每日出拳老爷子的博客 1万+

YOLO26改进 - C2PSA | C2PSA融合DiffAttention差分注意力:轻量级差分计算实现高效特征降噪,提升模型抗干扰能力

本文介绍了 DiffCLIP,一种将差分注意力机制集成到 CLIP 架构的视觉 - 语言模型,并将其应用于 YOLO26。差分注意力机制通过计算两个互补注意力分布的差值,抵消无关信息干扰。单头差分注意力将 Q 和 K 拆分,分别计算注意力分布后做差值融合;多头差分注意力则每个头独立执行差分操作后聚合输出。关键参数 λ 可动态调控噪声抵消强度。我们将 DiffAttention 代码集成到 YOLO26 中,替换原有模块。实验表明,改进后的 YOLO26 在图像 - 文本理解任务中表现出色。

魔改工程师的博客 602

JavaScript 常见的5种设计模式

本文是自己学习 JavaScript 设计模式的笔记,整理了 JavaScript 常见的五种设计模式,并总结了相应的案例代码。 1. 装饰者模式 装饰者模式是指,在不改变对象自身代码的前提下,新增功能的模式。 如下代码所示,创建3个飞机对象。plane可以发射普通子弹;plane2不仅可以发射普通子弹,还可以发射导弹;plane3不仅可以发射普通子弹和导弹,还可以发射炮弹。 创建构造函数Plane2时,不改变plane的功能,只增加功能,将Plane的实例挂载到自身属性上,并在fire方法下,调用.

火星基地 1847

【TC3xx芯片】TC3xx DMA模块详解

TC3xx DMA模块详解

qq_36056498的博客 5917

前端面试HTML5+CSS3+JS+TS4+Vue3+React18+八股文+手写+项目+笔试

变量声明不开辟内存,只是告诉编译器,要声明的部分存在,要预留部分的空间。var i;变量定义开辟内存。var i=123;props公开,单向数据流值,父子组件间的唯一通信不可改1.每个组件对象都会有props(properties的简写)属性2.组件标签的所有属性都保存在props中3.内部读取某个属性值:this.props.propertyNamestate私有(通过Ajax获取回来的数据,一般都是私有数据),React 把组件看成是一个状态机(State Machines),

luemeon的博客 3万+

基于扩散模型的图像去噪与修复:原理、实现与性能分析【附核心代码】

扩散模型(Diffusion Models)在图像修复、去噪、风格化、超分辨率等领域的应用,展示了其强大的生成能力和灵活性。通过模拟图像逐步加噪声再去噪的过程,扩散模型不仅能够恢复图像的细节,还能生成高质量的图像。本文详细探讨了扩散模型在图像修复和增强中的应用,并通过具体代码示例展示了如何使用扩散模型进行去噪、风格化、图像超分辨率等任务。扩散模型在图像修复中通过逐步去噪修复损坏的区域,在图像去噪中则能够去除图像中的噪声并保留细节;在图像风格化中,扩散模型通过结合目标风格和内容生成富有艺术性的图像;

一键难忘的博客 2930

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

JavaScript 常见10种设计模式

以上写法,如果数据量变多,代码重复并且臃肿。 es6之前,通过构造器函数创建对象。 弊端:每次new实例,say方法都会开辟内存创建此方法(构造器模式每次创建实例都会重复创建方法)。——但是不同对象的say方法是一样的。 3.2 补充:类语法兼顾构造器&原型模式 3.3 案例 四. 工厂模式 简单工厂的优点在于,你只需要一个正确的参数,就可以获取到你所需要的对象,而无需知道其创建的具体细节。 但是在函数内包含了所有对象的创建逻辑和判断逻辑的代码,每增加新的构造函数还需要修改判断逻辑代码。 当我们

qq_37581764的博客 1299

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

JavaScript中常见的设计模式

js常见的设计模式与开发实践。单例模式、策略模式、代理模式、迭代器模式、发布-订阅模式(观察者模式)、命令模式、组合模式、模板方法模式、享元模式、职责链模式、中介者模式、装饰者模式、状态模式、适配器模式

逆水寒 1737

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

JavaScript的几种常见的设计模式

JavaScript的几种常见的设计模式: 首先了解一下什么是设计模式: 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理地运用设计模式可以完美地解决很多问题,每...

weixin_43149598的博客 848

JavaScript设计模式

JavaScript设计模式 **设计模式:**代码经验的总结,是可重用的用于解决软件设计中一般问题的方案。 设计模式都是面向对象的。 学习设计模式,有助于写出可复用和可维护性高的程序。 常用的12种设计模式: 工厂模式 单例模式 原型模式 适配器模式 代理模式 策略模式 迭代器模式 观察者模式 发布-订阅模式 命令模式 组合模式 建造者模式 设...

林夏天的博客 7171

简单介绍几种常见的JavaScript设计模式

JavaScript是一种弱类型、动态的、基于原型的语言,由于语言的特殊性使得我们在书写JavaScript代码时候感觉到非常容易,甚至我们用很简单的方式都能实现一些设计模式,接下来我来简单的介绍几种常见的设计模式并利用JavaScript代码来实现它们 一、单体模式 单体模式:一个特定类的多个实例对象都指向同一个实例对象。 在JavaScript中没有类只有对象,当你创建一个对象时候并不会有其他对象与其类似,所以当我们用字面量创建一个对象时,其实就是一个JavaScript的单体例子。由于JavaScri

qq_16483541的博客 576

js高频手写题总结

可以看出,一个嵌套了两层的数组,通过将 flat 方法的参数设置为 Infinity,达到了我们预期的效果。执行temp(5),这个函数内执行add(m+n),n是此次传进来的数值5,m值还是上一步中的7,所以add(m+n)=add(7+5)=add(12),此时m=12,并且返回temp函数。执行temp(4),这个函数内执行add(m+n),n是此次传进来的数值4,m值还是上一步中的3,所以add(m+n)=add(3+4)=add(7),此时m=7,并且返回temp函数。

helloworld1024fd的博客 348

前端JS手写编程题库,终于开源了 Github

前端手写题集锦 use js 记录大厂笔试,面试常考手写题, 致力打造最全的前端JavaScript手写题题库和答案的最优解 注意,本仓库目前不包含算法相关的题目,比如leetcode上的题,只包含js的手写题,leetcode相关的题目也会整理,计划中,还未定方案 谢谢您的star,您的star是我更新的动力🥳 里面有答案,为了让你们有一个参考,不过非常希望你们能提供自己的思路,指出答案中存在的问题,复杂度优化等等, 期待你们的contribute, 想来一起维护这个项目,可以联系我,成为contr

m0_46424423的博客 517
上一篇: 百度前端必会手写面试题整理
下一篇: 前端经典手写面试题(持续更新中)
helloworld1024fd
博客等级 码龄4年 245粉丝 243原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值