首页 常识

JavaScript中的五大设计模式


设计模式是我大学教育中的一个亮点。当时,我没有完全理解它们的重要性,但随着我在开发人员职业生涯中的积累,我开始欣赏它们在软件开发中的关键作用。这些模式为开发人员在复杂项目上交流和协作提供了通用语言。它们是以可扩展和可维护的方式解决反复出现的问题的解决方案。

它们是任何有经验的开发人员的必要工具,并继续影响我在日常工作中处理和解决问题的方式。在文章中,我将介绍作为一个JavaScript开发者,你应该知道的5种设计模式。让我们来解锁JavaScript设计模式的力量。

1-工厂模式

工厂模式是一种设计模式,它提供了一种创建对象的方法,而无需指定要创建的对象的确切类。工厂类或方法用于根据特定的条件或输入来确定要实例化的对象类。这种方法允许更灵活和可维护的代码,因为对象的创建可以集中并从其余代码中抽象出来。

想象一下,你正在iOS和Android上构建一个跨平台应用程序。这个应用程序在两个平台上都有相同的界面,但你的代码包含了很多条件检查,以确定显示哪个按钮。

let button =
  platform == 'ios' ? 
  new IOSButton('Submit') 
  : new AndroidButton('Submit');

这不是很容易维护。让我们以工厂模式来更好的完成此操作:

class IOSButton {
  constructor(text) {
    this.text = text;
  }
}

class AndroidButton {
  constructor(text) {
    this.text = text;
  }
}

class ButtonFactory {
  createButton(text, platform) {
    switch (platform) {
      case 'ios':
        return new IOSButton(text);
      case 'android':
        return new AndroidButton(text);
      default:
        throw new Error('Invalid platform');
    }
  }
}

const buttonFactory = new ButtonFactory();
// Create an IOS button
const iosButton = buttonFactory.createButton('Submit', 'ios');
// Create an Android button
const androidButton = buttonFactory.createButton('Submit', 'android');

在这个例子中,我们有两个类,IOSButton和AndroidButton。我们还有一个ButtonFactory类,它有一个createButton方法,它接受一个text和一个platform参数,并根据platform返回一个新的button对象。createButton方法使用switch语句来根据平台实例化哪个按钮类。

2-单例模式

单例设计模式是一个强大的软件设计原则,它确保一个类只能有一个实例,同时提供对该实例的全局访问点。在某些情况下,应该只存在一个类实例并强制执行约束。缓存、线程池和注册表应该只有一个实例。

通常,类的构造函数被设置为private,以确保只有类成员可以访问和实例化它,从而确保整个应用程序只有一个类实例。

JavaScript没有私有构造函数的概念,因此达到相同效果的最常见方式是使用闭包和立即调用函数表达式(IIFE):

const Singleton = (function () {
  let instance;

  function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  function createInstance() {
    // 这是创建单例对象的地方
    const person = new Person('Rabi', 'Siddique');
    return person;
  }

  return {
    getInstance: function () {
      if (!instance) {
        instance = createInstance();
      }
      return instance;
    },
  };
})();

const instance1 = Singleton.getInstance();
const instance2 = Singleton.getInstance();
console.log(instance1 === instance2); // true

3-原型模式

原型模式通过复制已存在的对象(称为原型)来创建新对象。

原型模式是一种强大的技术,可以通过减少创建新对象所需的时间和资源来提高创建对象的性能,特别是当对象有很多字段或需要大量初始化处理(例如从数据库获取数据、调用API或执行复杂计算)时。该模式创建一个原型对象作为新对象的蓝图,从而消除了进一步内存分配和初始化的需要。通过复制原型对象来创建新对象,可以大大加快对象创建过程。

此外,原型模式提供了继承的另一种方式,允许对象从现有对象继承功能,而不需要复杂的类层次结构,使代码库更易于维护和理解。让我们看一个例子:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const person1 = new Person('Rabi', 'Siddique');
const person2 = Object.create(person1);

console.log(`${person2.firstName} ${person2.lastName}`); // Rabi Siddique

在这个例子中,我们通过Object.create方法复制person1的原型创建了一个新对象person2。person2将继承person1的属性和方法(如果有的话)。

4-代理模式

代理的字面定义是代表他人的权力。在代理模式设置中,代理在客户端面前代表另一个对象,称为主体。真正的主体被屏蔽,无法直接与客户端交互。这在很多情况下都很有用,例如:

  • 访问位于另一台计算机或另一个地址空间中的远程对象。
  • 保护主体不被未经授权的客户访问。
  • 将昂贵对象的创建推迟到需要时。
  • 将查询结果缓存到主题,以便客户端更快地访问。

一个代理模式的JavaScript例子:

// 原对象
const person = {
  name: 'Rabi Siddique',
  city: 'Gujranwala',
};

// The proxy object
const personProxy = new Proxy(person, {
  get: function (target, property) {
    return target[property];
  },
  set: function (target, property, value) {
    target[property] = value;
  },
});

// 使用proxy访问原始对象的属性
console.log(personProxy.name); // 'Rabi Siddique'

// 使用proxy修改原始对象的属性
personProxy.city = 'Lahore';
console.log(personProxy.city); // 'Lahore'

在这个例子中,personProxy是一个封装了原始person对象的代理对象。当通过personProxy访问或修改person对象的属性时,会调用代理的get和set方法。

5-构建者模式

构建者模式是一种有用的设计模式,它简化了创建复杂对象的过程。它允许您将对象的表示与其构造分离,使使用相同的构造过程更容易创建不同的表示。

假设你有一个热狗摊,客户需要在构造函数中告诉你他们想要的所有东西。这很难跟踪所有的选项,有时我们可能希望将每个步骤推迟到稍后的一点。在构建者模式中,我们使用方法而不是构造器逐步创建对象。这允许更多的灵活性和更好的组织。

在Javascript中,我们可以使用this关键字在每个方法中引用当前对象实例,并实现方法链。这意味着我们可以实例化一个对象,然后将方法链接到它,始终将对象作为返回值。这使得构建复杂对象的过程更加高效和易于管理。

class HotDogBuilder {
  constructor() {
    this.hotDog = {};
  }

  addBun(bun) {
    this.hotDog.bun = bun;
    return this;
  }

  addSausage(sausage) {
    this.hotDog.sausage = sausage;
    return this;
  }

  addToppings(toppings) {
    this.hotDog.toppings = toppings;
    return this;
  }

  addSauces(sauces) {
    this.hotDog.sauces = sauces;
    return this;
  }

  build() {
    return this.hotDog;
  }
}

const hotDog = new HotDogBuilder()
  .addBun('sesame')
  .addSausage('beef')
  .addToppings(['onion', 'tomato'])
  .addSauces(['mustard', 'ketchup'])
  .build();

console.log(hotDog);


在我们的示例中,我们可以使用构建器模式,通过有组织且高效地添加不同的配料、酱料和调味品,创建不同的热狗变体。构建者模式允许我们将构建逻辑委托给一个完全不同的类,这使得构建过程更加灵活。

下一篇 上一篇
猜你喜欢