7个开发者必须知道的Nodejs 设计模式

好的,我已经收到了完整的内容,我将开始翻译。

设计模式是解决日常软件设计问题所必需的。这些问题可能包括:

  1. 维护数据库连接
  2. 创建和管理对象
  3. 通知一组订阅了特定实体的用户。

如果你试图自己想出解决方案,你很可能需要花费大量精力来解决这些问题,并设计这些问题的最优解决方案。

但其实你根本不需要这样做!

设计模式被引入是为了提供这些反复出现问题的解决方案。你所需要做的就是按照你的框架/语言实现模式,然后就可以运行了!

所以,让我们来看看你在使用 Node.js 时可能需要实现的最常见的设计模式。

1. 外观模式

首先,你需要了解外观模式。在 Node.js 应用程序中,这非常重要。

简单地说,外观设计模式通过提供统一的接口简化了复杂的子系统。

它充当一个单一的入口点,隐藏了所有内部实现细节,并促进了与底层功能的更轻松交互。它充当了一个门户,将客户端与复杂细节隔离开来。

例如,使用 Google 帐户登录网站的过程可以被认为是外观的一个现实世界例子。你只需要点击“使用 Google 登录”按钮,它就像是一个统一的登录选项。

你不需要担心输入你的电子邮件、密码或其他个人信息。

好处:

  • 简化接口:减少了开发人员与复杂系统的交互的认知负荷。
  • 减少耦合:将客户端代码与内部实现细节解耦,可以提高代码的可维护性和灵活性。
  • 提高可读性:将复杂逻辑封装在外观中,使代码更有组织性和可理解性。
  • 控制访问:在访问底层功能之前启用特定规则或验证。

考虑以下代码片段:


// 复杂模块  
class ComplexModule {  
  initialize() {  
    // 复杂的初始化逻辑  
  }  
  
  operation1() {  
    // 复杂操作1  
  }  
  
  operation2() {  
    // 复杂操作2  
  }  
}  
  
// 客户端代码  
const complexModule = new ComplexModule();  
complexModule.initialize();  
complexModule.operation1();  
complexModule.operation2();

这段代码展示了如果你将子系统通信放在模块外部时,你的应用程序可能如何交互。你将不得不手动执行所有操作,并且很可能会在维护代码时遇到问题。

然而,看看这段代码:


// 复杂模块的外观  
class ModuleFacade {  
  constructor() {  
    this.complexModule = new ComplexModule();  
  }  
  
  performOperations() {  
    this.complexModule.initialize();  
    this.complexModule.operation1();  
    this.complexModule.operation2();  
  }  
}  
  
// 客户端代码  
const moduleFacade = new ModuleFacade();  
moduleFacade.performOperations();

现在,你可以看到,我们不再在模块外部进行子模块初始化,而是封装在一个名为 performOperations 的函数中,该函数处理所有内部复杂子系统通信。

所以你得到了一种清晰的方法来处理复杂的通信树。

2. 单例模式

接下来,这是你可能会在一生中每天都使用的模式之一。有时,你需要确保某物只有一个实例。

例如,考虑一个数据库连接。在给定时间内,你是否需要多个数据库连接到你的应用程序?你能重用现有连接吗?

这就是单例模式的作用。它确保你的类有一个全局实例,可以使用静态方法访问。

好处:

  • 全局访问:从应用程序的任何地方方便地访问共享数据或功能的一种方式。
  • 资源管理:通过仅有一个实例来有效使用资源,如数据库连接、日志记录器或文件句柄。
  • 一致性:只影响单个实例,从而强制实现一致的行为。
  • 控制状态:通过集中的数据操作点简化状态管理。

下面是在 Node.js 中实现单例的方式:


class ConfigManager {  
  constructor() {  
    this.databaseConfig = { /* 数据库配置 */ };  
    this.apiKey = "你的_api_密钥";  
    // 其他应用程序范围的配置  
  }  
  
  static getInstance() {  
    if (!this.instance) {  
      this.instance = new ConfigManager();  
    }  
    return this.instance;  
  }  
  
  getDatabaseConfig() {  
    return this.databaseConfig;  
  }  
  
  getApiKey() {  
    return this.apiKey;  
  }  
  
  // 获取其他配置的附加方法  
}  
  
// 使用  
const configManager = ConfigManager.getInstance();  
  
// 访问配置  
const databaseConfig = configManager.getDatabaseConfig();  
const apiKey = configManager.getApiKey();

你可能有一个 Node.js 应用程序,与多个外部服务进行交互,每个服务都需要特定的配置参数。使用单例模式,你可以创建一个 ConfigManager 类,负责以集中的方式处理这些配置。

3. 适配器模式

接下来,你需要想象一个场景,你正在使用的 API 和你正在开发的客户端具有不兼容的 API。

例如,你可能有一个接受两个 props 的 React 组件:

  1. 名字

  2. 姓氏

但是你的 API 返回一个变量:

  1. 全名

所以,如果你处于无法更新 API Body 的位置,你将不得不使用你拥有的东西,并让你的应用程序工作。

这就是适配器模式的作用。

适配器模式弥合了不兼容接口之间的差距,使它们能够无缝地协同工作。

好处:

  • 互操作性:使具有不同接口的组件之间能够通信,促进系统集成和重用。
  • 松散耦合:将客户端代码与适配组件的具体实现解耦,提高了灵活性和可维护性。
  • 灵活性:允许在不修改现有代码的情况下适配新组件,只需创建新的适配器。
  • 可重用性:适配器实现可以为类似的兼容性需求重复使用,减少代码重复。

示例:

下面是适配器设计模式的一个简单编码示例。

旧系统

class OldSystem {  
  request() {  
    return "旧系统请求";  
  }  
}

新系统 & 适配器


class NewSystem {  
  newRequest() {  
    return "新系统请求";  
  }  
}  
  
class Adapter {  
  constructor(newSystem) {  
    this.newSystem = newSystem;  
  }  
  
  request() {  
    return this.newSystem.newRequest();  
  }  
}

客户端用法


// 使用旧系统  
const oldSystem = new OldSystem();  
console.log(oldSystem.request()); // 输出:旧系统请求  
  
// 使用带有新系统的适配器  
const newSystem = new NewSystem();  
const adapter = new Adapter(newSystem);  
console.log(adapter.request()); // 输出:新系统请求

4. 建造者模式

接下来,我们将看一种模式,你可以用它来构建对象,并使对象管理变得更容易。

建造者模式将复杂对象的构建与其表示分离。

这就像组装一台定制的 PC —— 逐个选择组件并构建最终产品。在 Node.js 中,建造者模式有助于以逐步、可定制的方式构建具有复杂配置的对象。

在这种设计模式中,你不是使用具有多个参数的构造函数,而是为对象的每个可选属性创建单独的方法(“构建器”)。这些方法通常返回类的当前实例 (this),以允许将它们链接在一起逐步构建对象。

好处:

  • 提高可读性:通过使用有意义的方法名称显式设置每个属性,代码更清晰。
  • 灵活性:只使用必要的属性构建对象,避免在未使用的字段中出现意外值。
  • 不可变性build() 方法通常创建一个新实例,而不是修改构建器,促进了不可变性和更容易的推理。
  • 错误处理:在建造者方法中更容易验证属性值并抛出错误,而不是在复杂的构造函数中。

示例:

下面是建造者设计模式的一个简单编码示例。


class UserBuilder {  
  constructor(name) {  
    this.name = name;  
    this.email = null;  
    this.address = null;  
  }  
  
  withEmail(email) {  
    this.email = email;  
    return this; // 方法链  
  }  
  
  withAddress(address) {  
    this.address = address;  
    return this;  
  }  
  
  build() {  
    // 验证并构建 User 对象  
    const user = new User({  
      name: this.name,  
      email: this.email,  
      address: this.address,  
    });  
    return user;  
  }  
}  
  
// 客户端代码  
const user1 = new UserBuilder('John')  
  .withEmail('john@example.com')  
  .withAddress('123 Main St.')  
  .build();  
  
console.log(user1); // 打印具有值的完整 User 对象


5. 工厂模式

工厂模式提供了一个创建对象的接口,但让子类能够改变所创建的对象的类型。

可以将其想象成一个制造工厂,有不同的生产线用于生产不同的产品。在 Node.js 中,工厂模式在创建对象时不指定其具体类别方面表现出色,促进了灵活性和可扩展性。

优点:

  • 解耦:客户端代码与特定对象创建逻辑解耦,提高了灵活性和可维护性。
  • 集中控制:只要工厂处理了更改,就可以轻松添加新的对象类型或修改现有对象类型,而不会影响客户端代码。
  • 灵活性:根据运行时条件或配置选择适当的对象,使你的代码更具适应性。
  • 封装性:对象创建细节被隐藏在工厂内部,提高了代码的可读性和可维护性。

示例:

下面是工厂设计模式的一个简单编码示例。

形状接口

// 形状接口  
class Shape {  
  draw() {}  
}

具体形状


// Shape 接口的具体实现  
class Circle extends Shape {  
  draw() {  
    console.log("绘制圆形");  
  }  
}  
  
class Square extends Shape {  
  draw() {  
    console.log("绘制正方形");  
  }  
}  
  
class Triangle extends Shape {  
  draw() {  
    console.log("绘制三角形");  
  }  
}

形状工厂


// ShapeFactory 类负责创建形状的实例  
class ShapeFactory {  
  createShape(type) {  
    switch (type) {  
      case 'circle':  
        return new Circle();  
      case 'square':  
        return new Square();  
      case 'triangle':  
        return new Triangle();  
      default:  
        throw new Error('无效的形状类型');  
    }  
  }  
}

客户端代码


// 客户端代码使用 ShapeFactory 创建形状  
const shapeFactory = new ShapeFactory();  
  
const circle = shapeFactory.createShape('circle');  
circle.draw(); // 输出: 绘制圆形  
  
const square = shapeFactory.createShape('square');  
square.draw(); // 输出: 绘制正方形  
  
const triangle = shapeFactory.createShape('triangle');  
triangle.draw(); // 输出: 绘制三角形

6. 原型模式

原型模式涉及通过复制现有对象(称为原型)来创建新对象。

它创建了主键的副本。当创建一个对象比复制一个现有对象更昂贵时,这是很有用的。

概念:

  1. 原型:定义具有所需属性和方法的基础对象。这充当了后续对象的蓝图。
  2. 克隆:通过复制原型来创建新对象,通常使用像 Object.create 这样的内置方法或自定义克隆逻辑。
  3. 定制:新创建的对象可以修改其个别属性,而不会影响原型。

优点:

  • 性能:复制现有对象通常比从头开始构造新对象更快,特别是对于复杂对象而言。
  • 内存效率:通过原型共享属性和方法,避免了冗余存储,减少了内存使用。
  • 动态修改:可以轻松地稍后扩展原型以向所有现有和未来实例添加新功能。

示例:

下面是原型设计模式的一个简单编码示例。

原型对象


// 原型对象  
const animalPrototype = {  
  type: '未知',  
  makeSound: function () {  
    console.log('一些通用的声音');  
  },  
  clone: function () {  
    return Object.create(this); // 使用 Object.create() 进行克隆  
  },  
};

自定义实例


// 基于原型的自定义实例  
const dog = animalPrototype.clone();  
dog.type = '狗';  
dog.makeSound = function () {  
  console.log('汪汪!');  
};  
  
const cat = animalPrototype.clone();  
cat.type = '猫';  
cat.makeSound = function () {  
  console.log('喵喵!');  
};

客户端代码


// 客户端代码使用自定义实例  
dog.makeSound(); // 输出: 汪汪!  
cat.makeSound(); // 输出: 喵喵!

7. 代理模式

代理模式充当另一个对象的替代或占位符,控制对它的访问。

这创建了一个中介对象(“代理”),它位于客户端和真实对象之间。这个代理控制对真实对象的访问,可能在达到目标之前或之后拦截和修改操作。

这允许你在不直接改变真实对象的实现的情况下添加额外的功能。代理模式对于延迟加载、访问控制或添加日志/调试功能至关重要。

优点:

  • 受控访问:在与真实对象交互之前强制执行权限或验证。
  • 额外功能:添加日志、缓存或安全等功能,而不改变对象本身。
  • 抽象:通过隐藏真实对象的实现细节,简化客户端代码。
  • 灵活性:在运行时动态更改目标对象或处理程序行为。

示例:

下面是代理设计模式的一个简单编码示例。

在所有这些示例中,我使用了 JavaScript 的 Proxy

象来为其他对象创建代理。要更深入地了解 JavaScript 内置的代理,你可以访问此处


const target = {  
  name: '艾丽斯',  
  sayHello() {  
    console.log(`你好,我叫 ${this.name}`);  
  },  
};  
  
const handler = {  
  get(target, prop, receiver) {  
    console.log(`访问属性 ${prop}`);  
    return Reflect.get(target, prop, receiver);  
  },  
  set(target, prop, value, receiver) {  
    console.log(`将属性 ${prop} 设置为 ${value}`);  
    return Reflect.set(target, prop, value, receiver);  
  },  
};  
  
const proxy = new Proxy(target, handler);  
  
proxy.name; // 输出: 访问属性 name  
proxy.sayHello(); // 输出: 访问属性 sayHello  
                  //      你好,我叫 艾丽斯  
proxy.name = '鲍勃'; // 输出: 将属性 name 设置为 鲍勃

结语

设计模式对每个开发者来说都是重要的学习内容。无论你是初学者还是专家,了解设计模式及其在现代软件开发中的用法都很重要,因为它可以让你更快地构建更好的软件。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 对于Node.js设计模式第三版pdf,这是一本关于Node.js设计模式的书籍,适合想要深入了解Node.js开发者和架构师阅读。 在这本书中,作者通过实例代码和详细解释,介绍了一些常见的设计模式,并提供了在Node.js环境下的应用实践。这些设计模式包括但不限于观察者模式、装饰器模式、工厂模式等等。通过学习这些设计模式,读者可以更好地组织和管理Node.js应用的代码和功能,提高代码的可读性、可维护性和可扩展性。 此外,本书还介绍了一些面向对象设计原则和开发实践,如单一职责原则、依赖倒置原则、模块化设计等,帮助读者理解如何在Node.js中进行良好的架构设计。同时,书中还提供了一些在实际项目中遇到的常见问题和解决方案,帮助读者更好地应对实际开发中的挑战。 总的来说,Node.js设计模式第三版pdf是一本深入学习和理解Node.js设计模式的实用书籍,对于提高Node.js应用的开发质量和技术水平具有很大的帮助。无论是初学者还是有一定经验的开发者,都可以从中获取到有用的知识和技巧。 ### 回答2: 《Node.js 设计模式 第三版》是由Mario Casciaro和Luciano Mammino合著的一本关于Node.js设计模式的书籍。这本书以深入浅出的方式介绍了Node.js中的常见设计模式,并提供了实际的示例代码和解决方案。 本书共分为四个部分。第一部分介绍了Node.js设计模式的基础概念,以及如何选择适当的设计模式来解决问题。第二部分详细介绍了Node.js中常见的设计模式,包括单例模式、工厂模式、观察者模式、装饰器模式等等。每个模式都有详细的代码示例和解释,方便读者理解和实践。 第三部分讨论了如何组织和管理大型Node.js项目中的设计模式。作者介绍了常见的架构模式,如分层架构、微服务架构和事件驱动架构,并解释了如何使用设计模式来支持这些架构。读者可以学习如何将设计模式应用于实际项目中,提高代码的可维护性和可扩展性。 第四部分探讨了一些高级主题,如测试驱动开发、性能优化和安全性。作者分享了一些实用的技巧和建议,帮助读者更好地应用设计模式解决实际问题。 总体而言,这本书是一本非常实用的Node.js设计模式指南。通过学习这本书,读者可以了解Node.js中常见的设计模式,并学习如何应用这些模式来解决实际问题。无论是初学者还是有经验的开发人员都可以从中受益。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值