前端常见的8种设计模式

更新日期: 2023-03-17阅读: 685标签: 模式

前端开发中,设计模式是一种被广泛应用的思想。设计模式可以帮助开发者解决常见的问题,并提供可重用的解决方案。本文将会介绍前端常见的设计模式,并通过代码详解它们的实现。


一、单例模式

单例模式是指一个类只能被实例化一次,并提供全局访问点。这个模式非常适合那些需要共享资源的场景。比如,在前端开发中,我们经常需要确保某些资源只被加载一次,而不是每次都重新加载。下面是一个使用单例模式的例子:

class Singleton {
  constructor() {
    if (typeof Singleton.instance === 'object') {
      return Singleton.instance;
    }
    this.name = 'Singleton';
    Singleton.instance = this;
    return this;
  }
}

const instance1 = new Singleton();
const instance2 = new Singleton();

console.log(instance1 === instance2); // true

上述代码中,我们创建了一个 Singleton 类,该类只能被实例化一次。如果多次尝试实例化该类,将会返回同一个实例。这样就保证了某些资源只会被加载一次,从而提高性能。


二、观察者模式

观察者模式是指当一个对象状态改变时,它的所有依赖者都会收到通知并自动更新。这个模式非常适合那些需要实时更新用户界面的场景。下面是一个使用观察者模式的例子:

class ObserverList {
  constructor() {
    this.observerList = [];
  }

  add(observer) {
    return this.observerList.push(observer);
  }

  remove(observer) {
    this.observerList = this.observerList.filter((obs) => obs !== observer);
  }

  count() {
    return this.observerList.length;
  }

  get(i) {
    return this.observerList[i];
  }
}

class Subject {
  constructor() {
    this.observers = new ObserverList();
  }

  addObserver(observer) {
    this.observers.add(observer);
  }

  removeObserver(observer) {
    this.observers.remove(observer);
  }

  notify(context) {
    const observerCount = this.observers.count();
    for (let i = 0; i < observerCount; i++) {
      this.observers.get(i).update(context);
    }
  }
}

class Observer {
  constructor() {
    this.update = () => {};
  }
}

const subject = new Subject();

const observer1 = new Observer();
observer1.update = function (context) {
  console.log(`Observer 1: ${context}`);
};

const observer2 = new Observer();
observer2.update = function (context) {
  console.log(`Observer 2: ${context}`);
};

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.notify('Hello World');

上述代码中,我们创建了一个 Subject 类和一个 Observer 类。Subject 类包含了一个观察者列表,并提供了添加、删除和通知观察者的方法。Observer 类则包含了一个更新方法,用于处理来自被观察者的通知。在主程序中,我们创建了两个观察者,并将它们添加到被观察者的观察者列表中。然后,我们通知被观察者,被观察者会自动通知所有观察者,并执行它们的更新方法。


三、工厂模式

工厂模式是指通过一个工厂类来创建其他类的实例。这个模式非常适合那些需要根据不同条件创建不同实例的场景。下面是一个使用工厂模式的例子:

class ProductA {
constructor(name) {
this.name = name;
}
operation() {
console.log(`Product A (${this.name}) is working.`);
}
}
class ProductB {
constructor(name) {
this.name = name;
}
operation() {
console.log(`Product B (${this.name}) is working.`);
}
}
class Factory {
createProduct(type, name) {
switch (type) {
case 'A':
return new ProductA(name);
case 'B':
return new ProductB(name);
default:
throw new Error('Invalid product type.');
}
}
}
const factory = new Factory();
const productA1 = factory.createProduct('A', 'productA1');
const productA2 = factory.createProduct('A', 'productA2');
const productB1 = factory.createProduct('B', 'productB1');
const productB2 = factory.createProduct('B', 'productB2');
productA1.operation(); // Product A (productA1) is working.
productA2.operation(); // Product A (productA2) is working.
productB1.operation(); // Product B (productB1) is working.
productB2.operation(); // Product B (productB2) is working.

上述代码中,我们创建了两个产品类 `ProductA` 和 `ProductB`,以及一个工厂类 `Factory`。工厂类提供了一个创建产品实例的方法 `createProduct`,该方法根据传入的参数来决定创建哪种产品实例。在主程序中,我们通过工厂类创建了四个不同的产品实例,并分别执行它们的操作方法。


四、装饰者模式

装饰者模式是指动态地给一个对象增加一些额外的功能。这个模式非常适合那些需要在运行时动态改变对象行为的场景。下面是一个使用装饰者模式的例子:

class Shape {
draw() {}
}

class Circle extends Shape {
draw() {
console.log('Drawing a circle.');
}
}

class Rectangle extends Shape {
draw() {
console.log('Drawing a rectangle.');
}
}

class Decorator {
constructor(shape) {
this.shape = shape;
}

draw() {
this.shape.draw();
}
}

class RedShapeDecorator extends Decorator {
draw() {
this.shape.draw();
this.setRedBorder();
}

setRedBorder() {
console.log('Setting red border.');
}
}

const circle = new Circle();
const rectangle = new Rectangle();

circle.draw(); // Drawing a circle.
rectangle.draw(); // Drawing a rectangle.

const redCircle = new RedShapeDecorator(new Circle());
const redRectangle = new RedShapeDecorator(new Rectangle());

redCircle.draw(); // Drawing a circle. Setting red border.
redRectangle.draw(); // Drawing a rectangle. Setting red border.

上述代码中,我们创建了两个形状类 Circle 和 Rectangle,以及一个装饰者类 Decorator。装饰者类包含了一个形状对象,用于对其进行装饰。然后,我们创建了一个红色形状装饰者类 RedShapeDecorator,用于在形状周围添加一个红色边框。在主程序中,我们先执行原始形状的绘制方法,然后再使用红色装饰器对其进行装饰。


五、代理模式

代理模式是指使用一个代理对象来控制对另一个对象的访问。这个模式非常适合那些需要控制对某些敏感资源的访问的场景。下面是一个使用代理模式的例子:

class Image {
constructor(url) {
this.url = url;
this.loadImage();
}

loadImage() {
console.log(`Loading image from ${this.url}`);
}
}

class ProxyImage {
constructor(url) {
this.url = url;
}

loadImage() {
if (!this.image) {
this.image = new Image(this.url);
}
console.log(`Displaying cached image from ${this.url}`);
}
}

const image1 = new Image('https://example.com/image1.jpg');
const proxyImage1 = new ProxyImage('https://example.com/image1.jpg');

proxyImage1.loadImage(); // Loading image from https://example.com/image1.jpg
proxyImage1.loadImage(); // Displaying cached image from https://example.com/image1.jpg

const image2 = new Image('https://example.com/image2.jpg');
const proxyImage2 = new ProxyImage('https://example.com/image2.jpg');

proxyImage2.loadImage(); // Loading image from https://example.com/image2.jpg
proxyImage2.loadImage(); // Displaying cached image from https://example.com/image2.jpg

上述代码中,我们创建了一个图片类 `Image` 和一个代理图片类 `ProxyImage`。代理图片类包含了一个图片对象,用于控制对其加载和显示的访问。在主程序中,我们首先创建了一个真实的图片对象,并使用代理图片对象进行访问。第一次访问时,代理图片对象会加载并显示真实的图片;第二次访问时,代理图片对象直接从缓存中获取并显示图片。


六、适配器模式

适配器模式是指将不兼容接口的对象转化为兼容接口的对象。这个模式非常适合那些需要改变接口而不影响原有代码的场景。下面是一个使用适配器模式的例子:

class OldCalculator {
operations(a, b, operation) {
switch (operation) {
case 'add':
return a + b;
case 'sub':
return a - b;
default:
return NaN;
}
}
}

class NewCalculator {
add(a, b) {
return a + b;
}

sub(a, b) {
return a - b;
}
}

class CalculatorAdapter {
constructor() {
this.newCalculator = new NewCalculator();
}

operations(a, b, operation) {
switch (operation) {
case 'add':
return this.newCalculator.add(a, b);
case 'sub':
return this.newCalculator.sub(a, b);
default:
return NaN;
}
}
}

const oldCalculator = new OldCalculator();
console.log(oldCalculator.operations(10, 5, 'add')); // 15

const newCalculator = new NewCalculator();
console.log(newCalculator.add(10, 5)); // 15

const calculatorAdapter = new CalculatorAdapter();
console.log(calculatorAdapter.operations(10, 5, 'add')); // 15

上述代码中,我们创建了一个旧计算器类 OldCalculator 和一个新计算器类 NewCalculator。然后,我们创建了一个适配器类 CalculatorAdapter,该类包含了一个新计算器对象,用于将旧计算器的操作转化为新计算器的操作。在主程序中,我们分别使用旧计算器、新计算器和适配器进行加法运算,并得到了相同的结果。


七、命令模式

命令模式是指将请求封装成一个对象,并提供与执行该请求相关的所有信息。这个模式非常适合那些需要执行多个不同操作的场景。下面是一个使用命令模式的例子:

class Receiver {
  run() {
    console.log('Receiver is running.');
  }
}

class Command {
  constructor(receiver) {
    this.receiver = receiver;
  }

  execute() {}
}

class StartCommand extends Command {
  execute() {
    this.receiver.run();
  }
}

class Invoker {
  setCommand(command) {
    this.command = command;
  }

  executeCommand() {
    this.command.execute();
  }
}

const receiver = new Receiver();
const startCommand = new StartCommand(receiver);
const invoker = new Invoker();
invoker.setCommand(startCommand);
invoker.executeCommand(); // Receiver is running.

上述代码中,我们创建了一个接收者类 Receiver 和一个命令基类 Command。然后,我们创建了一个具体命令类 StartCommand,该类继承自命令基类,并实现了执行方法 execute,用于启动接收者。最后,我们创建了一个调用者类 Invoker,该类包含了一个命令对象,并提供了执行命令的方法。在主程序中,我们创建了一个接收者对象、一个具体命令对象和一个调用者对象,并将具体命令对象设置为调用者对象的命令。然后,我们执行调用者对象的执行方法,该方法会调用具体命令对象的执行方法,从而启动接收者。这个例子比较简单,但命令模式可以应用于很多复杂的场景,例如撤销/恢复操作、事务管理等。


八、观察者模式

观察者模式是指在对象之间定义一种一对多的依赖关系,使得每当一个对象改变状态时,所有依赖于它的对象都会得到通知并自动更新。这个模式非常适合那些需要在应用中实现事件处理的场景。下面是一个使用观察者模式的例子:

class Subject {
  constructor() {
    this.observers = [];
  }

  addObserver(observer) {
    this.observers.push(observer);
  }

  removeObserver(observer) {
    const index = this.observers.indexOf(observer);
    if (index >= 0) {
      this.observers.splice(index, 1);
    }
  }

  notifyObservers() {
    for (const observer of this.observers) {
      observer.update(this);
    }
  }
}

class ConcreteSubject extends Subject {
  constructor(state) {
    super();
    this.state = state;
  }

  getState() {
    return this.state;
  }

  setState(state) {
    this.state = state;
    this.notifyObservers();
  }
}

class Observer {
  update() {}
}

class ConcreteObserver extends Observer {
  update(subject) {
    console.log(`The subject has changed to ${subject.getState()}.`);
  }
}

const subject = new ConcreteSubject('state1');
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();

subject.addObserver(observer1);
subject.addObserver(observer2);

subject.setState('state2'); // The subject has changed to state2.

上述代码中,我们创建了一个主题基类 Subject 和一个具体主题类 ConcreteSubject。主题类包含了一个状态属性和一组观察者对象,并提供了方法以添加、删除和通知观察者。然后,我们创建了一个观察者基类 Observer 和一个具体观察者类 ConcreteObserver,该类继承自观察者基类,并实现了更新方法。在主程序中,我们创建了一个具体主题对象、两个具体观察者对象,并将观察者对象添加到主题对象中。然后,我们修改了主题对象的状态,并通过主题对象通知观察者对象进行更新操作。

以上就是七种常见的设计模式以及它们的应用场景和示例代码。当然,这只是冰山一角,还有很多其他的设计模式可以应用于不同的场景。熟悉各种设计模式并且能够灵活运用它们可以让你成为更优秀的开发者。


链接: https://www.fly63.com/article/detial/12413

js设计模式之单例模式,javascript如何将一个对象设计成单例

单例模式是我们开发中一个非常典型的设计模式,js单例模式要保证全局只生成唯一实例,提供一个单一的访问入口,单例的对象不同于静态类,我们可以延迟单例对象的初始化,通常这种情况发生在我们需要等待加载创建单例的依赖。

前端设计模式:从js原始模式开始,去理解Js工厂模式和构造函数模式

工厂模式下的对象我们不能识别它的类型,由于typeof返回的都是object类型,不知道它是那个对象的实例。另外每次造人时都要创建一个独立的person的对象,会造成代码臃肿的情况。

JavaScript设计模式_js实现建造者模式

建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象

html和xhtml,DOCTYPE和DTD,标准模式和兼容模式

主要涉及知识点: HTML与XHTML,HTML与XHTML的区别,DOCTYPE与DTD的概念,DTD的分类以及DOCTYPE的声明方式,标准模式(Standard Mode)和兼容模式(Quircks Mode),标准模式(Standard Mode)和兼容模式(Quircks Mode)的区别

前端四种设计模式_JS常见的4种模式

JavaScript中常见的四种设计模式:工厂模式、单例模式、沙箱模式、发布者订阅模式

javascript 策略模式_理解js中的策略模式

javascript 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 策略模式利用组合,委托等技术和思想,有效的避免很多if条件语句,策略模式提供了开放-封闭原则,使代码更容易理解和扩展, 策略模式中的代码可以复用。

javascript观察者模式_深入理解js中的观察者模式

javascript观察者模式又叫发布订阅模式,观察者模式的好处:js观察者模式支持简单的广播通信,自动通知所有已经订阅过的对象。存在一种动态关联,增加了灵活性。目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。

Vue中如何使用方法、计算属性或观察者

熟悉 Vue 的都知道 方法methods、计算属性computed、观察者watcher 在 Vue 中有着非常重要的作用,有些时候我们实现一个功能的时候可以使用它们中任何一个都是可以的

我最喜欢的 JavaScript 设计模式

我觉得聊一下我爱用的 JavaScript 设计模式应该很有意思。我是一步一步才定下来的,经过一段时间从各种来源吸收和适应直到达到一个能提供我所需的灵活性的模式。让我给你看看概览,然后再来看它是怎么形成的

Flutter 设计模式 - 简单工厂

在围绕设计模式的话题中,工厂这个词频繁出现,从 简单工厂 模式到 工厂方法 模式,再到 抽象工厂 模式。工厂名称含义是制造产品的工业场所,应用在面向对象中,顺理成章地成为了比较典型的创建型模式

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!