js设计模式

1.单例模式

当在一个家庭中只有一个电视遥控器可用时,这就是一个单例模式的例子。在这种情况下:

  • 单例类:遥控器是一个单例类,因为在家庭中只有一个遥控器实例,用于控制电视。
  • 实例化:只会创建一个遥控器实例,即使有多个人在家中。

单例模式确保一个类只有一个实例,并提供全局访问点来访问这个实例,单例模式通常是整个应用程序中共享资源、配置或状态的情况,以确保只有一个实例被创建和使用

单例模式的核心思想是通过限制类的实例化次数,保证运行时只有一个实例存在,这有助于避免资源浪费、减少内存消耗,同时也使得实例的状态在应用中保持一致,例如vuex就可以看做单例模式的实现,new Store(),全局都访问这个store

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

  someMethod() {
    console.log("Singleton method called.");
  }
}

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

console.log(instance1 === instance2); // 输出: true

instance1.someMethod(); // 输出: Singleton method called.

2.观察者模式

当你订阅一个 YouTube 频道,每当该频道上传新视频时,你会收到通知,这就是一个生活中的观察者模式的例子。在这个情况下:

  • 主题(被观察者):YouTube 频道是主题,它维护了一组观察者(订阅者)。
  • 观察者:用户是观察者,他们订阅了频道,并希望在频道有新视频上传时得到通知。
// 观察者接口
class Observer {
  update(message) {
    throw new Error("This method must be overridden.");
  }
}

// 主题(被观察者)
class ProductSubject {
  constructor() {
    this.observers = [];
  }

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

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

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

  addNewProduct(productName) {
    const message = `${productName} has been added to the platform.`;
    this.notifyObservers(message);
  }
}

// 具体观察者
class UserObserver extends Observer {
  constructor(username) {
    super();
    this.username = username;
  }

  update(message) {
    console.log(`${this.username} received notification: ${message}`);
  }
}

// 使用观察者模式
const productSubject = new ProductSubject();

const user1 = new UserObserver("Alice");
const user2 = new UserObserver("Bob");

productSubject.addObserver(user1);
productSubject.addObserver(user2);

productSubject.addNewProduct("Smartphone");

productSubject.removeObserver(user1);

productSubject.addNewProduct("Laptop");

3.策略模式

策略模式在生活中的一个例子是选择支付方式。想象一下你在网上购物,当你下单时,需要选择支付方式,如信用卡、支付宝、微信支付等。不同的支付方式对应不同的支付策略,而这个过程可以使用策略模式来实现。

  1. 策略接口(Strategy Interface):定义了一个共同的接口,所有具体策略类都要实现这个接口。这个接口通常包含一个或多个方法,用于描述算法的不同行为。

  2. 具体策略类(Concrete Strategy Classes):实现了策略接口,提供了不同的算法实现。

  3. 环境类(Context Class):持有一个策略对象的引用,它可以在运行时切换不同的策略。环境类将客户端与策略之间的耦合度降低,使得客户端只需要与环境类交互,而不直接与具体策略类交互。

// 策略接口
class PaymentStrategy {
  pay(amount) {
    throw new Error("This method must be overridden.");
  }
}

// 具体策略类
class CreditCardPayment extends PaymentStrategy {
  pay(amount) {
    console.log(`Paid $${amount} with credit card.`);
  }
}

class AlipayPayment extends PaymentStrategy {
  pay(amount) {
    console.log(`Paid $${amount} with Alipay.`);
  }
}

class WeChatPayment extends PaymentStrategy {
  pay(amount) {
    console.log(`Paid $${amount} with WeChat Pay.`);
  }
}

// 环境类
class ShoppingCart {
  constructor(paymentStrategy) {
    this.paymentStrategy = paymentStrategy;
  }

  checkout(amount) {
    this.paymentStrategy.pay(amount);
  }
}

// 使用策略模式
const cart = new ShoppingCart(new AlipayPayment());
cart.checkout(100); // 输出: Paid $100 with Alipay.

cart.paymentStrategy = new WeChatPayment();
cart.checkout(200); // 输出: Paid $200 with WeChat Pay.

4.装饰者模式

以咖啡订单为例

  1. 组件(Component):定义一个抽象接口,为具体组件和装饰者提供一个公共的接口。

  2. 具体组件(Concrete Component):实现组件接口,是需要被装饰的具体对象。

  3. 装饰者(Decorator):继承自组件接口,包含一个组件实例,以及可用于添加新功能的方法。

  4. 具体装饰者(Concrete Decorator):实现装饰者接口,具体实现装饰功能,并且可以递归地包含其他装饰者或具体组件。

    // 组件接口
    class Coffee {
      cost() {
        return 5;
      }
    }
    
    // 具体组件
    class SimpleCoffee extends Coffee {}
    
    // 装饰者接口
    class CoffeeDecorator extends Coffee {
      constructor(coffee) {
        super();
        this.coffee = coffee;
      }
    
      cost() {
        return this.coffee.cost();
      }
    }
    
    // 具体装饰者
    class MilkDecorator extends CoffeeDecorator {
      cost() {
        return this.coffee.cost() + 2;
      }
    }
    
    class SugarDecorator extends CoffeeDecorator {
      cost() {
        return this.coffee.cost() + 1;
      }
    }
    
    // 使用装饰者模式
    const simpleCoffee = new SimpleCoffee();
    console.log(simpleCoffee.cost()); // 输出: 5
    
    const coffeeWithMilk = new MilkDecorator(simpleCoffee);
    console.log(coffeeWithMilk.cost()); // 输出: 7
    
    const coffeeWithMilkAndSugar = new SugarDecorator(coffeeWithMilk);
    console.log(coffeeWithMilkAndSugar.cost()); // 输出: 8
    

    5.适配器模式

生活中的适配器模式例子:

想象你正在国外旅行,你带了一个电子设备(比如充电器)以及一个国际插座转换器。在不同的国家,插座的类型和电压标准可能会不同。你的电子设备需要使用你所带的插座转换器(适配器)才能正确地连接到当地的电源插座。

在这个例子中:

  • 客户端(你的电子设备):这是你带来的电子设备,它期望连接到一个特定类型的插座。

  • 适配器(插座转换器):这是你带来的插座转换器,它的作用是将国际标准插座的接口转换为你电子设备所需的接口类型。

  • 被适配者(国际标准插座):这是国际标准的插座,它的接口与你的电子设备的接口不兼容。

// 客户端接口(国内标准插座)
class ChineseSocket {
  plugIn() {
    return "插入中国标准插座";
  }
}

// 适配器类(插座转换器)
class SocketAdapter {
  constructor(foreignSocket) {
    this.foreignSocket = foreignSocket;
  }

  plugIn() {
    return this.foreignSocket.plugIn() + ",使用适配器转换";
  }
}

// 被适配者接口(国际标准插座)
class ForeignSocket {
  plugIn() {
    return "插入国际标准插座";
  }
}

// 在国内使用适配器
const chineseSocket = new ChineseSocket();
console.log(chineseSocket.plugIn());

// 使用适配器在国内使用国际标准插座
const foreignSocket = new ForeignSocket();
const adapter = new SocketAdapter(foreignSocket);
console.log(adapter.plugIn());

你可能感兴趣的:(设计模式,javascript,前端)