通俗易懂设计模式解析——适配器模式
前言
前面完成了创建型的设计模式的分享,创建型的设计模式解决的是对象创建的问题。今天开始介绍结构型的设计模式,其中结构型设计模式包括:适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。结构型设计模式解决的是类与对象的组合关系。今天讲结构型对象中的第一个——适配器模式。适配器模式——顾名思义嘛。在我们平常的理解中,适配器是干啥用的呢?不就是将两个原本不匹配的东西转换为匹配罢了。适配器是接口转换器,比如电源适配器,USB接口转换器等等。
适配器模式介绍
一、来由
在系统程序中,我们可能会面临需求的增加或者改变,或者是应用环境的改变。常常需要将一些已经存在的类放在新的需求或者新的环境中应用。但是新的环境要求使用到的接口与现在存在的类或对象不完全匹配。那么如何去面对这样的迁移变化呢?
二、意图
将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
三、案例图
四、适配器模式代码示例
在适配器模式中一般包含以下部分的存在:
客户端:与目标接口配合协同使用
目标接口:与客户端协同使用
被适配角色:表示一个已经存在了并使用的接口
适配器:整个模式核心存在,将被适配角色转换为目标需要的接口。
接下来我们看下这个示例,前段时间笔记本那个耳机圆孔接口坏掉了。这个时候我只有手机那种圆孔耳机。但是我也需要在电脑上面使用,那怎么办呢?我不想多花钱去买一个usb耳机,也没有时间去把电脑修好。简单、我去网上买一个耳机的Usb转换器。然后就可以在电脑上使用了。在这事例中,目标接口是电脑USB耳机,被适配角色是手机圆孔耳机,适配器就是圆孔耳机转换为USB的过程、电脑则是客户端:
namespace Adapter_Pattern { class AdapterPattern { } #region 目标角色——需要电脑usb耳机========================= /// <summary> /// 客户端需要的接口 /// </summary> interface ComputerHeadsetTarget { void GetComputerHeadset(); } #endregion #region 被适配角色——现在存在的手机耳机===================== /// <summary> /// 目前已经存在的接口 /// </summary> public class Adaptee { public void PhoneHeadset() { Console.WriteLine("我现在拥有的是手机耳机。"); } } #endregion #region 对象适配器——将手机耳机转换成电脑需要的usb耳机========== /// <summary> /// 对象适配器实现 /// </summary> public class ObjectAdapter : ComputerHeadsetTarget { Adaptee Adaptee = new Adaptee(); public void GetComputerHeadset() { Adaptee.PhoneHeadset(); Console.WriteLine("现在加入耳机Usb转换器"); Console.WriteLine("输出:电脑使用的usb耳机"); } } #endregion #region 类适配器——将手机耳机转换成电脑需要的usb耳机=========== /// <summary> /// 类适配器的实现 /// </summary> public class ClassAdapter : Adaptee,ComputerHeadsetTarget { public void GetComputerHeadset() { this.PhoneHeadset(); Console.WriteLine("现在加入耳机Usb转换器"); Console.WriteLine("输出:电脑使用的usb耳机"); } } #endregion }
class Program { static void Main(string[] args) { Console.WriteLine("我现在需要电脑usb耳机"); ///对象适配器 ObjectAdapter objectAdapter = new ObjectAdapter(); objectAdapter.GetComputerHeadset(); Console.WriteLine("我现在需要电脑usb耳机"); ///类适配器 ClassAdapter classAdapter = new ClassAdapter(); classAdapter.GetComputerHeadset(); Console.ReadLine(); } }
使用场景及优缺点
这适配器模式主要用于一些希望被复用的类,但是这些类中的接口又与新的环境不完全匹配的情况下。老代码遗留修改中、类库迁移中用处较多。
在上面示例中写了适配器的两种实现方式,对象适配器和类适配器。对于类适配器来说既继承了目标接口类又继承了已存在接口类。在C#编程中尽量采用多组合少继承的形式进行代码编写。多继承提高了类之间的耦合性。所以对于类适配器一般情况尽量少使用。而对于对象适配器来说采用的是对象组合的方式。
一、使用场景
1、系统需要复用现在的类,但是类中接口与现在环境不完全匹配
2、想要建立一个可以复用的类,用于彼此之间没有太大关联的一些类。
二、优点
对象适配器:
1、可以再不修改原来的类的基础上复用原来的类,符合开闭原则
2、采用的”对象组合”,降低类之间的耦合性
类适配器:
1、可以再不修改原来的类的基础上复用原来的类,符合开闭原则
2、可以重新定义被适配角色类中一部分行为,在类适配器中被适配角色类为基类
3、仅是引用一个对象,不需要额外的字段引用实例
三、缺点
对象适配器:
1、重新定义被适配角色类中部分行为困难
类适配器:
1、对于被适配角色类的子类中的一些方法就不能进行转换了,因为没有引用其实例,仅继承基类。所以只能调用基类中的方法。
2、采用了多继承的方式。提高了类之间的耦合性
总结
大家会不会觉得Adapter这个单词这么熟悉呢?我刚看的时候也觉得蛮熟悉的样子。应该大多数人都写过DBHelper这个数据库辅助类吧,在数据库连接操作过程中存在着DataSet对象和DataAdaper对象。DataAdaper也就是数据适配器,负责把DataSet与真实数据源连接起来。DataAdaper获得数据,然后将数据填充到DataSet对象中。针对于数据库与DataSet之间的一种适配。这也是.NET中一种适配器模式的实现。
天再高又怎样,踮起脚尖就更接近阳光。
欢迎大家扫描下方二维码,和我一起踏上设计模式的闯关之路吧!