温故而知新:设计模式之适配器模式(Adapter)

简介: 借用terrylee的原话: Adapter模式主要应用于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移等方面非常有用。 适配器模式再次体现了“面向接口编程,而非面向实现编程”这一精神。

借用terrylee的原话:

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

适配器模式再次体现了“面向接口编程,而非面向实现编程”这一精神。

场景:

有一个基于数据库的系统,里面的数据库操作就拿最常用的查询来说,主要是用SqlHelper类里的QueryData(string sql)这个方法来处理的,后来意外发现该方法实现上性能并不是最好(或者不能满足新的需要),而这时正好有一个第三方的DbHelper程序集,写得很成熟性能也不错,但唯一不足的是里面的查询方法签名是SelectData(string sql),怎么办?所有引用SqlHelper的地方全部修改,重头编译么?No,没人会想这样


先看下原来的代码:

using  System;
using  System.Data;

namespace  Adapter
{
    
class  Program
    {
        
static   void  Main( string [] args)
        {
            IDBHelper dbhelper 
=   new  SqlHelper();
            dbhelper.QueryData(
" Select * from TableA " );

            Console.ReadKey();
        }
    }

    
public   interface  IDBHelper 
    {
        DataSet QueryData(
string  sql);
    }

    
public   class  SqlHelper : IDBHelper 
    {
        
public  DataSet QueryData( string  sql) 
        {
            Console.WriteLine(
" QueryData is Called,the sql is :\ " { 0 }\ "" ,sql);
            
return   new  DataSet(); // 这里演示起见,就直接返回一个DataSet实例完事 :)
        }
    }
}

 

如何在尽量不影响原有客户端代码的情况下,用新的DbHelper来取代旧的SqlHelper呢?

假如第三方的DBHelper结构如下:

 

///   <summary>
    
///  第三方的新dbHelper,实际场景中,这个类通常都是封装在程序集中以dll提供,客户端程序无法修改
    
///   </summary>
     public   class  DbHelper 
    {
        
public  DataSet SelectData( string  sql)
        {
            Console.WriteLine(
" SelectData is Called,the sql is :\ " { 0 }\ "" , sql);
            
return   new  DataSet(); // 这里演示起见,就直接返回一个DataSet实例完事 :)
        }
    }

 

可以新增一个适配器:

     ///   <summary>
    
///  新增的适配器
    
///   </summary>
     public   class  DBHelperAdapter : IDBHelper 
    {
        
private  DbHelper _dbHelper;

        
public  DBHelperAdapter(DbHelper dbHelper) 
        {
            
this ._dbHelper  =  dbHelper;
        }

        
public  DataSet QueryData( string  sql)         
        {
            
return  _dbHelper.SelectData(sql);
        }

    }

 

这样原有的客户端程序,只需要把
IDBHelper dbhelper = new SqlHelper();

改成:

IDBHelper dbhelper = new DBHelperAdapter(new DbHelper()); 就万事大吉了,当然你可以用配置文件+反射,完全解耦,此处略过

反思:

本例中之所以能轻易将新的类替换旧的类,主要得益于旧的代码仅依赖于抽象(即接口IDBHelper),而非具体的实现(即类SqlHelper),否则也不可能达到最终效果。

OO原则中的"面对接口编码","依赖倒置"的妙处也就在于此。

 

最后给出类图:

img_1d28494b7b74a2cc00ec76f933a83e59.png

目录
相关文章
|
17天前
|
设计模式 Java 中间件
23种设计模式,适配器模式的概念优缺点以及JAVA代码举例
【4月更文挑战第6天】适配器模式(Adapter Pattern)是一种结构型设计模式,它的主要目标是让原本由于接口不匹配而不能一起工作的类可以一起工作。适配器模式主要有两种形式:类适配器和对象适配器。类适配器模式通过继承来实现适配,而对象适配器模式则通过组合来实现
30 4
|
1月前
|
设计模式 算法 API
适配器模式:C++设计模式中的瑞士军刀
适配器模式:C++设计模式中的瑞士军刀
47 0
|
1月前
|
设计模式
设计模式之适配器模式
设计模式之适配器模式
|
1月前
|
设计模式 Java 程序员
【设计模式】适配器模式
【设计模式】适配器模式
|
3月前
|
设计模式 程序员
【设计模式】适配器模式
【1月更文挑战第27天】【设计模式】适配器模式
|
3月前
|
设计模式
设计模式-类适配器模式
设计模式-类适配器模式
13 0
|
3月前
|
设计模式 uml
设计模式-适配器模式1
设计模式-适配器模式1
22 0
设计模式-适配器模式1
|
3月前
|
设计模式 uml
设计模式-适配器模式(对象适配器)
设计模式-适配器模式(对象适配器)
19 0
|
3月前
|
设计模式
设计模式-适配器模式
设计模式-适配器模式
|
3月前
|
设计模式
设计模式 | 适配器模式
设计模式 | 适配器模式
16 0