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
随机推荐
- C语言基础--数组详细说明
目录 一.什么是数组 二.一维数组 1.一维数组创建 2.一维数组的使用 2.1 索引值 2.2 遍历数组 2.3 如何使用sizeof()计算出数组的长度 三.二维数组 1.二维数组的创建 2.二维 ...
- Spring—bean的作用域
beans的作用域 单例模式(Spring默认模式) <?xml version="1.0" encoding="UTF-8"?> <bean ...
- 内网渗透大杀器fscan
fscan简介 一款内网综合扫描工具,方便一键自动化.全方位漏扫扫描.支持主机存活探测.端口扫描.常见服务的爆破.ms17010.redis批量写公钥.计划任务反弹shell.读取win网卡信息.we ...
- [golang]使用tail追踪文件变更
简介 借助 github.com/hpcloud/tail ,可以实时追踪文件变更,达到类似shell命令tail -f的效果. 示例代码 以下示例代码用于实时读取nginx的access.log日志 ...
- 从浅入深了解.NET Core MVC 2.x全面教程【第二章】
二.Logging 1.诊断中间件 命名空间:Microsoft.AspNetCore.Diagnostics 报告信息并处理异常 2.诊断中间件 UseDeveloperExceptionPage: ...
- nlp入门(五)隐马尔科夫模型
源码请到:自然语言处理练习: 学习自然语言处理时候写的一些代码 (gitee.com) 一.马尔科夫模型概念 1.1 马尔科夫模型:具有马尔可夫性质并以随机过程为基础的模型 1.2 马尔科夫性质:过去 ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-12-playwright操作iframe-中篇
1.简介 按照计划今天就要用实际的例子进行iframe自动化测试.经过宏哥长时间的查找,终于找到了一个含有iframe的网页(QQ邮箱和163邮箱),别的邮箱宏哥就没有细看了.所以今天这一篇的主要内容 ...
- Programming abstractions in C阅读笔记:p132-p137
<Programming Abstractions In C>学习第53天,p132-p137,3.2小节"strings"总结如下: 一.技术总结 3.2小节介绍了字 ...
- cephadm快速部署指定版本ceph集群及生产问题处理
cephadm快速部署指定版本ceph集群及生产问题处理 目录 cephadm快速部署指定版本ceph集群及生产问题处理 1.虚拟机规划:centos8 2.ceph版本:(安装指定版本在源里面指定即 ...
- gitlab与LDAP 联调
gitlab整理 目录 gitlab整理 1.安装Gitlab依赖包 2.下载,安装 3.配置,访问域名及邮箱 4.初始化,启动 5.访问,以及邮箱测试 5.1汉化 6.问题总结处理 6.1安装时出现 ...