フロントエンド開発で一般的に使用されるデザインパターンとアプリケーション

序文

フロントエンド開発では、誰もがコードを書くことができますが、このように書けばよいことはわかっていても、なぜこのように書くのか、その意味はわからない、ということがあります。今日はデザインパターンに関する知識を補足するための釣り事件があり、デザインパターンをより深く理解し、記録して共有することで、開発アイデアをより明確にすることができます。後で面接官が「デザインパターンを知っていますか?どんなデザインパターンを使ったのですか?」と質問するのを避けるために、私:「書くことはできますが、話すことはできません」、面接官:「戻って、面接を待ちます」通知"


デザインパターンの分類

デザイン パターンは、ソフトウェア開発における一般的な問題を解決するための一般的な方法であり、コードの可読性、保守性、拡張性の向上に役立ちます。デザインパターンには多くの種類があり、目的やシナリオに応じて、創造的、構造的、行動的の 3 つのカテゴリに分類できます。

クリエイティブ

  • シングルトンパターン

    作成パターンは主にオブジェクトの作成方法に焦点を当てており、クラスのインスタンスが 1 つだけであることを確認し、グローバル アクセス ポイントを提供する必要がある場合は、シングルトン パターンを使用できます。たとえば、グローバル ステータス オブジェクト、グローバル構成オブジェクト、またはグローバル イベント バス オブジェクトを管理する必要がある場合、シングルトン パターンを使用してこれを実現できます。

    // 定义一个单例类
    class Singleton {
          
          
      constructor(name) {
          
          
        this.name = name;
      }
      // 定义一个静态方法获取实例
      static getInstance(name) {
          
          
        // 如果实例不存在,则创建一个新的实例
        if (!this.instance) {
          
          
          this.instance = new Singleton(name);
        }
        // 返回实例
        return this.instance;
      }
    }
    
    // 测试
    const a = Singleton.getInstance('a');
    const b = Singleton.getInstance('b');
    console.log(a === b); // true
    console.log(a.name); // a
    console.log(b.name); // a
    
  • 工場出荷時のパターン

// 定义一个工厂类
class Factory {
    
    
  // 定义一个静态方法创建对象
  static create(type) {
    
    
    // 根据不同类型返回不同对象
    switch (type) {
    
    
      case 'A':
        return new A();
      case 'B':
        return new B();
      default:
        return null;
    }
  }
}

// 定义两个不同类型的类
class A {
    
    
  constructor() {
    
    
    this.name = 'A';
  }
}

class B {
    
    
  constructor() {
    
    
    this.name = 'B';
  }
}

// 测试
const a = Factory.create('A');
const b = Factory.create('B');
console.log(a instanceof A); // true
console.log(b instanceof B); // true
console.log(a.name); // A
console.log(b.name); // B
  • ビルダーパターン

ビルダー パターンは、複雑なオブジェクトの構築プロセスとプレゼンテーション プロセスを分離し、同じ構築プロセスで異なる表現を作成できるようにするデザイン パターンです。フロントエンド開発では、複雑なフォーム コンポーネントの作成や複雑なグラフ コンポーネントの作成など、複雑なオブジェクトを作成する必要があるシナリオによく遭遇します。ビルダー パターンを使用すると、複雑なオブジェクトの構築プロセスをクラスにカプセル化し、さまざまなプロパティと構成を設定するためのメソッドを提供し、最終的なオブジェクトを返すことができます。これにより、オブジェクトを作成するためにコンストラクターやオブジェクト リテラルを直接使用する必要がなくなり、コードの可読性と保守性が向上します。もちろん、この方法で記述するには tsx を使用することを強くお勧めします。これは、react または vue3+tsx を使用して実現できます。

// 定义一个表单组件类
class Form {
  constructor() {
    this.fields = []; // 表单字段列表
    this.title = ''; // 表单标题
    this.submitText = ''; // 提交按钮文本
  }
  // 定义一个渲染方法
  render() {
    // 返回一个vue组件对象
    return {
      template: `
        <div>
          <h1>{
   
   {title}}</h1>
          <div v-for="field in fields">
            <label>{
   
   {field.label}}</label>
            <input :type="field.type" :name="field.name" />
          </div>
          <button>{
   
   {submitText}}</button>
        </div>
      `,
      data() {
        return {
          title: this.title,
          fields: this.fields,
          submitText: this.submitText,
        };
      },
    };
  }
}

// 定义一个表单组件建造者类
class FormBuilder {
  constructor() {
    this.form = new Form(); // 创建一个新的表单组件对象
  }
  // 定义一个添加字段的方法
  addField(field) {
    this.form.fields.push(field); // 将字段添加到表单字段列表中
    return this; // 返回当前建造者对象,实现链式调用
  }
  // 定义一个设置标题的方法
  setTitle(title) {
    this.form.title = title; // 设置表单标题
    return this; // 返回当前建造者对象,实现链式调用
  }
  // 定义一个设置提交按钮文本的方法
  setSubmitText(text) {
    this.form.submitText = text; // 设置提交按钮文本
    return this; // 返回当前建造者对象,实现链式调用
  }
  // 定义一个获取最终表单组件对象的方法
  build() {
    return this.form.render(); // 返回最终的表单组件对象
  }
}

// 测试
const formBuilder = new FormBuilder();
const form = formBuilder.setTitle('注册表单')
                        .addField({ label: '用户名', type: 'text', name: 'username' })
                        .addField({ label: '密码', type: 'password', name: 'password' })
                        .addField({ label: '邮箱', type: 'email', name: 'email' })
                        .setSubmitText('注册')
                        .build();
new Vue({
  el: '#app',
  components: {
    form,
  },
});

構造タイプ

  • アダプターモード

アダプター パターンは、あるクラスまたはオブジェクトのインターフェイスを別のインターフェイスに変換し、本来互換性のないクラスまたはオブジェクトが連携できるようにする設計パターンです。フロントエンド開発では、さまざまなソースから API を呼び出したり、さまざまな形式でデータを処理したりするなど、さまざまなインターフェイスやデータ形式への接続が必要なシナリオに遭遇することがよくあります。アダプター パターンを使用すると、元のクラスまたはオブジェクトの変更を回避できますが、中間層を介してインターフェイスまたはデータ変換が実装され、コードの再利用性とスケーラビリティが向上します。

// 定义一个适配器类
class Adapter {
    
    
  constructor(adaptee) {
    
    
    this.adaptee = adaptee;
  }
  // 定义一个适配方法
  getData() {
    
    
    // 将适配对象的数据转换成目标格式
    const data = this.adaptee.data.map(item => ({
    
    
      id: item._id,
      name: item._name,
      value: item._value,
    }));
    // 返回目标对象
    return data
  }
}

// 定义一个适配对象
const adaptee = {
    
    
  data: [
    {
    
     _id: '1', _name: 'a', _value: '10' },
    {
    
     _id: '2', _name: 'b', _value: '20' },
    {
    
     _id: '3', _name: 'c', _value: '30' },
  ],
};

// 测试
const adapter = new Adapter(adaptee);
console.log(adapter.getData()); // [{ id: '1', name: 'a', value: '10' }, { id: '2', name: 'b', value: '20' }, { id: '3', name: 'c', value: '30' }]
  • デコレータパターン

装飾パターンは、オブジェクトに何らかの責任を動的に追加する、つまり追加の機能を追加するデザイン パターンです。これにより、元のオブジェクトを変更せずに元のオブジェクトをラップする装飾クラスを作成できるため、元のオブジェクトの機能を拡張または変更できます。利点は、元のオブジェクトを変更することなく、元のオブジェクトの機能拡張または変更を実現できることです。

// 定义一个抽象组件类
class Component {
    
    
  // 定义一个抽象方法
  operation() {
    
    
    throw new Error('Abstract method');
  }
}

// 定义一个具体组件类
class ConcreteComponent extends Component {
    
    
  // 实现抽象方法
  operation() {
    
    
    console.log('具体组件的操作');
  }
}

// 定义一个抽象装饰类
class Decorator extends Component {
    
    
  constructor(component) {
    
    
    super();
    // 持有一个组件对象的引用
    this.component = component;
  }
  // 实现抽象方法
  operation() {
    
    
    // 调用组件对象的方法
    this.component.operation();
  }
}

// 定义一个具体装饰类A
class ConcreteDecoratorA extends Decorator {
    
    
  // 实现抽象方法
  operation() {
    
    
    // 调用父类的方法
    super.operation();
    // 执行装饰器自己的操作
    console.log('装饰器A的操作');
  }
}

// 定义一个具体装饰类B
class ConcreteDecoratorB extends Decorator {
    
    
  // 实现抽象方法
  operation() {
    
    
    // 调用父类的方法
    super.operation();
    // 执行装饰器自己的操作
    console.log('装饰器B的操作');
  }
}

// 测试代码
const c = new ConcreteComponent();
const d1 = new ConcreteDecoratorA(c);
const d2 = new ConcreteDecoratorB(d1);
d2.operation();

行動的な

  • オブザーバーパターン

オブザーバー パターンは、1 対多の依存関係を定義する設計パターンで、オブジェクト (オブザーバー) の状態が変化すると、それに依存するすべてのオブジェクト (オブザーバー) に通知され、自動的に更新されます。フロントエンド開発では、カスタム イベント システムの実装や単純な MVVM フレームワークの実装など、イベント駆動型またはデータ バインディングを必要とするシナリオに遭遇することがよくあります。オブザーバー パターンを使用すると、オブジェクト間の疎結合が実現し、コードのスケーラビリティとテスト容易性が向上します。Vue の双方向バインディングはオブザーバー モードです。最初に dom で vmodel コマンドを使用します。変更が発生した場合は、バインディング値を変更するように親コンポーネントに通知します。

// 定义一个被观察者类
class Subject {
    
    
  constructor() {
    
    
    this.state = null; // 被观察者的状态
    this.observers = []; // 观察者列表
  }
  // 添加观察者方法
  attach(observer) {
    
    
    this.observers.push(observer);
  }
  // 移除观察者方法
  detach(observer) {
    
    
    const index = this.observers.indexOf(observer);
    if (index !== -1) {
    
    
      this.observers.splice(index, 1);
    }
  }
  // 更新状态方法
  setState(state) {
    
    
    this.state = state;
    this.notify();
  }
  // 通知观察者方法
  notify() {
    
    
    for (let observer of this.observers) {
    
    
      observer.update(this.state);
    }
  }
}

// 定义一个观察者类
class Observer {
    
    
  constructor(name) {
    
    
    this.name = name;
  }
  // 更新方法
  update(state) {
    
    
    console.log(`${
      
      this.name} received ${
      
      state}`);
  }
}

// 测试
const subject = new Subject();
const observer1 = new Observer('observer1');
const observer2 = new Observer('observer2');
subject.attach(observer1);
subject.attach(observer2);
subject.setState('hello');
subject.detach(observer1);
subject.setState('world');

要約する

デザイン パターンを合理的に使用すると、コードの可読性が向上し、開発のアイデアがより明確になるため、これらのデザイン パターンを完全に理解することは非常に有益です。

おすすめ

転載: blog.csdn.net/wz9608/article/details/131894685