如何使用三个Gang-of-Four设计模式在React中编写可重用的代码
设计模式为软件开发中的常见问题提供了可重复使用且经过验证的解决方案。使用设计模式可以节省无数的开发时间,并帮助更快地将功能交付给生产。
作为开发人员,了解设计模式以及如何使用它们来提高开发效率是至关重要的。
因此,本文将讨论Gang-of-Four设计模式以及如何使用React实现它们。
设计模式。四人帮
如前所述,设计模式有助于为软件开发中的典型设计问题提供独立于语言、可重复使用和可扩展的解决方案。四人帮指的是四位作者,他们写了一本书--《设计模式》。可重用的面向对象软件的要素》一书,从根本上提出了23种基于面向对象编程原则的设计模式。
四位作者将设计模式分为三组。
- 创造性模式.这些模式提供了实例化一个对象(创建一个组件)的方法,同时隐藏了创建逻辑。
- 结构模式.这些模式有助于有效定义类(组件)之间的关系。
- 行为模式.这些模式与组件之间的通信有关。
由于所有这些模式都是独立于语言的。开发人员可以将这些模式适应于像React这样的框架,以设计可扩展和可读的React组件。
用React实现设计模式
我们现在对设计模式有了一个简单的了解,以及为什么开发人员应该使用它们。因此,让我们看看如何在React应用程序中使用这些设计模式。
对于这个演示,我推荐使用React和TypeScript,因为它提供了一个静态类型的语言,具有接口、继承和类型支持,这有助于快速实现模式。
前提条件
在继续进行之前,确保你已经安装了Node.js。你可以运行node -v来确认安装。如果你已经成功安装了Node.js,你应该看到下面的输出。
图01 - 确认Node.js的安装
之后,运行下面的命令,创建一个名为 "react-design-patterns "的React TypeScript项目。
npx create-react-app react-design-patterns --template typescript
设计模式1:Singleton
什么是Singleton?
Singleton是一种创建性的设计模式,它可以确保一个类只有一个实例,并且只有一个访问点。
你什么时候应该使用Singleton?
例如,假设一个React应用程序利用一个全局配置对象来保存登录的用户信息。理想情况下,应用程序必须重新使用这些信息,以便在整个应用程序中获得当前用户的信息。
这是一个完美的场景,开发者可以使用单子模式。
用React实现Singleton
在实现单子模式时,我们必须解决两个方面的问题:
- 该对象必须有一个单一的实例
- 它必须只能用一个点来访问。
通过React,开发者可以使用自定义管理模块来满足这两个条件。例如,考虑下图所示的代码。
// user type
上面的片段显示了一个TypeScript模块,它使用两个方法来管理一个单实例的私有变量--loggedInUserStore的状态:getUserInformation--检索单实例,initializeUser--配置单实例。
这个模块提供了一个管理全局用户信息的单子方法。要在一个组件中使用这个模块,请导入动作并调用方法,如下图所示。
import { useEffect, useState } from "react";
上面的片段显示了一个检索单一实例的组件。
import { useEffect } from "react";
上面的片段显示了在useEffect里面配置的单用户实例。
图02:通过Singleton模式的预期结果
单子模式的优点
- 使用单子使代码具有可扩展性和可维护性
- 它避免了多个组件之间可能的代码重复。
单子模式的缺点
- 使用单子的主要缺点是,它使你的代码的可测试性降低,因为单子的全局状态在单元测试之间被保留下来。
设计模式2:观察者
什么是观察者?
观察者是一种行为模式,它有助于定义一个订阅机制,以通知观察者(组件)关于被观察对象的任何变化。
什么时候应该使用观察者?
在React应用中使用观察者的最合适的用例是当应用依赖于浏览器事件时。例如,假设一个React应用程序有一个组件需要根据互联网的可用性来切换其功能。该组件可以订阅浏览器的internet(主题)事件,获得变化的通知,然后相应地更新其状态。
在React中实现观察者
在实现观察者时:
- 组件必须首先订阅事件。
- 然后,当组件解除挂载时,要确保取消对事件的订阅。
考虑下图所示的代码。
import { useEffect, useState } from "react";
上面显示的片段显示了React中观察者的实现。首先,它用两个主题(在线,和离线事件)创建了两个订阅。当主体通知任何变化时,回调函数被执行以更新组件的状态。
观察者模式的优点
- 它解耦了主体和观察者之间的代码,因此允许更出色的可维护性。
- 多个观察者可以在任何时候订阅和取消订阅主体。
观察者模式的缺点
- 如果订阅没有被取消,React可能会继续监听变化,导致内存泄漏,并出现性能下降。
设计模式3: Facade
什么是Facade模式?
Facade是一种结构模式,旨在提供一种简化的方式,通过单一的API与多个组件交互。此外,它隐藏了内部操作的复杂性,从而使代码更具可读性。为了实现这种模式,我们需要接口和类。但是,我们可以利用这种模式的基本原则,将其应用于React中。
你应该在什么时候使用facade?
当应用变得复杂时,你可以选择在React应用中实现门面模式。例如,在React中加入facade模式的一个很好的用例是在管理组件状态时。
例如,你可能有一个管理应用程序用户的组件(添加、删除、获取、获取一个)。一般来说,这将导致许多状态变量和HTTP调用,使代码变得杂乱无章,从而降低其可读性。请看下面的片段。
export const NoFacade: FC = () => {
乍一看,这段代码是不可读的,因为它由复杂的HTTP请求和状态变量组成。然而,开发者可以将复杂的HTTP请求和状态变量分组,并公开一个单一的API来操作这些数据。这时,开发者可以使用facade模式。
在React中,开发者可以通过将复杂的代码分组到一个自定义的Hook中,并公开Hook方法供客户端使用来完成同样的工作。
在React中实现facade
让我们改进前面的片段,用一个自定义Hook代替复杂的代码。自定义Hook将包含创建、获取和删除用户的方法。组件可以使用这些方法来消费这些功能,而不需要查看按顺序执行的复杂代码。
自定义片段的代码如下所示。
import axios from "axios";
上面的片段强调了管理用户管理的自定义Hook。它返回一组方法,组件可以用来与API进行交互。
该组件的更新代码显示如下。
export const Facade: FC = () => {
上面的代码片段突出显示了该组件的更新代码。正如你所观察到的,自定义Hook创建了一个更可读、更不复杂的代码,并且完全隐藏了组件中所有复杂的业务逻辑。
Facade模式的优点
- 它使代码可重复使用,这有助于避免代码的重复。
- 它将组件的业务逻辑解耦,允许开发者为这些功能编写单元测试。
Facade模式的缺点
- 很难重构现有的代码并将其封装在一个自定义的Hook中。但是,当正确实施时,该模式可以创建高度可重复使用和可扩展的代码。
总结
本文介绍了设计模式,以及开发者如何利用React的设计模式来改善前端设计。
我希望你觉得这篇文章对你有帮助。
谢谢你的阅读。