c#中适配器模式详解
基础介绍:
想象这样一个场景,原项目中接口返回的数据是XML格式的数据,但现在来了一个新客户,它期望接口返回的数据类型为json格式的。
想要实现要么就是改原有接口,但这样就违反了开闭原则,容易出现未知bug,影响到老客户的正常使用。
而如果写一个适配器类也就是转换类(第三方类),将原本返回的XML格式数据转换成json格式数据,而具体数据是怎么来的则直接用原有接口方法就可以。
新客户只需要调用适配器类就可以了,而老客户这边也不会进行任何修改处理。
如果再有新的客户要求其他类型的返回,只需要在适配器类中增加相应的转换处理就可以了。
再思考一个问题,现实生活中空调插头一般都是三头的,但如果家里只有两孔插座,那必然是插不进去的。
以前老的办法那就是把三头插座掰掉一个,另外两个也掰直,这样做存在很大的安全隐患,而且有时并不能工作。
而如果提供一个拥有三孔插座和两头插头的转换器的话,那空调可以先插在这个转换器上,然后这个转换器再插在插座上就可以了。
本质并没有变,只是将二孔插座包装了一下,向外界提供了一个三孔插座的外观以供客户使用。
适配的本质就是转换,将不满足使用条件的东西通过第三方类进行加工处理成可使用的东西。
适配器模式(Apapter Pattern)是一种结构型设计模式,将一个类的接口转换成客户希望的另一个接口。适配器模式使得原本由于接口兼容而不能一起工作的那些类可以一起工作。
适配器模式用来解决现有对象与客户端期待接口不一致的问题。
- 目标角色(Target):描述了其他类与客户端代码合作时必须遵循的协议。
- 客户角色(Client):与符合Target接口的对象协同。
- 被适配(服务类,功能类)(Adaptee):定义一个已经存在并已经使用的接口,这个接口需要适配。 客户端与其接口不兼容, 因此无法直接调用其功能。
- 适配器(Adapter) :适配器模式的核心。适配器接受客户端通过适配器接口发起的调用,同时根据其内在逻辑调用对应服务类。客户端代码只需通过接口与适配器交互即可, 无需与具体的服务类耦合。
优缺点:
- 单一职责原则:可以将接口或数据转换代码从主要业务逻辑中分离。
- 开闭原则: 客户端接口只需适配器进行交互, 能在不修改现有代码的情况下在程序中添加新类型的适配器。
- 通过适配器模式,可以使两个不兼容的接口协同工作,避免了修改现有代码的需要。
- 提高了代码的复用性和灵活性,因为适配器可以重复使用,并且可以在不同的场景中使用。
- 降低了系统的耦合度,适配器模式允许系统中的各个组件相互独立地演化。
- 代码整体复杂度增加 :因为需要新增一系列接口和类。 有时直接更改服务类使其与其他代码兼容会更简单。
应用场景:
系统需要复用现有类,但是接口又与复用环境要求不一致的情况。
- 旧系统与新系统的兼容:可以使新系统能够无缝地与老旧系统进行通信。
- 第三方组件的集成:适配器可以将第三方组件的接口转换为符合我们系统需求的接口形式,从而能够顺利地集成到我们的系统中。
- 多个类库之间的互操作:适配器模式可以起到桥梁的作用。
创建方式:
适配器模式有两种实现结构,对象适配器和类适配器。
试想一下,目前有一个三头插头的空调,需要一个三孔插座,但目前只有一个两孔插座。
编写一个适配器来包装一下这个两孔插座,让用户可以使用这个空调。
类适配器

1 /// <summary>
2 /// 两孔插座---被适配者
3 /// </summary>
4 public class TwoHoleSocket
5 {
6 public void SpecificRequest()
7 {
8 Console.WriteLine("两孔插座");
9 }
10 }
11
12 /// <summary>
13 /// 三孔插座---目标角色
14 /// </summary>
15 public interface IThreeHoleSocket
16 {
17 void Request();
18 }
19
20 /// <summary>
21 /// 适配器类提供了三孔插座的外观,但其本质是两孔插座
22 /// </summary>
23 public class PowerAdapter : TwoHoleSocket, IThreeHoleSocket
24 {
25 public void Request()
26 {
27 Console.WriteLine("提供三孔插座的外观");
28 //执行两孔插座的功能
29 this.SpecificRequest();
30 }
31 }
32
33 /// <summary>
34 /// 客户端
35 /// </summary>
36 class Client
37 {
38 static void Main(string[] args)
39 {
40 //客户端可以通过适配器来使用这个两孔插座了(因为外观已经是三孔的了)
41 IThreeHoleSocket threeHoleSocket = new PowerAdapter();
42 threeHoleSocket.Request();
43 Console.ReadKey();
44 }
45 }TwoHoleSocket类代表原有的两孔插座,IThreeHoleSocket接口来规范三孔插座的外观。
PowerAdapter类代表适配器,将两孔插座赋予三孔插座的外观。
这样用户就可以使用这个适配器来使用这个三头插头的空调了。
从实例中可以看出,类适配器只要是用继承来实现的,但如果有很多个类进行适配,这个方式就不支持了。
对象适配器

1 /// <summary>
2 /// 两孔插座---被适配者
3 /// </summary>
4 public class TwoHoleSocket
5 {
6 public void SpecificRequest()
7 {
8 Console.WriteLine("两孔插座");
9 }
10 }
11
12 /// <summary>
13 /// 三孔插座---目标角色
14 /// </summary>
15 public class ThreeHoleSocket
16 {
17 // 客户端需要的方法
18 public virtual void Request()
19 {
20 //具体实现
21 }
22 }
23
24 /// <summary>
25 /// 适配器类提供了三孔插座的外观,但其本质是两孔插座
26 /// </summary>
27 public class PowerAdapter : ThreeHoleSocket
28 {
29 //引用两孔插座的实例,从而将客户端与TwoHoleSocket联系起来
30 public TwoHoleSocket twoHoleSocket = new TwoHoleSocket();
31 public override void Request()
32 {
33 Console.WriteLine("提供三孔插座的外观");
34 this.Request();
35 //执行两孔插座的功能
36 twoHoleSocket.SpecificRequest();
37 }
38 }
39
40 /// <summary>
41 /// 客户端
42 /// </summary>
43 class Client
44 {
45 static void Main(string[] args)
46 {
47 //客户端可以通过适配器来使用这个两孔插座了(因为外观已经是三孔的了)
48 ThreeHoleSocket threeHoleSocket = new PowerAdapter();
49 threeHoleSocket.Request();
50 Console.ReadKey();
51 }
52 }从实例中可以看出,对象适配器其实就是在适配器类中创建了一个被适配者的实例,从而将两者联系在一起。
这种方式采用 “对象组合”的方式,更符合松耦合。
总结:
总而言之,适配器就是一个第三方类,将不合时宜的东西转换成符合心意的工具类。
本质就是转换。
c#中适配器模式详解的更多相关文章
- winxp计算机管理中服务详解
winxp计算机管理中服务详解01 http://blog.sina.com.cn/s/blog_60f923b50100efy9.html http://blog.sina.com.cn/s/blo ...
- cocos2dx常见的46中+22中动作详解
cocos2dx常见的46中+22中动作详解 分类: iOS2013-10-16 00:44 1429人阅读 评论(0) 收藏 举报 bool HelloWorld::init(){ ///// ...
- Android中Context详解 ---- 你所不知道的Context
转自:http://blog.csdn.net/qinjuning/article/details/7310620Android中Context详解 ---- 你所不知道的Context 大家好, ...
- iOS中-Qutarz2D详解及使用
在iOS中Qutarz2D 详解及使用 (一)初识 介绍 Quartz 2D是二维绘图引擎. 能完成的工作有: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成 ...
- 【转】declare-styleable的使用(自定义控件) 以及declare-styleable中format详解
原文网址:http://www.cnblogs.com/622698abc/p/3348692.html declare-styleable是给自定义控件添加自定义属性用的 1.首先,先写attrs. ...
- Python中dict详解
from:http://www.cnblogs.com/yangyongzhi/archive/2012/09/17/2688326.html Python中dict详解 python3.0以上,pr ...
- 【转】 java中HashMap详解
原文网址:http://blog.csdn.net/caihaijiang/article/details/6280251 java中HashMap详解 HashMap 和 HashSet 是 Jav ...
- java中HashMap详解(转)
java中HashMap详解 博客分类: JavaSE Java算法JDK编程生活 HashMap 和 HashSet 是 Java Collection Framework 的两个重要成 ...
- java集合(2)- java中HashMap详解
java中HashMap详解 基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了非同步和允许使用 null 之外,HashMap 类与 H ...
- PHP中Trait详解及其应用
w PHP中Trait详解及其应用 - 开发者日常 - SegmentFaulthttps://segmentfault.com/a/1190000008009455
随机推荐
- Federated Learning003
联邦学习笔记--003 2022.11.28周一 今天主要学习了几篇优秀的博客,补充了一些知识. (一)联邦学习面临的挑战 非独立同分布的数据 有限通信带宽 不可靠和有限的设备 什么是Non-IID( ...
- 2021-3-9 保存csv格式文件
public void SaveCSV(DataTable dt, string fullPath) { FileInfo fi = new FileInfo(fullPath); if (!fi.D ...
- windows安装uwsgi报错 AttributeError: module 'os' has no attribute 'uname'
Win10系统不支持安装UWSGI, 不用尝试了 安装 pip install uwsgi windows安装报错 AttributeError: module 'os' has no attribu ...
- 学习OI两年我到底收获了什么
做一个小小的总结 学习了两年的代码,刚刚要进入高中,留下一点文字给以前的学习做一个总结. 命中注定の邂逅-- 这两年之间,和编程产生了比学习更为低调的羁绊关系(我觉得用这个词语比较合适).编程给我带来 ...
- 随风迎 jmeter下TPS插件的安装(转)
1.下载插件http://pan.baidu.com/s/1mioVJni 2.解压下载的安装包: 将 jpgc-graphs-basic-2.0.zip 解压缩后只有一个 lib 目录,该目录下有一 ...
- 一 APPIUM基本理论知识(转)
1.APPIUM介绍 Appium 是一个自动化测试开源工具,支持 iOS 平台和 Android 平台上的原生应用,web 应用和混合应用.所谓的"移动原生应用"是指那些用 iO ...
- Nginx深入:nginx功能模块、目录结构及配置文件详解
Nginx功能模块说明 1.Nginx 核心功能模块(Core functionality) Nginx核心功能模块负责Nginx的全局应用,主要对应主配置文件的核心层(Main层)和事件(Event ...
- java file I/O流
一.File的简介:(java.io包) 生活中的文件: (1)文件的作用:持久化(瞬时状态的对立面状态) (1)文件的定义:一堆数据的集合 (2)文件存储的位置:磁盘,硬盘,软盘,U盘等等 计算机中 ...
- go语言环境要这样搭建才"省钱"
go语言环境要这样搭建才省钱 目录 go语言环境要这样搭建才省钱 本篇概要 集成开发环境工具(ide) Goland或IntelliJ IDEA Visual Studio Code 其他集成开发环境 ...
- AWD-PWN流量监控与抄流量反打
RE手 在AWD中比较做牢,队伍里也没pwn手,在awd出现pwn靶机比较坐牢.之前都不知道pwn靶机可以抄流量反打. 参考pwn_waf:https://github.com/i0gan/pwn_w ...