编程 前端开发中常用的设计模式

2024-11-19 07:38:07 +0800 CST views 461

前端常用设计模式汇总

设计模式简介

根据设计模式的经典参考书《Design Patterns - Elements of Reusable Object-Oriented Software》(中文译名:设计模式 - 可复用的面向对象软件元素),设计模式主要分为三大类:创建型模式结构型模式行为型模式。本文将简述前端开发中常用的一些设计模式,帮助你在实际项目中应用这些模式,提升代码质量。

1. 设计模式的目的

设计模式旨在提高代码的封装性、可读性、重用性、可扩展性和可靠性,使项目更易于开发、维护和扩展。

2. 设计模式的分类

  • 创建型模式:主要关注对象的创建方式。

    • 工厂模式
    • 单例模式
  • 结构型模式:主要关注类和对象的组合。

    • 外观模式
    • 代理模式
  • 行为型模式:主要关注对象之间的通信和协作。

    • 策略模式
    • 迭代器模式
    • 观察者模式
    • 中介者模式
    • 访问者模式

3. 创建型模式

3.1 工厂模式

目的:定义一个创建对象的接口,可以方便地创建不同类型的对象,集中管理对象创建逻辑。

应用场景:需要根据不同条件创建不同实例时。

代码示例

class ProductA {
  constructor(name) {
    this.name = name;
  }
  produce() {
    console.log("produce A is producing..");
    return `produce A: ${this.name}`;
  }
}

class ProductB {
  constructor(name) {
    this.name = name;
  }
  produce() {
    console.log("produce B is producing..");
    return `product B: ${this.name}`;
  }
}

class Factory {
  create(type, name) {
    switch (type) {
      case "A":
        return new ProductA(name);
      case "B":
        return new ProductB(name);
      default:
        throw new Error("不存在的产品类型");
    }
  }
}

// 使用
const factory = new Factory();
const productA = factory.create("A", "productA");
const productB = factory.create("B", "productB");
productA.produce(); // produce A is producing..
productB.produce(); // produce B is producing..

3.2 单例模式

目的:确保全局只有一个实例对象。

应用场景:需要全局唯一的对象,比如配置管理、日志记录等。

代码示例

class Singleton {
  constructor() {
    if (typeof Singleton.instance === "object") {
      return Singleton.instance;
    }
    this.name = "Singleton";
    Singleton.instance = this;
    return this;
  }
}
const singleton1 = new Singleton();
const singleton2 = new Singleton();
console.log("对比:", singleton1 === singleton2); // true

4. 结构型模式

4.1 外观模式

目的:通过为多个复杂的子系统提供一个一致的接口,隐藏系统的复杂性。

应用场景

  • 为复杂的模块或子系统提供一个统一的访问接口。
  • 子系统之间相对独立,外界不需要直接与子系统交互。

代码示例

// 绑定事件
function addEvent(element, event, handler) {
  if (element.addEventListener) {
    element.addEventListener(event, handler, false);
  } else if (element.attachEvent) {
    element.attachEvent("on" + event, handler);
  } else {
    element["on" + event] = fn;
  }
}

// 取消绑定
function removeEvent(element, event, handler) {
  if (element.removeEventListener) {
    element.removeEventListener(event, handler, false);
  } else if (element.detachEvent) {
    element.detachEvent("on" + event, handler);
  } else {
    element["on" + event] = null;
  }
}

4.2 代理模式

目的:通过一个代理对象控制对另一个对象的访问。

应用场景

  • 需要在访问某个对象时做一些额外操作,如延迟加载、缓存等。
  • 直接访问某对象会导致一些不便或开销,可以通过代理模式优化访问。

代码示例

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 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

5. 行为型模式

5.1 策略模式

目的:定义一系列算法,将它们封装起来,并且使它们可以互相替换,优化代码中的 if-else 分支。

应用场景:需要在运行时选择不同的算法。

代码示例

function Strategy(type, a, b) {
  const Strategyer = {
    add: function (a, b) {
      return a + b;
    },
    subtract: function (a, b) {
      return a - b;
    },
    multip: function (a, b) {
      return a * b;
    },
  };
  return Strategyer[type](a, b);
}

5.2 迭代器模式

目的:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示。

应用场景:需要对某个对象进行操作,但是又不能暴露内部细节。

代码示例

const item = [1, 2, 3, 4, 5];
function Iterator(items) {
  this.items = items;
  this.index = 0;
}
Iterator.prototype = {
  hasNext: function () {
    return this.index < this.items.length;
  },
  next: function () {
    return this.items[this.index++];
  }
};

// 使用
const iterator = new Iterator(item);
while (iterator.hasNext()) {
  console.log('迭代器:', iterator.next()); // 1, 2, 3, 4, 5
}

5.3 观察者模式

目的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

应用场景:需要在对象状态变化时通知多个依赖对象。

代码示例

// 被观察者
function Subject() {
  this.observers = [];
}
Subject.prototype = {
  // 订阅
  subscribe: function (observer) {
    this.observers.push(observer);
  },
  // 取消订阅
  unsubscribe: function (observerToRemove) {
    this.observers = this.observers.filter(observer => observer !== observerToRemove);
  },
  // 事件触发
  fire: function () {
    this.observers.forEach(observer => observer.call());
  }
};

// 使用
const subject = new Subject();
const observer1 = () => {
  console.log('observer1 触发了...');
};
const observer2 = () => {
  console.log('observer2 触发了...');
};
subject.subscribe(observer1);
subject.subscribe(observer2);
subject.fire(); // observer1 触发了...    observer2 触发了...

5.4 中介者模式

目的:通过一个中介对象来封装一系列对象之间的交互,从而减少对象之间的耦合。

应用场景:多个对象之间存在复杂的交互,使用中介者模式可以降低对象之间的耦合度。

代码示例

// 聊天室成员类
class Member {
  constructor(name) {
    this.name = name;
    this.chatroom = null;
  }
  // 发送消息
  send(message, toMember) {
    this.chatroom.send(message, this, toMember);
  }
  // 接收消息
  receive(message, fromMember) {
    console.log(`${fromMember.name} to ${this.name}: ${message}`);
  }
}

// 聊天室类
class Chatroom {
  constructor() {
    this.members = {};
  }
  // 增加成员
  addMember(member) {
    this.members[member.name] = member;
    member.chatroom = this;
  }
  // 发送消息
  send(message, fromMember, toMember) {
    toMember.receive(message, fromMember);
  }
}

// 使用
const chatroom = new Chatroom();
const John = new Member('John');
const Tom = new

 Member('Tom');
chatroom.addMember(John);
chatroom.addMember(Tom);
John.send('Hi Tom!', Tom); // John to Tom: Hi Tom!

5.5 访问者模式

目的:在不改变数据结构的前提下,增加新的操作。

应用场景:需要对一个对象结构中的对象进行不同的操作,而不影响这些对象的类。

代码示例

// 财务报表类
class Report {
  constructor(income, cost, profit) {
    this.income = income;
    this.cost = cost;
    this.profit = profit;
  }
}

// 老板类
class Boss {
  get(data) {
    console.log(`老板访问报表数据,盈利:${data}`);
  }
}

// 财务人员类
class Account {
  get(num1, num2) {
    console.log(`财务人员访问报表数据,收入:${num1},支出: ${num2}`);
  }
}

// 访问者类
function visitor(data, person) {
  const handle = {
    Boss: function (data) {
      person.get(data.profit);
    },
    Account: function (data) {
      person.get(data.income, data.cost);
    }
  };
  handle[person.constructor.name](data);
}

// 使用
const report = new Report(1000, 500, 200);
visitor(report, new Account()); // 财务人员访问报表数据,收入:1000,支出: 500
visitor(report, new Boss()); // 老板访问报表数据,盈利:200

以上是一些常见的设计模式的介绍和应用示例。这些模式在开发中可以帮助解决常见问题,提升代码的结构和可维护性。了解并掌握这些设计模式,将有助于你在前端开发中写出更加优雅和高效的代码。

复制全文 生成海报 前端开发 设计模式 软件工程

推荐文章

Vue3中的响应式原理是什么?
2024-11-19 09:43:12 +0800 CST
IP地址获取函数
2024-11-19 00:03:29 +0800 CST
PHP 微信红包算法
2024-11-17 22:45:34 +0800 CST
什么是Vue实例(Vue Instance)?
2024-11-19 06:04:20 +0800 CST
PHP 的生成器,用过的都说好!
2024-11-18 04:43:02 +0800 CST
markdown语法
2024-11-18 18:38:43 +0800 CST
mendeley2 一个Python管理文献的库
2024-11-19 02:56:20 +0800 CST
前端如何优化资源加载
2024-11-18 13:35:45 +0800 CST
Vue3如何执行响应式数据绑定?
2024-11-18 12:31:22 +0800 CST
CSS 奇技淫巧
2024-11-19 08:34:21 +0800 CST
Vue3中如何实现响应式数据?
2024-11-18 10:15:48 +0800 CST
开源AI反混淆JS代码:HumanifyJS
2024-11-19 02:30:40 +0800 CST
程序员茄子在线接单