C#面向对象设计模式纵横谈:Adapter 适配器模式

适配(转换)的概念无处不在

适配,即在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口。

动机(Motivation)

在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?

意图(Intent)

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

——《设计模式》 GoF

例说Adapter应用

这种实际上是一种委派的调用,本来是发送请求给MyStack,但是MyStack实际上是委派给list去处理。MyStack在这里其实就是Adapter(适配对象),list即是Adaptee(被适配的对象),而IStack就是客户期望的接口。

结构(Structure)

适配器有两种结构

-对象适配器(更常用)

对象适配器使用的是对象组合的方案,它的Adapter核Adaptee的关系是组合关系,即上面例子中MyStack和list是组合关系。

OO中优先使用组合模式,组合模式不适用再考虑继承。因为组合模式更加松耦合,而继承是紧耦合的,父类的任何改动都要导致子类的改动。上面的例子就是对象适配器。

-类适配器

下面的例子是类适配器。

Adapter继承了ArrayList,也继承了IStack接口,它既可以使用ArrayList里的方法,也可以使用IStack接口里的方法,这样就感觉有点不伦不类。这个类违反了类应该具有单一职责的原则,它既有ArrayList的职责,也有IStack的职责,因此这种类适配不是很常用,也不推荐使用。

另外,如果一个方法有可能要委托到2个或2个以上的对象,或者2个或2个以上的类需要委托,对于对象适配器,只需要增加几个内部的属性就可以实现适配。

而对于类适配器,因为C#中类只能是单一继承,它不能继承自2个或2个以上的类,所以类适配器这里便无法使用。

Adapter模式的几个要点

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

GoF23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。Adapter模式可以实现的非常灵活,不必拘泥于GoF23中定义的两种结构。例如,完全可以将Adapter模式中的“现存对象”作为新的接口方法参数,来达到适配的目的。

Adapter模式本身要求我们尽可能地使用“面向接口的编程”风格,这样才能在后期很方便地适配。

.NET框架中的Adapter应用

1.在.NET中复用COM对象:

-COM对象不符合.NET对象的接口

-使用tlbimp.exe来创建一个Runtime Callable Wrapper(RCW)以使其符合.NET对象的接口

2..NET数据访问类(Adapter变体):

-各种数据库并没有提供DataSet接口

-使用DbDataAdapter可以将任何个数据库访问/存取适配到一个DataSet对象上

微软把适配器和被适配的对象分离了,它把EmployeeDAO作为适配器了。这和上面的模式有点不同,但是原理都是一样的,如果是写成下面的样子,就比较好理解了。

DataSet就是一个适配器

3.集合类中对现有对象的排序(Adapter变体):

-现有对象未实现IComparer接口

-实现一个排序适配器(继承IComparer接口),然后在其Compare方法中对两个对象进行比较

这样写是会报错的,因为要使用Array.Sort的静态方法,传入的参数类型Employee必须要求实现IComparer接口。但如果Employee类已经在很多地方使用了,我们不能更改它,这个时候可以考虑适配。Array.Sort方法本身提供了一种重载,可以传入一个比较方法。

因此我们可以重新写一个类实现IComparer接口,这里是让员工根据年龄排序

这里的实现适配没有把适配器放在类里面。没必要非要做成教科书上的结构才叫适配器,把适配对象直接作为参数传递一样是一种很好的做法。

适配(转换)的概念无处不在

适配,即在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口。

动机(Motivation)

在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?

意图(Intent)

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

——《设计模式》 GoF

例说Adapter应用

这种实际上是一种委派的调用,本来是发送请求给MyStack,但是MyStack实际上是委派给list去处理。MyStack在这里其实就是Adapter(适配对象),list即是Adaptee(被适配的对象),而IStack就是客户期望的接口。

结构(Structure)

适配器有两种结构

-对象适配器(更常用)

对象适配器使用的是对象组合的方案,它的Adapter核Adaptee的关系是组合关系,即上面例子中MyStack和list是组合关系。

OO中优先使用组合模式,组合模式不适用再考虑继承。因为组合模式更加松耦合,而继承是紧耦合的,父类的任何改动都要导致子类的改动。上面的例子就是对象适配器。

-类适配器

下面的例子是类适配器。

Adapter继承了ArrayList,也继承了IStack接口,它既可以使用ArrayList里的方法,也可以使用IStack接口里的方法,这样就感觉有点不伦不类。这个类违反了类应该具有单一职责的原则,它既有ArrayList的职责,也有IStack的职责,因此这种类适配不是很常用,也不推荐使用。

另外,如果一个方法有可能要委托到2个或2个以上的对象,或者2个或2个以上的类需要委托,对于对象适配器,只需要增加几个内部的属性就可以实现适配。

而对于类适配器,因为C#中类只能是单一继承,它不能继承自2个或2个以上的类,所以类适配器这里便无法使用。

Adapter模式的几个要点

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

GoF23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。Adapter模式可以实现的非常灵活,不必拘泥于GoF23中定义的两种结构。例如,完全可以将Adapter模式中的“现存对象”作为新的接口方法参数,来达到适配的目的。

Adapter模式本身要求我们尽可能地使用“面向接口的编程”风格,这样才能在后期很方便地适配。

.NET框架中的Adapter应用

1.在.NET中复用COM对象:

-COM对象不符合.NET对象的接口

-使用tlbimp.exe来创建一个Runtime Callable Wrapper(RCW)以使其符合.NET对象的接口

2..NET数据访问类(Adapter变体):

-各种数据库并没有提供DataSet接口

-使用DbDataAdapter可以将任何个数据库访问/存取适配到一个DataSet对象上

微软把适配器和被适配的对象分离了,它把EmployeeDAO作为适配器了。这和上面的模式有点不同,但是原理都是一样的,如果是写成下面的样子,就比较好理解了。

DataSet就是一个适配器

3.集合类中对现有对象的排序(Adapter变体):

-现有对象未实现IComparer接口

-实现一个排序适配器(继承IComparer接口),然后在其Compare方法中对两个对象进行比较

这样写是会报错的,因为要使用Array.Sort的静态方法,传入的参数类型Employee必须要求实现IComparer接口。但如果Employee类已经在很多地方使用了,我们不能更改它,这个时候可以考虑适配。Array.Sort方法本身提供了一种重载,可以传入一个比较方法。

因此我们可以重新写一个类实现IComparer接口,这里是让员工根据年龄排序

这里的实现适配没有把适配器放在类里面。没必要非要做成教科书上的结构才叫适配器,把适配对象直接作为参数传递一样是一种很好的做法。


相关文章

  • 物流管理信息平台采购管理子系统的设计与开发-毕业论文
  • 毕业论文 目录 第一章 前言 . ................................................... 2 第一节. 绪论 ......................................... ...查看


  • 企业信息系统运行状态监控与管理
  • 企业信息系统运行状态监控与管理的信息化 在企业内部运行着许多信息系统,信息系统管理员的主要工作之一就是负责这些系统的运行状态监控与管理,这也是信息系统管理员的日常工作.然而在实际工作中,系统管理员往往疏于日常监控与管理,只是在出现故障时才疲 ...查看


  • 理解面向对象
  • 面向对象设计思想(C#) 有了翅膀才能飞,欠缺灵活的代码就象冻坏了翅膀的鸟儿.不能飞翔,就少了几许灵动的气韵.我们需要给代码带去温暖的阳光, 让僵冷的翅膀重新飞起来.结合实例,通过应用OOP.设计模式和重构,你会看到代码是怎样一步一步复活的 ...查看


  • 软件设计模式
  • 软件设计模式浅析 木子田心街 (河南 郑州) 摘 要:本文主要从设计模式的几个方面进行简单的概括和研究,从简单的工厂模式到Coordinator模式,以及对设计模式在未来的展望做出了进一步的分析和总结. 关键词:简单工厂模式:Coordin ...查看


  • 大连海事大学软件工程期末试题库
  • 一. 填空题 1.适配器模式,分为类的适配器和对象的适配器两种实现.其中类的适配器采用的是( )关系,而对象适配器采用的是()关系. 2.创立型模式的根本意图是要把( )和( )的责任进行分离,从而降低系统的( ). 3.MVC模型的基本工 ...查看


  • net互联网软件开发工程师 new-2
  • .NET互联网软件开发工程师 岗位描述: 字不能放在变量名首位 8.C# 数组从零开始建立索引,即数组索引从零开始.C# 中数组的工作方式与在大多数其他流行语言中的工作方式类似.但还有一些差异应引起注意. 声明数组时,方括号 ([]) 必须 ...查看


  • 软件常用英文常用
  • hardware 硬件 computer 计算机,Personal Computer(简称PC )个人计算机 keyboard 键盘 mouse 鼠标 monitor 监视器 LCD (Liquid Crystal Display) 液晶显 ...查看


  • 基于"C#程序设计"课程的混合式学习
  • [摘要]文章提出混合式学习的教学模式,并以"C#程序设计"课程为例进行了具体应用.主要针对教学思想和教学平台两方面的研究,在具体的教学单元中实施"主导-主体"的教育思想,采用"预习" ...查看


  • 网络故障排错总结
  • 一.常见测试命令 一. 常见windows 系统自带测试命令的测试范围 1. Ipconfig 命令 查看主机上的TCP/IP配置,包括IP 地址.子网掩码和默认网关等信息时使用ipconfig 命令. 命令格式如下: ipconfig [ ...查看


热门内容