JS设计模式

简介: JS设计模式

创建型模式


工厂模式


在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象,它提供了一种创建对象的最佳方式。


个人理解类似于工厂车间,可以生产指定产品


function函数示例:


function factoryMode(name, age) {
 const obj = { name, age };
 return obj;
}
const zs = factoryMode('张三', 18);
const ls = factoryMode('李四', 20)
复制代码


构造函数模式


调用构造函数 new fn() ,返回拥有指定特征的对象实例


和工厂模式有相同之处,不同如下:


1.没有显式的创建对象


2.直接将属性和方法赋给了this对象


3.没有return语句


new 做了以下4个步骤


1.创建一个新的对象


2.将构造函数的作用域付给新对象(因此this就指向了这个新对象)


3.执行构造函数中的代码(为这个新对象添加属性)


4.返回新对象


function函数示例:


function ConstructorMode(name, age) {
  this.name = name;
  this.age = age;
};
const zs = new ConstructorMode('张三', 18);
const ls = new ConstructorMode('李四', 20)
复制代码


原型模式


原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。它提供了一种创建对象的最佳方式。


将公共的方法,属性放的原型(prototype)上,避免重复定义,便于维护


function PrototypeMode(name, age) {
  this.name = name;
  this.age = age;
}
PrototypeMode.prototype.sayName = function () { 
 console.log('my name is', this.name);
}
const zs = new PrototypeMode('张三', 18);
const ls = new PrototypeMode('李四', 20);
zs.sayName();
ls.sayName();
复制代码


单例模式


这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象,它提供了一种创建对象的最佳方式。


funciton函数示例:


function singletonMode(name, age) {
  let instance = {};
  return function (name, age) {
    if (!instance.name) {
      instance.name = name;
      instance.age = age;
    }
    return instance;
  }
}
const instance = singletonMode();
const zs = instance('张三', 18);
const ls = instance('李四', 20);
console.log(zs === ls); // true
复制代码


class类示例:


class SingletonModeClass {
  static instanceClass = {};
  constructor(name, age) {
    if (!this.constructor.instanceClass.name) {
      this.constructor.instanceClass.name = name;
      this.constructor.instanceClass.age = age;
    }
    return this.constructor.instanceClass;
  }
}
const zs2 = new SingletonModeClass('张三', 18);
const ls2 = new SingletonModeClass('李四', 20);
console.log(zs2 === ls2); // true
复制代码


结构型模式


装饰者模式


装饰者模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。即:在不改变原有对象的基础之上,将功能附加到对象上


function函数示例:


function Dog() {
  this.name = '小黑';
  this.age = 2;
  this.skill = function () {
    console.log('汪汪汪');
  }
}
const xiaohei = new Dog();
function addWalk(dog) {
  const skill = dog.skill;
  dog.skill = function () {
    skill();
    console.log('我可以走');
  }
};
addWalk(xiaohei);
function addRun(dog) {
  const skill = dog.skill;
  dog.skill = function () {
    skill();
    console.log('我可以跑');
  }
};
addRun(xiaohei);
xiaohei.skill();
复制代码


代理模式


在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。


意图:为其他对象提供一种代理以控制对这个对象的访问。


即访问一个对象,不会直接访问到这个对象,而是访问到它的代理对象上,通过代理对象预处理业务逻辑,然后通知被代理对象


优点


1. 职责清晰


2. 高扩展性


3. 可以保护对象


4. 优化性能,减少开销很大的对象,可缓存结果


ES6 proxy 示例:


const person = {
  name: "张三",
  age: 18
};
const proxy = new Proxy(person, {  
get: function (target, propKey, receiver) {
    console.log(target, propKey, receiver);
    if (propKey in target) {
      return target[propKey];
    } else {
      throw new ReferenceError(`没有${propKey}属性`);
    }
  },
  set: function (target, propKey, value, receiver) {
    console.log(target, propKey, value, receiver);
    console.log(`${propKey}属性被设置成了20`);
    target[propKey] = 20;
  }
});
proxy.name       "张三"
proxy.sex        Uncaught ReferenceError: 没有sex属性
proxy.age = 100  age属性被设置成了20
复制代码


比如明星的很多事务,都是经纪人帮忙处理,比如买东西,是否接受某个代言等


// 定义一个鞋子类
const Shoes = function (name) {
  this.name = name;
};
Shoes.prototype.getName = function () {
  return this.name;
};
// 添加了一个business方法,通过当前的时间来判断是否能买到鞋子
Shoes.prototype.business = function () {
  const curTime = new Date().getHours();
  return curTime >= 8 && curTime <= 20 ? `买到一双${this.getName()}` : '非营业时间!';
}
// 定义一个助理对象
const assistant = {
  buyShoes: function (shoes) {
    star.buyShoes(shoes.business());
  },
  pickUpWork: function (work) { 
   if (work.amt < 100000) {
      star.pickUpWork('出场费小于10万不接')
    } else if (!work.brand.includes('china')) {
      star.pickUpWork('不是国产品牌不接')
    } else {
      star.pickUpWork(`接了一个${work.brand}的活动,出场费${work.amt}`)
    }
  }
};
// 定义一个明星对象
const star = {
  buyShoes: function (res) {
    console.log(res);
  },
  pickUpWork: function (res) {
    console.log(res); 
 }};
assistant.buyShoes(new Shoes('鳄鱼皮鞋')); // 买了一双鳄鱼皮鞋||非营业时间!
assistant.pickUpWork({ amt: 100, brand: '李宁 china' }); // 出场费小于10万不接
assistant.pickUpWork({ amt: 1000000, brand: 'Nike' }); // 不是国产品牌不接
assistant.pickUpWork({ amt: 1000000, brand: '李宁 china' }); // 接了一个李宁 china的活动,出场费1000000
复制代码


还有比如大图加载前会有一大块空白,这个时候一般要显示loading图或者占位图,也可以用代理模式的思想完成,如下:


const myImage = (function () {
  // 创建dom
  const imgNode = document.createElement('img');
  document.body.appendChild(imgNode);
  return {
    setSrc: function (src) {
      imgNode.src = src;
    }
  }
})();
const preImage = (function () {
  // 创建虚拟图片dom
  const img = new Image();
  // 要加载的图片完成后,替换src
  img.onload = function () {
    myImage.setSrc(img.src);
  };
  return {
    // 先给dom设置loading图片
    setSrc: function (src) {
      myImage.setSrc('https://z3.ax1x.com/2021/03/29/cCjyPf.png');
      // 设置虚拟图片dom的src
      img.src = src;
    }
  }
})();
preImage.setSrc('https://s1.ax1x.com/2020/05/09/YlFytA.jpg');
复制代码


适配器模式


适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁,它结合了两个独立接口的功能,就像常见的mac转接头。示例如下:


// 普通接口
class Mac {
   getInterface() {
    return 'Mac接口';
  }
}
// 转换器
class Converter {
  constructor() {
    // 转换接口
    this.MacInstance = new Mac();
  }
  transfer() {
    // 获取要转换的接口
    const MacInterface = this.MacInstance.getInterface();
    return `将${MacInterface}转为通用接口`
  }
}
// 实例化转换器
const converter = new Converter();
// 调用转换功能
console.log(converter.transfer()); // 将Mac接口转为通用接口
复制代码


行为型模式


观察者模式


当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知依赖它的对象。


class类示例:


// 被观察者,调用setState时触发观察者update
class Subject {
  constructor() {
    this.count = 0;
    // 观察者集合
    this.observerList = [];
  }
  // 获取state
  getCount() {
    return this.count;
  }
  // 设置state
  setState(count) {
    this.count = count;
    this.notifyAllObservers();
  }
  // 添加观察者
  addObserver(observer) {
    this.observerList.push(observer);
  }
  // 通知观察者更新
  notifyAllObservers() {
    this.observerList.forEach(observer => {
      observer.update();
    })
  }}
// 观察者 被观察者调用setState时触发update
class Observer {
  constructor(name, subject) {
    this.name = name;
    // 保存被观察者
    this.subject = subject;
    // 被观察者添加this观察者
    this.subject.addObserver(this);
  }
  // 更新
  update() {
    console.log(`${this.name}更新,count=${this.subject.getCount()}`)
  }
}
let subjectObj = new Subject();
let observer1 = new Observer('observer1', subjectObj);
let observer2 = new Observer('observer2', subjectObj);
subjectObj.setState(1);
subjectObj.setState(2);
复制代码


以上就是个人总结的JS中的设计模式,如果有错误或者不严谨的地方,请给予指正,十分感谢!

相关文章
|
2月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
21 0
|
2月前
|
设计模式 JavaScript 前端开发
小白请看 JS大项目宝典:设计模式 教你如何追到心仪的女神
小白请看 JS大项目宝典:设计模式 教你如何追到心仪的女神
|
3月前
|
设计模式 JavaScript Go
js设计模式【详解】—— 状态模式
js设计模式【详解】—— 状态模式
46 7
|
3月前
|
设计模式 JavaScript
js设计模式【详解】—— 桥接模式
js设计模式【详解】—— 桥接模式
51 6
|
3月前
|
设计模式 JavaScript
js设计模式【详解】—— 原型模式
js设计模式【详解】—— 原型模式
42 6
|
3月前
|
设计模式 JavaScript 算法
js设计模式【详解】—— 模板方法模式
js设计模式【详解】—— 模板方法模式
41 6
|
3月前
|
设计模式 JavaScript 前端开发
JavaScript进阶 - JavaScript设计模式
【7月更文挑战第7天】在软件工程中,设计模式是解决常见问题的标准解决方案。JavaScript中的工厂模式用于对象创建,但过度使用可能导致抽象过度和缺乏灵活性。单例模式确保唯一实例,但应注意避免全局状态和过度使用。观察者模式实现了一对多依赖,需警惕性能影响和循环依赖。通过理解模式的优缺点,能提升代码质量。例如,工厂模式通过`createShape`函数动态创建对象;单例模式用闭包保证唯一实例;观察者模式让主题对象通知多个观察者。设计模式的恰当运用能增强代码可维护性。
72 0
|
3月前
|
设计模式 缓存 JavaScript
js设计模式实例
【7月更文挑战第2天】JavaScript设计模式包含工厂、单例、建造者、抽象工厂和代理模式等,它们是最佳实践和可重用模板,解决创建、职责分配和通信等问题。例如,工厂模式封装对象创建,单例确保全局唯一实例,建造者模式用于复杂对象构建,抽象工厂创建相关对象集合,而代理模式则控制对象访问。这些模式提升代码质量、可读性和灵活性,是高效开发的关键。
30 0
|
5天前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
19天前
|
设计模式 算法 安全
设计模式——模板模式
模板方法模式、钩子方法、Spring源码AbstractApplicationContext类用到的模板方法
设计模式——模板模式