写点什么

【愚公系列】2022 年 05 月 二十三种设计模式 (六)- 适配器模式 (Adapter Pattern)

作者:愚公搬代码
  • 2022 年 5 月 06 日
  • 本文字数:2291 字

    阅读完需:约 8 分钟

前言

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题的核心解决方案,这也是它能被广泛应用的原因。

一、适配器模式(Adapter Pattern)

适配器模式属于结构型模式,把一个类的接口变成客户端所期待的另一种接口,从而使原本接口不匹配而无法一起工作的两个类能够在一起工作。


适配器模式又可以分为 4 种类型,类适配器模式、对象适配器模式、单接口适配器模式(缺省适配器模式)和双向适配器模式。后 2 种模式的实现比较复杂并且在实际开发过程中很少使用,故本博文只讨论前 2 种模式。

二、使用步骤

角色

1、抽象目标(Target)


抽象目标类定义客户所需的接口,可以是一个抽象类或接口,也可以是具体类。在类适配器中,由于 C#语言不支持多重继承,所以它只能是接口;


2、适配器(Adapter)


它可以调用另一个接口,作为一个转换器,对 Adaptee 和 Target 进行适配,它是适配器模式的核心;


3、适配者(Adaptee)


适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类包好了客户希望的业务方法。

示例


命名空间 AdapterPattern 包含 ClassBased 和 ObjectBased 子命名空间,分别表示基于类的适配器模式和基于对象的适配器模式。类的适配器中包含家用电器类、电压类、目标动作接口和手机适配器类。对象的适配器中包含适配者、适配器、目标接口和目标基类。本案例尝试使用手机适配器将家用电器的电压从 220V 适配至 3V。


namespace AdapterPattern
复制代码

类的适配器模式

namespace AdapterPattern.ClassBased
复制代码


public class Voltage {
public uint Value { get; set; }
}
复制代码


电压 Voltage 类,包含一个无符号 int 类型的电压值。


public class Appliance {
public Voltage GetVoltage() { return new Voltage { Value = 220 }; }
}
复制代码


家用电器 Appliance 类,包含一个获取电压的 GetVoltage 方法。


public interface ITarget {
Voltage GetMobileVoltage();
}
复制代码


目标接口 ITarget,包含一个获取手机电压的 GetMobileVoltage 方法。这是我们要适配的目标动作。


public class MobileAdapter : Appliance, ITarget {     public Voltage GetMobileVoltage() {        var voltage = GetVoltage();        Console.WriteLine($"Appliance voltage is {voltage.Value}V!");         voltage.Value = 3;        Console.WriteLine($"After adapted,it becomes {voltage.Value}V!");         return voltage;    } }
复制代码


手机适配器 MobileAdapter 类,继承自 Applicance 家用电器并实现 ITarget 接口。

对象的适配器模式

namespace AdapterPattern.ObjectBased
复制代码


public class Adaptee {
public void OriginalMethod() { Console.WriteLine("Original Method is being called!"); }
}
复制代码


适配者 Adaptee 类,这是将要被我们适配的类。


public interface ITarget {
void TargetMethod();
}
复制代码


目标接口 ITarget,定义我们的目标动作。


public class Target : ITarget {
public virtual void TargetMethod() { Console.WriteLine("Target Method is being called!"); }
}
复制代码


目标 Target 类,实现目标接口以实现动作。


public class Adapter : Target {
private Adaptee _adaptee = new Adaptee();
public override void TargetMethod() { _adaptee.OriginalMethod(); }
}
复制代码


适配器 Adapter 类,继承自 Target 类。内部维持对适配者的引用并实现一个目标动作。


public class Program {
private static ClassBased.ITarget _targetClass = null; private static ObjectBased.ITarget _targetObject = null;
public static void Main(string[] args) { //Class Pattern _targetClass = new ClassBased.MobileAdapter(); var voltage = _targetClass.GetMobileVoltage();
Console.WriteLine("-----------------------------");
//Object Pattern _targetObject = new ObjectBased.Adapter(); _targetObject.TargetMethod();
Console.ReadKey(); }
}
复制代码


以上是调用方的代码,分别演示了类的适配器模式和对象的适配器模式的用法。以下是这 2 个案例的输出结果:


Appliance voltage is 220V!After adapted,it becomes 3V!-----------------------------Original Method is being called!
复制代码


<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">

总结

优点

1、可以让任何两个没有关联的类一起运行;2、可以在不修改原有代码的基础上来复用现有类,很好地符合 “开闭原则”;3、增加了类的透明度和更好的灵活性。

缺点

1、由于 C#不支持多重继承,所以最多只能适配一个适配者类,而且目标类必须是抽象类;2、采用了类和接口的“双继承”实现方式,带来了不良的高耦合。

使用场景

1、系统需要复用现有类,而该类的接口不符合系统的需求;2、想要建立一个可重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作;3、对于对象适配器模式,在设计里需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。

发布于: 20 小时前阅读数: 28
用户头像

还未添加个人签名 2022.03.01 加入

该博客包括:.NET、Java、前端、IOS、Android、鸿蒙、Linux、物联网、网络安全、python、大数据等相关使用及进阶知识。查看博客过程中,如有任何问题,皆可随时沟通。

评论

发布
暂无评论
【愚公系列】2022年05月 二十三种设计模式(六)-适配器模式(Adapter Pattern)_5月月更_愚公搬代码_InfoQ写作社区