返回

JavaScript 中的设计模式:创建型设计模式,探索构建对象的艺术

前端

创建型设计模式:揭秘对象的诞生艺术

在软件开发的世界里,设计模式是一套久经考验的解决方案,它们为你解决常见的编程问题提供了可靠的方法。其中,创建型设计模式着重于对象创建的方式,让你以一种系统化、可复用且可扩展的方式构建代码。

单例模式:确保唯一性

单例模式保证一个类只存在一个实例,并提供一个全局访问点来访问该实例。这种模式适用于需要全局共享状态或资源的情况,例如数据库连接、缓存或日志记录器。

// 单例模式
class Singleton {
  static instance = null;

  constructor() {
    if (!Singleton.instance) {
      Singleton.instance = this;
    }

    return Singleton.instance;
  }
}

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

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

工厂模式:统一创建对象

工厂模式通过一个统一的接口创建对象,无需指定对象的具体类。这对于需要创建大量不同类型对象的场景非常有用,例如在游戏中创建各种敌人或道具。

// 工厂模式
class EnemyFactory {
  createEnemy(type) {
    switch (type) {
      case 'goblin':
        return new Goblin();
      case 'orc':
        return new Orc();
      case 'troll':
        return new Troll();
      default:
        throw new Error('Invalid enemy type');
    }
  }
}

const factory = new EnemyFactory();

const goblin = factory.createEnemy('goblin');
const orc = factory.createEnemy('orc');
const troll = factory.createEnemy('troll');

console.log(goblin); // Goblin { ... }
console.log(orc); // Orc { ... }
console.log(troll); // Troll { ... }

抽象工厂模式:创建相关对象家族

抽象工厂模式提供一个接口,让你创建相关或依赖的对象家族,而无需指定它们的具体类。这在需要创建一组相关对象时非常有用,例如在图形用户界面中创建按钮、文本框和复选框。

// 抽象工厂模式
class GUIFactory {
  createButton() {
    throw new Error('This method must be implemented by subclasses');
  }

  createTextBox() {
    throw new Error('This method must be implemented by subclasses');
  }

  createCheckBox() {
    throw new Error('This method must be implemented by subclasses');
  }
}

class WindowsGUIFactory extends GUIFactory {
  createButton() {
    return new WindowsButton();
  }

  createTextBox() {
    return new WindowsTextBox();
  }

  createCheckBox() {
    return new WindowsCheckBox();
  }
}

class MacGUIFactory extends GUIFactory {
  createButton() {
    return new MacButton();
  }

  createTextBox() {
    return new MacTextBox();
  }

  createCheckBox() {
    return new MacCheckBox();
  }
}

const factory = new WindowsGUIFactory();

const button = factory.createButton();
const textBox = factory.createTextBox();
const checkBox = factory.createCheckBox();

console.log(button); // WindowsButton { ... }
console.log(textBox); // WindowsTextBox { ... }
console.log(checkBox); // WindowsCheckBox { ... }

生成器模式:分离对象创建过程

生成器模式将对象的创建过程与使用它们的代码分离,让你可以独立地创建复杂或耗时的对象。这对于需要创建大量复杂对象的场景非常有用,例如在数据处理中创建大量记录,或在图像处理中创建大量图像。

// 生成器模式
class UserGenerator {
  constructor(data) {
    this.data = data;
    this.index = 0;
  }

  next() {
    if (this.index < this.data.length) {
      const user = this.data[this.index];
      this.index++;
      return { value: user, done: false };
    } else {
      return { value: undefined, done: true };
    }
  }
}

const generator = new UserGenerator([
  { name: 'John', age: 30 },
  { name: 'Mary', age: 25 },
  { name: 'Bob', age: 40 },
]);

console.log(generator.next()); // { value: { name: 'John', age: 30 }, done: false }
console.log(generator.next()); // { value: { name: 'Mary', age: 25 }, done: false }
console.log(generator.next()); // { value: { name: 'Bob', age: 40 }, done: false }
console.log(generator.next()); // { value: undefined, done: true }

原型模式:克隆对象

原型模式通过克隆现有的对象来创建新对象,而无需通过构造函数创建。这对于需要创建大量相似对象的情况非常有用,例如在游戏中创建大量具有相同属性和行为的敌人或道具。

// 原型模式
class Enemy {
  constructor(name, health, attack) {
    this.name = name;
    this.health = health;
    this.attack = attack;
  }

  clone() {
    return new Enemy(this.name, this.health, this.attack);
  }
}

const goblin = new Enemy('Goblin', 100, 10);
const orc = goblin.clone();

console.log(goblin); // Enemy { name: 'Goblin', health: 100, attack: 10 }
console.log(orc); // Enemy { name: 'Goblin', health: 100, attack: 10 }

策略模式:定义一系列算法

策略模式定义了一系列算法,并封装它们,使它们可以互换,从而让你在运行时改变算法。这对于需要在不同算法之间切换的情况非常有用,例如在排序算法中选择不同的排序策略。

// 策略模式
class SortStrategy {
  sort(array) {
    throw new Error('This method must be implemented by subclasses');
  }
}

class BubbleSortStrategy extends SortStrategy {
  sort(array) {
    for (let i = 0; i < array.length - 1; i++) {
      for (let j = 0; j < array.length - i - 1; j++) {
        if (array[j] > array[j + 1]) {
          const temp = array[j];
          array[j] = array[j + 1];
          array[j + 1] = temp;
        }
      }
    }
  }
}

class QuickSortStrategy extends SortStrategy {
  sort(array) {
    if (array.length <= 1) {
      return array;
    }

    const pivot = array[0];
    const left = [];
    const right = [];

    for (let i = 1; i < array.length; i++) {
      if (array[i] < pivot) {
        left.push(array[i]);
      } else {
        right.push(array[i]);
      }
    }
  }
}

结论

创建型设计模式为构建对象提供了强大的工具,使你的代码更加健壮、可维护和可扩展。通过了解这些模式及其应用,你可以显著提高你的软件开发技能。

常见问题解答

1. 何时使用单例模式?

  • 当你需要确保一个类只有一个实例并提供一个全局访问点时。

2. 工厂模式和抽象工厂模式有什么区别?

  • 工厂模式创建单一类型的对象,而抽象工厂模式创建相关或依赖的对象家族。

3. 生成器模式的优点是什么?

  • 它将对象的创建过程与使用它们的代码分离,允许独立创建复杂或耗时的对象。

4. 原型模式的目的是什么?

  • 克隆现有的对象,而无需通过构造函数创建,从而创建大量相似对象。

5. 何时应该使用策略模式?

  • 当你需要在运行时更改算法时,例如在排序算法中选择不同的排序策略。