Шаблоны проектирования — это многоразовые решения общих проблем программирования, которые можно применять в самых разных ситуациях. В JavaScript есть несколько шаблонов проектирования, которые особенно полезны для создания масштабируемых и удобных в сопровождении приложений. Вот три самых полезных шаблона проектирования в JavaScript, а также примеры их применения:

  1. Шаблон одиночного элемента.Шаблон одиночного элемента используется для обеспечения того, чтобы класс имел только один экземпляр, и обеспечивает глобальную точку доступа к этому экземпляру. Это может быть полезно, когда вам нужно обмениваться данными или ресурсами между несколькими частями приложения или когда вы хотите применить определенное поведение или ограничение. Например:
class Database {
  private static instance: Database;

  private constructor() {}

  public static getInstance(): Database {
    if (!Database.instance) {
      Database.instance = new Database();
    }
    return Database.instance;
  }
}

const db1 = Database.getInstance();
const db2 = Database.getInstance();

console.log(db1 === db2); // true
class Logger {
  private static instance: Logger;

  private constructor() {}

  public static getInstance(): Logger {
    if (!Logger.instance) {
      Logger.instance = new Logger();
    }
    return Logger.instance;
  }

  public log(message: string): void {
    console.log(`[${new Date().toISOString()}] ${message}`);
  }
}

const logger1 = Logger.getInstance();
logger1.log("This is a log message");

const logger2 = Logger.getInstance();
logger2.log("This is another log message");

2.Фабричный шаблон. Фабричный шаблон используется для создания объектов на основе определенного интерфейса или контракта без указания точного класса объекта, который будет создан. Это может быть полезно, когда у вас есть сложная иерархия объектов и вы хотите создавать объекты гибким и модульным способом. Например:

interface Shape {
  draw(): void;
}

class Circle implements Shape {
  public draw(): void {
    console.log("Drawing a circle");
  }
}

class Square implements Shape {
  public draw(): void {
    console.log("Drawing a square");
  }
}

class ShapeFactory {
  public static createShape(type: string): Shape {
    switch (type) {
      case "circle":
        return new Circle();
      case "square":
        return new Square();
      default:
        throw new Error("Invalid shape type");
    }
  }
}

const shape1 = ShapeFactory.createShape("circle");
shape1.draw(); // "Drawing a circle"

const shape2 = ShapeFactory.createShape("square");
shape2.draw(); // "Drawing a square"t
interface Animal {
  makeNoise(): void;
}

class Cat implements Animal {
  public makeNoise(): void {
    console.log("Meow");
  }
}

class Dog implements Animal {
  public makeNoise(): void {
    console.log("Woof");
  }
}

class AnimalFactory {
  public static createAnimal(type: string): Animal {
    switch (type) {
      case "cat":
        return new Cat();
      case "dog":
        return new Dog();
      default:
        throw new Error("Invalid animal type");
    }
  }
}

const animal1 = AnimalFactory.createAnimal("cat");
animal1.makeNoise(); // "Meow"

const animal2 = AnimalFactory.createAnimal("dog");
animal2.makeNoise(); // "Woof"

3.Шаблон наблюдателя. Шаблон наблюдателя используется для установления отношения "один ко многим" между объектами, так что один объект (субъект) может уведомлять несколько других объектов (наблюдателей) об изменении своего состояния. . Это может быть полезно, когда вы хотите отделить объекты и позволить им косвенно взаимодействовать друг с другом. Например:

class Subject {
  private observers: Observer[] = [];

  public subscribe(observer: Observer): void {
    this.observers.push(observer);
  }

  public unsubscribe(observer: Observer): void {
    this.observers = this.observers.filter((o) => o !== observer);
  }

  public notify(): void {
    this.observers.forEach((observer) => observer.update());
  }
}

class Observer {
  public update(): void {
    console.log("Received update from subject");
  }
}

const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();

subject.subscribe(observer1);
subject.subscribe(observer2);

subject.notify(); //