JavaScript 设计模式
概念
设计模式可以被称为软件工程中对最常见问题的解决方案的详细记录。开发人员很难在某些人已经解决的问题上发表自己的想法。每个开发人员都渴望编写易于应用于不同问题、可维护、可读和可重用的产业级代码。这需要一种适当的代码结构机制或模式来加以考虑,因此解决这个挑战变得至关重要。这就是设计模式在特定情况下提供解决这些常见问题的基础的地方。
设计模式是必需的,因为它们不会随着时间的推移而改变,并能够与标准或高级别的应用实践结合在一起。
在本教程中,我们将学习这些设计模式在 JavaScript 中的应用。大多数 JavaScript 开发人员在创建应用程序时不知不觉地频繁使用设计模式。本教程将涵盖对最重要且经常使用的JavaScript设计模式的解释和示例。
设计模式的好处
它们是最好的解决方法: 所有开发人员都经常使用设计模式,因为他们知道这样会有效果。更重要的是,他们对设计模式非常熟悉,因为在实施之前它们已经进行了多次修订。
它们是可重用的: 设计模式描述了可在特定情况下进行修改以解决多个问题的可重用解决方案,因为它们不仅仅存在于一个问题。
它们是表达性的: 设计模式不需要进一步的解释,因为它们可以有效地将大问题解释为小片段。
它们增强沟通: 设计模式熟悉的开发人员可以为问题设置共同的目标,这有助于他们相互之间就潜在的威胁和解决方案进行沟通。
无需重构代码: 设计模式通常被称为各种问题的最佳解决方案。如果一个应用程序在编写时考虑了设计模式,那么生成的解决方案被认为是唯一的有效解决方案,因此不需要重构代码。
它们可以减少代码库的大小: 作为唯一的最佳解决方案,设计模式通过使用很少的代码行和非常小的占用空间来实现所需的解决方案,从而节省了宝贵的空间。
由于我们已经了解了JavaScript中设计模式的大部分基础知识,让我们通过编码示例来理解它们。
分类
JavaScript设计模式包括各种分类。给定的图像给出了所有模式的概述。
我们现在将使用合适的示例详细讨论这三种设计模式。
创建型设计模式
上述设计模式都是关于类的实例化。通过创建类和对象创建模式的划分,可以进一步详细说明。这种设计模式处理将类对象复杂性优化为简单易用的模式的创建机制。复杂的设计模式需要高级方法和时间,通过创建设计模式可以通过有效控制类的继承和对象的聪明委托来解决这个问题。上图已经显示了一些流行的设计模式。让我们讨论一些类别。
构造器模式
构造器模式是JavaScript中最简单、最现代、最流行的创建型设计模式的子类之一。该模式的主要目的是便捷构造器的创建。请考虑下面的示例:
class Automobile {
constructor(brand, mileage) {
this.brand = brand;
this.mileage = mileage;
this.getDetails = function () {
console.log(`{this.brand} gives{this.mileage}kmpl!`);
};
}
}
const Automobile1 = new Automobile('Mercedes',20.8);
Automobile1.getDetails();
输出
Mercedes gives 20.8 kmpl!
在这个示例中,我们定义了一个类/函数 Automobile ,它具有属性 brand 和 mileage 。在示例中使用的 getDetails() 方法将以上述输出中的格式打印出给定的汽车品牌和里程数。我们通过使用new关键字为给定的属性触发构造函数方法来实例化一个函数/类的对象。
原型模式
原型设计模式简单地意味着 克隆 。使用原型模式,我们可以通过克隆的方式根据现有对象的模板实例化新对象。然后通过原型继承来使用JavaScript的原型能力。通过下面的图片和代码示例可以更好地理解这个情况。
const cheetah = {
Speed: 120,
start() {
return 'Running';
},
stop() {
return 'Resting';
},
};
const cheetah1 = Object.create(cheetah, { Trainer: { value: 'John' } });
console.log(cheetah1.__proto__ === cheetah); // true
在这个示例中,我们已经实现了使用原型的使用 cheetah 的方式,然后使用 Object.create 方法克隆它来创建一个新的对象,创建一个常量 cheetah1 ,其中将根据ES6标准将 Trainer 的名称存储起来。
结构设计模式
这种设计模式主要涉及类和对象的组合或它们之间的关系。它具有结构上定义的机制,用于确保如果系统的一部分发生更改,整个系统不依赖于它并发生变化。为了实现这一点,需要确定使用继承来组合接口的类创建模式,并使用对象创建模式来定义推出新功能的方法。它还包含了上面图片中已经显示的各种类别。让我们讨论其中一些。
适配器设计模式
适配器设计模式主要用于不同设计的对象在单一接口中一起工作。假设我们正在构建一个接受JSON格式的结构和格式的库。我们需要有一个旧版的API以XML格式响应,并且稍后这个响应将用于生成图表,但图表只接受JSON对象。因此,编写了一个适配器函数将此XML转换为JSON,根据需要连接两种不同形式的对象。请参考下面的图片。
组合设计模式
这是最常用的结构性设计模式之一,我们将对象组合成 树状结构 ,然后将这些结构性树视为单个对象。以基于jQuery的示例来说明组合设计模式的结构。
$("#element").addClass("blur") // element is an id
$(".element").addClass("blur") // element is a class
$("div").addClass("blur") // native element div
$(".element.isActive").addClass("blur") // trying to access a DOM node
that has element as well as isActive class
$(".element h2").addClass("blur") // trying to access the native
element h2 which is inside a node with class element
在上述示例中,jQuery使得在选择的DOM节点上应用不同的方法变得非常容易,只需通过轻松访问组合即可。方法 addClass 用于隐藏实现的细节。它主要确保一组对象的行为就像它们是独立的对象一样。
行为设计模式
这种设计模式依赖于识别、实施和不同对象之间的通信的模式。行为模式主要关注通信,因为它们有助于确保不同的部分具有适当的信息同步。因此,它提高了通信的灵活性。
让我们讨论一些行为设计模式的类别。
责任链
这种设计模式主要用于构建一个系统,其中每个请求都通过一系列事件链传递并由处理程序处理。请求会被处理并从一条链传递到另一条链,或者被拒绝。这种设计模式对于使用顺序检查处理请求的系统非常适用。让我们以自动取款机为例。每当我们从ATM请求取款金额时,机器会处理请求并以一系列组合票据(500卢比、200卢比、100卢比)支付金额。
var Request = function(amount) {
this.amount = amount;
console.log("Request Amount:" +this.amount);
}
Request.prototype = {
get: function(bill) {
var count = Math.floor(this.amount / bill);
this.amount -= count * bill;
console.log("Dispense " + count + " $" + bill + " bills");
return this;
}
}
function run() {
var request = new Request(378); //Requesting amount
request.get(100).get(50).get(20).get(10).get(5).get(1);
}
在这个编码示例中,每当我们请求提取一定金额时,都会创建一个请求对象。这会引发一系列的调用,将对象链接在一起,并由事件处理程序处理特定的面额。最后,ATM可以发放满足处理请求的所需组合的钞票。
观察者模式
观察者模式是一种行为设计模式,其主要任务是定义一个 订阅机制 ,以通知多个观察者或对象发生的任何事件。这会提示事件处理程序执行事件驱动的响应。这个模式被普遍称为 发布/订阅 ,它缩写为 Pub/Sub ,表示 发布/订阅 之间的一系列一对一的对象依赖关系。这个设计模式用于推进良好的面向对象设计和增强 松散耦合 。
class Subject {
constructor () {
this.criticalNumber = 0
this.observers = []
}
addObserver (observer) {
this.observers.push(observer)
}
removeObserver (observer) {
let index = this.observers.findIndex(o => o === observer)
if (index !== -1) {
this.observers.splice(index, 1)
}
}
notify () {
console.log('Notifying observers about some important information')
this.observers.forEach (observer => {
observer.update(this.criticalNumber)
})
}
changeCriticalNumber () {
/* Changing the critical information */
this.criticalNumber = 42
/* Notifying the observers about this change */
this.notify()
}
}
class Observer {
constructor (id) {
this.id = id
}
update (criticalNumber) {
console.log(`Observer {this.id} - Received an update from the subject{criticalNumber}`)
}
}
在这个示例中,我们构建了一个 通知服务系统 ,其任务是通知用户有关订阅的信息。在这个系统中,我们创建了多个对象和事件侦听器来监听所谓的 订阅者 的更新。因此,我们在这里定义了两个类,分别是 主题 和 观察者 。这两个类需要保存关键信息和观察者列表。每当关键信息状态发生变化时,主题会使用上面示例代码中的notify方法通知所有观察者有关事件的信息。观察者类调用一个更新方法,该方法从主题调用通知请求。
结论
在本教程中,我们学习了JavaScript中各种常见设计模式以及它们如何轻松解决常见和复杂问题。我们还学习了各种设计模式的主要分类,包括 创建型、结构型 和 行为型 设计模式。创建型模式主要侧重于对象和类机制,以简化模式。结构型设计模式提供了一种更好的方法来解决问题并逐个解决它们,而行为型模式在建立跨活动的通信方面发挥了作用。我们还简要探讨了这三种设计模式的一些子分类以及它们在JavaScript中的应用。JavaScript设计模式在构建应用程序中起着重要作用。不同的分类定义了存在或可能发生的不同问题集,无论我们构建什么,这些模式都确保我们正在构建的东西是最好的。这是因为这些设计模式的最佳功能性能就是它们在JavaScript领域中针对每一个设计问题提供的最佳解决方案。