好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

步步为营 .NET 设计模式学习笔记 六、Adapter(适配器模式)

步步为营 .NET 设计模式学习笔记 六、Adapter(适配器模式)

概述

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

意图

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

结构图

图1 类的Adapter模式结构图

图2 对象的Adapter模式结构图

生活中的例子

适配器模式允许将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。扳手提供了一个适配器的例子。一个孔套在棘齿上,棘齿的每个边的尺寸是相同的。在美国典型的边长为1/2''和1/4''。显然,如果不使用一个适配器的话,1/2''的棘齿不能适合1/4''的孔。一个1/2''至1/4''的适配器具有一个1/2''的阴槽来套上一个1/2''的齿,同时有一个1/4的阳槽来卡入1/4''的扳手。

图3使用扳手适配器例子的适配器对象图

示例图用例设计:

先创建User.cs

01 public   class   User

02 {

03      public   int   ID

04      {

05          get ;

06          set ;

07      }

08      public   string   Name

09      {

10          get ;

11          set ;

12      }

13      public   string   Age

14      {

15          get ;

16          set ;

17      }

18 }

1    

1 然后再新建IDBHelper.cs

01 public   interface   IDBHelper

02 {

03      /// <summary>

04      /// 连接字符串

05      /// </summary>

06      /// <returns></returns>

07      string   DBConnectString();

08      /// <summary>

09      /// 返回结果集

10      /// </summary>

11      /// <param name="strsql"></param>

12      /// <returns></returns>

13      DataSet GetUserGroup( string   strsql);

14      /// <summary>

15      /// 返回插入的行数

16      /// </summary>

17      /// <param name="user"></param>

18      /// <returns></returns>

19      int   InsertUser(User user);

20 }

1    

1 然后再新建SQLHelper.cs:

01 public    class   SQLHelper:IDBHelper

02     {

03         #region IDBHelper 成员

04  

05         public   string   DBConnectString()

06         {

07             return   "SQL Connect String" ;

08         }

09  

10         public   DataSet GetUserGroup( string   strsql)

11         {

12             DataSet ds =  new   DataSet();

13             return   ds;

14         }

15  

16         public   int   InsertUser(User user)

17         {

18             return   1;

19         }

20  

21         #endregion

22     }

1 然后再新建OracleHelper.cs:

01 public    class   OracleHelper:IDBHelper

02     {

03         #region IDBHelper 成员

04  

05         public   string   DBConnectString()

06         {

07             return   "Oracle Connect String." ;

08         }

09  

10         public   DataSet GetUserGroup( string   strsql)

11         {

12             DataSet ds =  new   DataSet();

13             return   ds;

14         }

15  

16         public   int   InsertUser(User user)

17         {

18             return   1;

19         }

20  

21         #endregion

22     }

然后再建DataContent.cs:

01 public   class   DataContent:IDBHelper

02    {

03        private   IDBHelper DbHelper = GetDBHelper();

04        public   static   IDBHelper GetDBHelper()

05        {

06             

07            string   strClass = ConfigurationSettings.AppSettings[ "DBHeper" ].ToString();

08            Assembly assembly =  Assembly.Load( "Adapter" );

09            IDBHelper dbHelper = assembly.CreateInstance(strClass)  as   IDBHelper;

10            return   dbHelper;

11        }

12  

13        #region IDBHelper 成员

14  

15        public   string   DBConnectString()

16        {

17            return   DbHelper.DBConnectString();

18        }

19  

20        public   System.Data.DataSet GetUserGroup( string   strsql)

21        {

22            return   DbHelper.GetUserGroup(strsql);

23        }

24  

25        public   int   InsertUser(User user)

26        {

27           return   DbHelper.InsertUser(user);

28        }

29  

30        #endregion

31    }

在App.config里加下面代码:

1 <appSettings>

2    <add key= "DBHeper"   value= "Adapter.SQLHelper" />

3   <!--<add key= "DBHeper"   value= "Adapter.OracleHelper" />-->

4 </appSettings>

看我们的调用程序:

01 public   partial   class   Run : Form

02 {

03      public   Run()

04      {

05          InitializeComponent();

06      }

07  

08      private   void   btnRun_Click( object   sender, EventArgs e)

09      {

10  

11          DataContent dataContent =  new   DataContent();

12          rtbResult.AppendText(dataContent.DBConnectString());

13      }

14 }

结果如图:

 

实现要点

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

2.Adapter模式有对象适配器和类适配器两种形式的实现结构,但是类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合精神。

3.Adapter模式的实现可以非常的灵活,不必拘泥于GOF23中定义的两种结构。例如,完全可以将Adapter模式中的“现存对象”作为新的接口方法参数,来达到适配的目的。

4.Adapter模式本身要求我们尽可能地使用“面向接口的编程”风格,这样才能在后期很方便的适配。[以上几点引用自MSDN WebCast]

5. 适配器模式是否能成功运用的关键在于代码本身是否是基于接口编程的,如果不是的话,那么适配器无能为力。

6. 适配器模式的实现很简单,基本的思想就是适配器一定是遵循目标接口的。

7. 适配器模式的变化比较多,可以通过继承和组合方式进行适配,适配器可以是一组适配器产品,适配器也可以是抽象类型。

8.  适配器模式和Facade的区别是,前者是遵循接口的,后者可以是不遵循接口的,比较灵活。

9.  适配器模式和Proxy的区别是,前者是为对象提供不同的接口,或者为对象提供相同接口,并且前者有一点后补的味道,后者是在设计时就会运用的。

效果

对于类适配器:

1.用一个具体的Adapter类对Adaptee和Taget进行匹配。结果是当我们想要匹配一个类以及所有它的子类时,类Adapter将不能胜任工作。

2.使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类。

3.仅仅引入了一个对象,并不需要额外的指针一间接得到Adaptee.

对于对象适配器:

1.允许一个Adapter与多个Adaptee,即Adaptee本身以及它的所有子类(如果有子类的话)同时工作。Adapter也可以一次给所有的Adaptee添加功能。

2.使得重定义Adaptee的行为比较困难。这就需要生成Adaptee的子类并且使得Adapter引用这个子类而不是引用Adaptee本身。

适用性

在以下各种情况下使用适配器模式:

1.系统需要使用现有的类,而此类的接口不符合系统的需要。

2.想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作。这些源类不一定有很复杂的接口。

3.(对对象适配器而言)在设计里,需要改变多个已有子类的接口,如果使用类的适配器模式,就要针对每一个子类做一个适配器,而这不太实际。

4. 从代码角度来说, 如果需要调用的类所遵循的接口并不符合系统的要求或者说并不是客户所期望的,那么可以考虑使用适配器。

5. 从应用角度来说, 如果因为产品迁移、合作模块的变动,导致双方一致的接口产生了不一致,或者是希望在两个关联不大的类型之间建立一种关系的情况下可以考虑适配器模式。

总结

总之,通过运用Adapter模式,就可以充分享受进行类库迁移、类库重用所带来的乐趣。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于步步为营 .NET 设计模式学习笔记 六、Adapter(适配器模式)的详细内容...

  阅读:43次

CopyRight:2016-2025好得很程序员自学网 备案ICP:湘ICP备09009000号-16 http://www.haodehen.cn
本站资讯不构成任何建议,仅限于个人分享,参考须谨慎!
本网站对有关资料所引致的错误、不确或遗漏,概不负任何法律责任。
本网站刊载的所有内容(包括但不仅限文字、图片、LOGO、音频、视频、软件、程序等)版权归原作者所有。任何单位或个人认为本网站中的内容可能涉嫌侵犯其知识产权或存在不实内容时,请及时通知本站,予以删除。

网站内容来源于网络分享,如有侵权发邮箱到:kenbest@126.com,收到邮件我们会即时下线处理。
网站框架支持:HDHCMS   51LA统计 百度统计
Copyright © 2018-2025 「好得很程序员自学网
[ SiteMap ]