桥接模式和适配器模式的区别
桥接模式和适配器模式有什么区别?
What is the difference between the Bridge and Adapter patterns?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
桥接模式和适配器模式有什么区别?
What is the difference between the Bridge and Adapter patterns?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(10)
实际上,当您有现有代码(无论是第三方代码还是内部代码)但超出您的控制范围或无法更改以完全满足要求时,适配器模式非常有用。例如,我们有一个超级武器阵列,它可以控制一系列末日设备,
但我们意识到我们的武器库中已经有一个核装置,这远远早于武器界面的转换。真的很喜欢它在这里工作...所以我们做什么...将它插入!
NukeWeaponsAdaptor - 基于我们的 Nuke 类,但是导出武器界面,现在我们肯定可以摧毁世界了。 。
Bridge 模式是你预先实现的,如果你知道你有两个正交的层次结构,它提供了一种将接口和实现解耦的方法 这样您就不会获得大量的类。 假设您有:
MemoryMappedFile 和 DirectReadFile 类型的文件对象。假设您希望能够从各种来源读取文件(可能是 Linux 与 Windows 实现等)。 Bridge 可以帮助您避免遇到以下问题:
MemoryMappedWindowsFile
内存映射Linux文件
直接读取Windows文件
直接读取Linux文件
Effectively, the Adapter pattern is useful when you have existing code, be it third party, or in-house, but out of your control, or otherwise not changeable to quite meet the interface you need it to. For instance, we have a SuperWeaponsArray which can control a fine array of doomsday devices.
Great. Except we realize we have a nuclear device in our arsenal that vastly predates the conversion to the Weapon interface. But we'd really like it to work here... so what do we do... wedge it in!
NukeWeaponsAdaptor - based off of our Nuke class, but exporting the Weapon interface. Sweet, now we can surely destroy the world. It seems like bit of a kludge, but it makes things work.
The Bridge pattern is something you implement up front - if you know you have two orthogonal hierarchies, it provides a way to decouple the interface and the implementation in such a way that you don't get an insane number of classes. Let's say you have:
MemoryMappedFile and DirectReadFile types of file objects. Let's say you want to be able to read files from various sources (Maybe Linux vs. Windows implementations, etc.). Bridge helps you avoid winding up with:
MemoryMappedWindowsFile
MemoryMappedLinuxFile
DirectReadWindowsFile
DirectReadLinuxFile
http://en.wikipedia.org/wiki/Adapter_pattern
适配器模式更多的是让你的适配器现有代码可用于较新的系统或界面。
如果您有一组公司标准的 Web 服务 API,希望将其提供给另一个应用程序的现有可扩展性接口,则您可以考虑编写一组适配器来执行此操作。请注意,存在一个灰色区域,这更多的是关于如何在技术上定义模式,因为其他模式(例如外观)是相似的。
http://en.wikipedia.org/wiki/Bridge_pattern
桥接模式将允许您可能有算法或系统的替代实现。
虽然不是经典的桥接模式示例,但想象一下,如果您有一些数据存储的实现:一个在空间上高效,另一个在原始性能上高效......并且您有一个在应用程序或框架中提供这两种实现的业务案例。
就您的问题“我可以在哪里使用哪种模式”而言,答案是,无论它对您的项目有意义!也许可以考虑提供澄清编辑,以指导您认为需要使用其中之一的讨论。
http://en.wikipedia.org/wiki/Adapter_pattern
The Adapter pattern is more about getting your existing code to work with a newer system or interface.
If you have a set of company-standard web service APIs that you'd like to offer to another application's existing extensibility interface, you might consider writing a set of adapters to do this. Note that there's a grey area and this is more about how you technically define the pattern, since other patterns like the facade are similar.
http://en.wikipedia.org/wiki/Bridge_pattern
The Bridge pattern is going to allow you to possibly have alternative implementations of an algorithm or system.
Though not a classic Bridge pattern example, imagine if you had a few implementations of a data store: one is efficient in space, the other is efficient in raw performance... and you have a business case for offering both in your app or framework.
In terms of your question, "where I can use which pattern," the answer is, wherever it makes sense for your project! Perhaps consider offering a clarification edit to guide the discussion on where you believe you need to use one or the other.
适配器:
示例:
正方形和矩形是两种不同的形状并获取面积( )其中每一个都需要不同的方法。但 Square 仍然在 Rectangle 接口上工作,并转换了一些属性。
桥:
正如所解释的,该模式中有四个组件四种设计模式书(页数:174)
请参阅下面的 SE 帖子中的代码:
何时使用桥接模式以及它与适配器模式有何不同?
Adapter:
Example:
Square and Rectangle are two different shapes and getting area() of each of them requires different methods. But still Square work on Rectangle interface with conversion of some of the properties.
Bridge:
You have four components in this pattern as explained Gang of Four Design patterns book ( page: 174 )
Refer to code in below SE post:
When to use the Bridge pattern and how is it different from the Adapter pattern?
在最上面的答案中,@James 引用了 GoF 第 219 页的一句话。我认为值得在这里复制完整的解释。
In the top answer, @James quotes a sentence from the GoF, page 219. I think it's worthwhile reproducing the full explanation here.
这篇文章已经存在很长一段时间了。然而,重要的是要理解外观与适配器有些相似,但并不完全相同。适配器将现有类“调整”为通常不兼容的客户端类。假设您有一个旧的工作流系统,您的应用程序将其用作客户端。您的公司可能会用一种新的“不兼容”系统(就界面而言)替换工作流程系统。在大多数情况下,您可以使用适配器模式并编写实际调用新工作流引擎接口的代码。桥通常以不同的方式使用。如果您实际上有一个系统需要使用不同的文件系统(即本地磁盘、NFS 等),您可以使用桥接模式并创建一个抽象层来使用所有文件系统。这基本上是桥接模式的一个简单用例。外观和适配器确实共享一些属性,但是外观通常用于简化现有的接口/类。在 EJB 的早期,没有对 EJB 的本地调用。开发人员总是获取存根,缩小范围,并将其称为“伪远程”。这通常会导致性能问题(特别是当真正通过线路调用时)。经验丰富的开发人员会使用外观模式为客户端提供非常粗粒度的界面。然后,这个外观将依次对不同的更细粒度的方法进行多次调用。总而言之,这大大减少了所需的方法调用数量并提高了性能。
This post has been around for quite a while. However, it is important to understand that a facade is somewhat similar to an adapter but it's not quite the same thing. An adapter "adapts" an existing class to a usually non-compatible client class. Let's say that you have an old workflow system that your application is using as a client. Your company could possibly replace the workflow system with a new "incompatible" one (in terms of interfaces). In most cases, you could use the adapter pattern and write code that actually calls the new workflow engine's interfaces. A bridge is generally used in a different way. If you actually have a system that needs to work with different file systems (i.e. local disk, NFS, etc.) you could use the bridge pattern and create one abstraction layer to work with all your file systems. This would basically be a simple use case for the bridge pattern. The Facade and the adapter do share some properties but facades are usually used to simplify an existing interface/class. In the early days of EJBs there were no local calls for EJBs. Developers always obtained the stub, narrowed it down and called it "pseudo-remotely". This often times caused performance problems (esp. when really called over the wire). Experienced developers would use the facade pattern to provide a very coarse-grained interface to the client. This facade would then in turn do multiple calls to different more fine-grained methods. All in all, this greatly reduced the number of method calls required and increased performance.
根据另一个 stackoverflow 答案这里,对我来说看起来更短、更清晰的答案:
适配器当您有一个抽象接口并且您想要
将该接口映射到具有类似功能的另一个对象
角色,但界面不同。
Bridge 与 Adapter 非常相似,但当您
定义抽象接口和底层实现。
也就是说,您不适应某些遗留代码或第三方代码,而是
所有代码的设计者,但您需要能够交换
不同的实现。
Looks like shorter and clear answer to me according to another stackoverflow answer here:
Adapter is used when you have an abstract interface, and you want to
map that interface to another object which has similar functional
role, but a different interface.
Bridge is very similar to Adapter, but we call it Bridge when you
define both the abstract interface and the underlying implementation.
I.e. you're not adapting to some legacy or third-party code, you're
the designer of all the code but you need to be able to swap out
different implementations.
Bridge是改进的Adapter。桥接器包括适配器并增加了额外的灵活性。
以下是 Ravindra 答案中的元素如何在模式之间映射:
Bridge is improved Adapter. Bridge includes adapter and adds additional flexibility to it.
Here is how elements from Ravindra's answer map between patterns:
我认为这很简单。
该适配器旨在允许第三方应用程序与您的应用程序配合使用。
相反,这样您的应用程序就可以与第三方应用程序一起工作。
使用桥接模式,它应该连接两个或多个应用程序而无需实现适配器。
事实上,桥是两个应用程序进行交互的接口。作为桥接的示例,这些是 PHP 中的 PSR 接口。
示例:
OtherApp
MyApp
在前面的示例中,我们为每个请求和每个响应实现了 2 个适配器。
如果我们重写示例并尝试实现桥接器。
OtherApp
MyApp
在六边形架构中,如果您从一开始就编写应用程序并准备好接受正在使用的另一个应用程序的规则,则端口(接口、合约)可以充当“桥梁”。
否则,您将不得不编写“适配器”。
I think it's simple.
The adapter is designed to allow a third party application to work with your application.
Conversely, so that your application can work with third party applications.
Using the bridge pattern, it is supposed to connect two or more applications without implementing an adapter.
In fact, a bridge is an interface through which two applications will interact. As an example of bridging, these are PSR interfaces in PHP.
Example:
OtherApp
MyApp
In the before example, we have implemented 2 adapters per request and per response.
If we rewrite example and try to implement the bridge.
OtherApp
MyApp
In hexagonal architecture, Ports (Interfaces, Contracts) can act as 'Bridges' if you write an application from the very beginning and are ready to accept the rules of another application being used.
Otherwise, you will have to write 'Adapters'.
假设您有一个具有(通用/抽象)绘图功能的抽象 Shape 类和一个实现 Shape 的 Circle。桥接模式只是一种双向抽象方法,用于解耦实现(在 Circle 中绘制)和通用/抽象功能(在 Shape 类中绘制)。
它到底意味着什么?乍一看,这听起来像是您已经制作的东西(通过依赖倒置)。因此,不必担心拥有不那么僵化或更模块化的代码库。但这背后有更深层次的哲学。
根据我的理解,当我需要添加与当前系统密切相关的新类(如 RedCircle 或 GreenCircle )并且它们仅在单个功能上有所不同(如 color )时,可能会出现使用模式的需求。我将需要 Bridge 模式,特别是如果现有系统类( Circle 或 Shape )要经常更改,并且您不希望新添加的类受到这些更改的影响。这就是为什么通用绘图功能被抽象到一个新接口中,以便您可以独立于形状或圆形来更改绘图行为。
Suppose you've a abstract Shape class with a (generic/abstracted) drawing functionality and a Circle who implements the Shape. Bridge pattern simply is a two-way abstraction approach to decouple the implementation ( drawing in Circle ) and generic/abstracted functionality ( drawing in the Shape class ).
What does it really mean? At a first glance, it sounds like a something you already making ( by dependency inversion). So no worries about having a less-ridig or more modular code base. But it's a bit deeper philosophy behind it.
From my understanding, the need of usage pattern might emerge when I need to add new classes which are closely related with the current system ( like RedCircle or GreenCircle ) and which they differ by only a single functionality ( like color ). And I'm gonna need Bridge pattern particularly if the existing system classes ( Circle or Shape ) are to be frequently changed and you don't want newly added classes to be affected from those changes. So that's why the generic drawing functionality is abstracted away into a new interface so that you can alter the drawing behaviour independent from Shape or Circle.
有很多答案可以区分适配器和桥接器。
但当人们寻找代码示例时,我将给出一个将适配器设计模式制作成时间线故事的示例:
仔细注意:
dhanushAttacker.setNavigationCapability(pinakaAttacker.get(..))
值得注意的点
客户端拥有:
稍后共享:
接收方拥有:
希望有人也为 Bridge 提供内联:)
There are plenty of answers To distinguish between Adapter and Bridge.
But as ppl are looking for code examples, I would give one example for Adapter Design Pattern crafted into a timeline story :
Carefully notice :
dhanushAttacker.setNavigationCapability(pinakaAttacker.get(..))
Noteworthy points
Client side owns:
Shared later:
Receiver side owns :
Hoping someone gives an inline for Bridge too :)