适配器模式应用场景
Traditionally, structural patterns are described as the thing that helps simplify the process of object composition. Its purpose is to help identify the relationship between different objects, making sure that if something changes within the system, it doesn’t force the entire system to change with it.
传统上,结构模式被描述为有助于简化对象组成过程的事物。 其目的是帮助识别不同对象之间的关系,确保如果系统中发生某些更改,则不会强制整个系统随之更改。
Let’s begin with the adapter pattern.
让我们从适配器模式开始。
适配器图案 (Adapter Pattern)
Imagine you have to build another cart solution for your boss. But there’s a caveat — you’re not allowed to change the original code that spits out the cart data. Why? Because no one knows how that change will impact the rest of the application. It’s a fragile piece of art that no one wants to touch, not yet, or ever. The situation is one of those moments where you just don’t have the time or mental space to question it. You’ll just have to accept that it’s going to be like this until you fully transition out of your legacy systems.
想象一下,您必须为老板构建另一个购物车解决方案。 但是需要注意的是-您不能更改用于吐出购物车数据的原始代码。 为什么? 因为没有人知道这一更改将如何影响应用程序的其余部分。 这是一件易碎的艺术品,没人愿意,现在甚至永远都不想碰。 这种情况就是您没有时间或精力去质疑它的时刻之一。 您只需要接受这种情况就可以了,直到您完全退出旧系统为止。
But the process of transitioning is going to take a long time and you don’t want your code to be too intertwined with the old code. What do you do?
但是过渡过程将花费很长时间,并且您不希望您的代码与旧代码过于纠结。 你是做什么?
In situations like these, the adapter pattern comes in handy.
在这种情况下,可以使用适配器模式。
The adapter pattern introduces an intermediary piece of code that makes two parts of a system compatible with one another. It also injects an element of lose coupling by keeping the two pieces of code separate. It means that you can write your code however you want without the need to take the other piece of code into consideration. Your adapter code will do the necessary translation and give you what you need and in whatever format you want.
适配器模式引入了一段中间代码,使系统的两个部分相互兼容。 它还通过使两段代码分开来注入失去耦合的元素。 这意味着您可以根据需要编写代码,而无需考虑其他代码。 您的适配器代码将进行必要的翻译,并为您提供所需的内容以及所需的任何格式。
When one side of the code changes, you only need to change the adapter for that particular part rather than both sides of the application.
当代码的一侧发生更改时,您只需要更改该特定部分的适配器,而无需更改应用程序的两侧。
那么,您到底如何用JavaScript编写适配器模式呢? (So how exactly do you write an adapter pattern in JavaScript?)
There’s no actual way to write it as such. It’s more a conceptual idea and the code itself is dependent on the situation you’re trying to bridge. It’s a process of abstracting the data you need from an external or 3rd party object. To do this, we often create an interface to represent our adapter and create the connections required between the two parts.
没有实际的方式可以这样写。 这更多是一个概念性想法,代码本身取决于您要弥合的情况。 这是从外部或第三方对象中提取所需数据的过程。 为此,我们经常创建一个接口来表示我们的适配器,并在两个部分之间创建所需的连接。
One thing to take note is that the adapter only has a single direction of dependency. The adapter only consumes what it aims to translates. In most cases, it’s the legacy API or 3rd party libraries. It doesn’t do anything else other than form a connection between two sides of an application. It should not contain any business logic.
需要注意的一件事是,适配器仅具有单个方向的依赖性。 适配器仅消耗其要翻译的内容。 在大多数情况下,它是旧版API或第三方库。 除了在应用程序的两侧之间建立连接之外,它没有做任何其他事情。 它不应包含任何业务逻辑。
Conventionally, an adapter sits in a utils
folder and then imported into a file when it's needed. However, it can also be a stand alone function.
按照惯例,适配器位于utils
文件夹中,然后在需要时导入到文件中。 但是,它也可以是独立功能。
Let’s take a look at the exported class
version first.
让我们首先看一下导出的class
版本。
//your original cart data service
//this is just a hypothetical name
import { v4 as cart } from "cartServiceV4"
class CartServiceAdapter {
getCart(){
//some cart code
//using data from the imported cart service
//can transform the original output to suit your needs
return cart;
}
removeItemFromCart(){
//some cart code
return cart;
}
//etc
}
export default new CartService();
import
brings in the thing you want to translate. export
makes your CartServiceAdapter
available for usage by anything that imports it.
import
会带来您要翻译的内容。 export
使CartServiceAdapter
可供导入它的任何对象使用。
When you need the cart
data, you just need to import your adapter into your code using import
.
当你需要的cart
的数据,你只需要使用导入你的适配器插入你的代码import
。
import cart from "./utils/CartServiceAdapter"
console.log(cart.getCart());
What this hypothetical code looks like in diagram form:
该假设代码以图表形式显示:
This means that rather than forcing your new cart code to conform to the needs of the mysterious original code, you can just write an adapter that translates the original to fit with the new code. As a result, you’re free to construct your code however you want.
这意味着您不必编写新的购物车代码来满足神秘原始代码的需求,而只需编写一个适配器即可转换原始代码以使其适合新代码。 结果,您可以随意构建自己的代码。
You can also write your adapters as normal functions rather than a class. There are no restrictions on how you write it. Here’s an example of what a possible interface can look like as a function:
您也可以将适配器编写为普通函数,而不是类。 编写方式没有任何限制。 这是一个可能的界面作为函数的示例:
//original cart data that cannot be changed at source
//let's pretend this is from a mysterious data service
//we have no direct access to this
var cart = [
{item: "vintage clock", sku: 9284, value: 15.99},
{item: "motivate carts", sku: 9232, value: 19.99}
]
//old interface pulls in data from mysterious data service
//we're not allowed to touch this
function Cart(){
return this.cart;
}
//our adapter code to translate the data
//prevents us from consuming the Cart() directly
function CartAdapter(){
var originalCart = Cart();
var adapterCart = originalCart.map(function(obj){
return {
item: obj.item,
productId: obj.sku,
price:obj.value
}
});
return adapterCart;
}
//now we can use the result of the CartAdapter() however we want
//changes in Cart() will result in only a change in the adapter
//the rest of the code remains unimpacted once the adapter is fixed
console.log(CartAdapter());
In the example above, we’re pretending that the cart
data format cannot be changed that it's being pulled into the application via the Cart()
function. Cart()
can be seen as the old interface that we don't want to touch. CartAdapter()
as the intermediary piece of code that prevents us from consuming Cart()
directly. When something changes in Cart()
, we only need to change CartAdapter()
rather than the family of functions that may be consuming the data from Cart()
directly.
在上面的示例中,我们假装无法将cart
数据格式更改为通过Cart()
函数将其拖入应用程序。 Cart()
可以看作是我们不想触摸的旧界面。 CartAdapter()
作为中间代码段,可防止我们直接使用Cart()
。 当Cart()
某些内容发生变化时,我们只需要更改CartAdapter()
而无需更改可能直接使用Cart()
的数据的函数族。
The adapter pattern comes in handy for when you’re working across multiple platforms, data sources, libraries and frameworks. It fills in the gaps that are caused by the various requirements and differences in environments. The context of the original code may make sense, but not in the use case that it needs to be consumed. The adapter pattern makes this possible by bridging the different sources together.
当您跨多个平台,数据源,库和框架工作时,适配器模式非常有用。 它填补了各种要求和环境差异所造成的空白。 原始代码的上下文可能有意义,但在用例中不需要使用它。 适配器模式通过将不同的源桥接在一起使之成为可能。
翻译自: https://medium.com/madhash/adapter-pattern-in-a-nutshell-2aafb4099a23
适配器模式应用场景