前端设计模式:开发-关闭原则OCP

118 阅读7分钟

定义

设计模式中的开闭原则(Open-Closed Principle, OCP)的定义是:软件中的对象(业务模块、类、方法等)对于扩展应该是开放的,对于修改应该是封闭的。这意味着一个软件实体(如类、模块、函数等)应该能够在不修改其源代码的情况下进行扩展,以适应新的需求或变化。

开闭原则强调软件设计应该具有一定的灵活性和可扩展性,同时保持系统的稳定性和可维护性。具体来说,它包含以下几个方面的要求:

对扩展开放:软件实体应该能够支持新的功能或行为的扩展,而不需要修改现有的代码。这通常通过抽象和继承机制来实现,例如使用接口或抽象类来定义一组通用的行为,然后通过具体的子类来实现这些行为。

对修改封闭:一旦软件实体被设计并实现,其内部的实现细节应该保持稳定,不应该因为新的需求或变化而频繁修改。如果需要进行修改,也应该尽量通过扩展新的组件或功能来实现,而不是修改现有的代码。

面向抽象编程:开闭原则的实现需要依赖于面向抽象编程的思想。通过定义清晰的接口或抽象类,我们可以将系统的各个部分解耦,使得它们之间的依赖关系更加灵活和可控。

提高可复用性和可维护性:遵循开闭原则设计的软件系统具有更高的可复用性和可维护性。因为系统的各个部分都是相对独立的,所以它们可以更容易地被重用和维护。

在JavaScript中,开闭原则同样具有重要的应用价值。例如,在设计一个Web应用时,我们可以使用模块化、组件化等技术手段来实现开闭原则。通过将应用拆分成多个独立的模块或组件,并定义清晰的接口或API来约束它们之间的交互关系,我们可以使得应用更加灵活和可扩展。

需要注意的是,开闭原则并不是一种强制性的规范,而是一种指导性的设计原则。在实际开发中,我们需要根据项目的具体需求和实际情况来灵活运用这一原则,以确保软件系统的质量和效益。

在JavaScript中 开闭原则的应用

在JavaScript中,开闭原则(Open-Closed Principle, OCP)的应用主要体现在提高代码的可维护性、可扩展性和可复用性上。以下是一些具体的应用方式:

抽象化: 通过定义接口或抽象类来抽象出软件系统的稳定部分和变化部分。在JavaScript中,虽然没有传统意义上的接口和抽象类(ES6之前),但可以通过函数、对象字面量、高阶函数等方式来实现抽象。例如,可以定义一个函数或对象来封装一组通用的行为,然后通过不同的参数或属性来实现不同的具体行为。

模块化: 将JavaScript代码拆分成多个独立的模块,每个模块都负责完成特定的功能。模块之间通过接口或API进行通信,而不是直接访问对方的内部实现。这样,当需要扩展新功能时,只需要添加新的模块或修改现有模块的接口,而不需要修改模块的内部实现。

继承和多态: 在JavaScript中,虽然继承不是必须的(因为JavaScript是一种基于原型的语言),但可以通过构造函数、原型链或ES6中的class关键字来实现继承。通过继承,可以创建出具有共同属性和方法的子类,并在子类中覆盖或扩展父类的方法。这样,当需要为系统添加新功能时,可以通过创建新的子类来实现,而不需要修改父类的代码。

策略模式: 策略模式是一种常用的设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。在JavaScript中,可以通过函数或对象来实现策略模式。每个策略都封装了一种算法,并通过一个共同的接口来调用它们。当需要改变算法时,只需要替换掉相应的策略对象即可,而不需要修改调用它们的代码。

回调函数和事件监听: 在JavaScript中,回调函数和事件监听是实现开闭原则的一种有效方式。通过将容易变化的部分封装在回调函数中,并将这些回调函数传递给稳定的函数或对象,可以在不修改稳定部分代码的情况下扩展新功能。例如,可以定义一个处理HTTP请求的函数,它接受一个回调函数来处理请求的响应。这样,当需要处理不同类型的响应时,只需要提供不同的回调函数即可。

高阶函数: 高阶函数是JavaScript中的一个重要特性,它允许函数作为参数传递给其他函数,或者允许函数返回另一个函数。通过高阶函数,我们可以将复杂的逻辑封装在函数中,并通过传递不同的参数或函数来实现不同的行为。这样,当需要扩展新功能时,可以通过添加新的高阶函数来实现,而不需要修改现有的函数代码。

组件化: 现代JavaScript开发强调组件化,每个组件都是自封闭的、独立的,可以轻松地添加或更新功能,而不用担心会影响到系统的其他部分。这符合开闭原则的核心思想,即软件实体应该对扩展开放、对修改关闭。通过组件化,我们可以将复杂的系统拆分成多个简单的组件,并通过接口或API进行通信,从而提高系统的可维护性和可扩展性。

需要注意的是,虽然开闭原则是一个非常重要的设计原则,但在实际开发中也需要根据项目的具体需求和实际情况来灵活运用。有时候,过分追求开闭原则可能会导致代码过于复杂或难以维护。因此,在遵循开闭原则的同时,也需要权衡代码的复杂度、可读性和可维护性等因素。

  • 开闭原则OCP(Open Closed Principle)
  • 定义:Software entities (classes, modules, functions) should be open for extension but closed for modification
  • 做加法,不要做乘法

摘录:

修改已经存在的源代码是存在很大风险的,尤其是项目上线运行一段时间后,开发人员发生变化,这种风险可能就更大。

比如已经有个类样式,还是全局的 你是直接改这个类样式,还是再加个类,加样式呢。或者把全局变为局部样式

开闭原则提高系统的可维护性和代码的重用性。

啥是扩展:抽象接口的实现类 抽象类的继承

封装变化、降低耦合

实现开放封闭的核心思想就是面对抽象编程,而不是面对具体编程,因为抽象相对稳定。 让类依赖于固定的抽象,所以对修改是封闭的;而通过面向对象的继承和多态机制,可以实现对抽象体的继承,通过覆写其方法来改变固有行为,实现新的扩展方法,所以对于扩展就是开放的。这是实施开放封闭原则的基本思路。

常用的设计模式主要有模板方法(Template Method)设计模式策略(Strategy)设计模式。而封装变化,是实现这一原则的重要手段,将经常发生变化的部分封装为一个类。

参考文档: zhuanlan.zhihu.com/p/24269134