代码改变世界

适配器模式的实例应用

  AceYue  阅读(1411)  评论(0编辑  收藏  举报

适配器模式

Adapter(别名Wrapper)模式:将一个类的接口,转换成客户期望的另一个类的接口。适配器让原本接口不兼容的类可以合作无间。

 

要点:

1. 适配器模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。

2. 适配器模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。

适配器模式的优点

  1. 将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,而无须修改原有代码。
  2. 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
  3. 灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

类适配器模式的缺点如下:

         对于Java、C#等不支持多重继承的语言,一次最多只能适配一个适配者类,而且目标抽象类只能为抽象类,不能为具体类,其使用有一定的局限性,不能将一个适配者类和它的子类都适配到目标接口。

类适配器模式还具有如下优点:

         由于适配器类是适配者类的子类,因此可以在适配器类中置换一些适配者的方法,使得适配器的灵活性更强.

对象适配器模式还具有如下优点:

         一个对象适配器可以把多个不同的适配者适配到同一个目标,也就是说,同一个适配器可以把适配者类和它的子类都适配到目标接口。

对象适配器模式的缺点如下:

         与类适配器模式相比,要想置换适配者类的方法就不容易。如果一定要置换掉适配者类的一个或多个方法,就只好先做一个适配者类的子类,将适配者类的方法置换掉,然后再把适配者类的子类当做真正的适配者进行适配,实现过程较为复杂

模式适用环境

         系统需要使用现有的类,而这些类的接口不符合系统的需要。

         想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。

         两个类所做到事情相同或者相似,但是具有不同的接口的时候,和客户要求不符合的时候。

         旧的系统开发的类已经实现了一些功能,但是客户端却只能以另外接口的形式访问,但是我不希望手动更改原有的类;

         使用第三方组件,组件接口定义和自己定义的不同,不希望修改自己定义的接口,但是要使用第三方组件接口的功能。

 

 

用例分析

         一位用户拿着业界标准开关(一个标准的StandardSwitcher,它依赖IStandardSwitchable接口才能工作,然而目前我们的灯并不支持这个接口)出现在我面前,叫嚣着他的“标准开关”应该能打开我们的灯。好吧,这个需求是合理的,的确应该支持。

 

两个方案

     现在有两个选择。

  1. 让我们的灯直接支持标准开关。也就是让灯实现IStandardSwitchable接口。

    • 好处:成本低,实现方式优雅。

    • 坏处:相当于放弃了已经买了我们的灯,又想用标准开关的用户。

  2. 不改变现在的灯,让标准开关能打开我们的灯。标准接口我们改不了,灯也不能改。好在计算机界有句话,叫“加一层可以解决一切问题”。这让我想到了买外国电器附赠的那个电源接口转换器。现在,我们的灯需要个类似的玩意儿。

    • 好处:支持所有的灯。

    • 坏处:这东西都是要附赠的,会降低我们的利润。

     第一个方案很简单,就是让Light多实现个接口就OK了。图就不给了。

     现在分析第二个方案,标准接口依赖IStandardSwitchable接口,那我们必须有一个类来实现它,并完成所需要的功能——操作灯。咱也是学过设计模式的人,这个问题很明显可以用Adapter模式来解释。

复制代码
View Code
 1     public interface IStandardSwitchable
 2     {
 3         void TurnOn();
 4         void TurnOff();
 5     }
 6  
 7     public class SwitcherAdapter : IStandardSwitchable
 8     {
 9         public Light Switchee { get; set; }
10  
11         public void TurnOn()
12         {
13             Switchee.TurnOn();
14         }
15  
16         public void TurnOff()
17         {
18             Switchee.TurnOff();
19         }
20     }
复制代码

       目前的需求,我们有灯,有收音机,如果用户说要用标准开关开收音机,难道还要实现一个RadioAdapter不成?

       需求是要“通过加一层让灯支持标准开关”,但是并不是说这一层就要使用灯,为了让这个Adapter更加通用,应该让Adapter依赖ISwitchable接口。像下面这个样子。

 

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示