C# 设计模式 之 适配器模式(Adapter)

    抽象地说,如果客户需要使用某个类的服务,而这项服务是这个类用一个不同的接口提供的,那么就可以使用适配器模式(Adapter)为客户提供一个期望的接口。

    具体地说,现有的类已经提供了客户所需要的服务,但是方法的名称不相同,通过使用适配器模式(Adapter)为客户提供一个类,这个类包含客户需要的完成相同服务且方法名称相同的方法。

   这里分两种情况:

  (1) 客户用接口定义了它所需要的服务,存在一个类提供了客户所需要的服务。这时,适配器模式(Adapter)是:创建一个新类,它继承提供服务的类,实现了客户的接口。它简称类适配器模式。代码如下:

using  System;
using  System.Collections.Generic;
using  System.Text;

/// <!--
/// 创建人  : 逍遥剑客
/// 创建时间: 2006-10-29
/// -->

namespace  ClassAdapterModel
{

    
/// <summary>
    
/// 供了客户所需要的服务的类
    
/// </summary>

    class ExistingClass
    
{
        
public void UsefulMethod(string inputParam)
        
{
            Console.WriteLine(
"完成客户使需要的服务! 传入的参数为:" + inputParam);
        }


    }


    
/// <summary>
    
/// 客户定义的接口
    
/// </summary>

    interface IRequiredInterface
    
{
        
void RequiredMenthod(string inputParam);
    }


    
/// <summary>
    
/// 创建一个新类,它继承提供服务的类,实现了客户的接口
    
/// </summary>

    class NewClass : ExistingClass, IRequiredInterface
    
{
        
public void RequiredMenthod(string inputParam)
        
{
            UsefulMethod(inputParam);
        }


    }


    
/// <summary>
    
/// 客户类,通过该类创建一个客户对象,它需要 ExistingClass 提供的服务
    
/// </summary>

    class Client
    
{
        
/// <summary>
        
/// 构造函数
        
/// </summary>

        public Client()
        
{
            Console.WriteLine(
"构造函数!");
        }


        
static void Main(string[] args)
        
{
            Client clt 
= new Client();
            NewClass nc 
= new NewClass();
            IRequiredInterface ir 
= nc;
            ir.RequiredMenthod(
"客户类参数");
        }

    }

}

  (2) 客户没有定义它需要提供服务的接口,但是有一个客户使用的类,另外存在一个类提供了客户所需要的服务。这时,我们适配器模式(Adapter)是:创建一个新类,它继承客户使用的类,然后利用提供服务的类创建用一个对象,新类通过使用这个对象的方法来完成所需要的服务。它简称对象适配器模式。代码如下:

using  System;
using  System.Collections.Generic;
using  System.Text;

/// <!--
/// 创建人  : 逍遥剑客
/// 创建时间: 2006-10-29
/// -->

namespace  ObjectAdapterModel
{

    
/// <summary>
    
/// 供了客户所需要的服务的类
    
/// </summary>

    class ExistingClass
    
{
        
public void UsefulMethod(string inputParam)
        
{
            Console.WriteLine(
"完成客户使需要的服务! 传入的参数为:" + inputParam);
        }


    }


    
/// <summary>
    
/// 客户类,通过该类创建一个客户对象,它需要 ExistingClass 提供的服务
    
/// </summary>

    class Client
    
{
        
/// <summary>
        
/// 构造函数
        
/// </summary>

        public Client()
        
{
            Console.WriteLine(
"构造函数!");
        }


        
/// <summary>
        
/// 该类自身具有的功能
        
/// </summary>
        
/// <param name="inputParam">输入参数</param>

        public virtual void RequiredMenthod(string inputParam)
        
{
            Console.WriteLine(
"该类自身具有的功能,但不足以完成任务! 传入的参数为:" + inputParam);
        }

    }


    
/// <summary>
    
/// 创建一个新类,它继承客户类
    
/// </summary>

    class NewClass : Client
    
{
        
private ExistingClass es = new ExistingClass();

        
/// <summary>
        
/// 新类通过使用创建提供服务类的对象的方法来完成所需要的服务
        
/// </summary>
        
/// <param name="inputParam">输入参数</param>

        public override void RequiredMenthod(string inputParam)
        
{
            es.UsefulMethod(inputParam);
        }


        
static void Main(string[] args)
        
{
            Client clt 
= new Client();
            clt.RequiredMenthod(
"客户类参数");
        }

    }

}

 

   (1)类适配器模式和(2)对象适配器模式比较,后者的设计方案非常脆弱。首先,因为后者在创建一个新类,继承客户使用的类,要求客户使用的类的方法标记为 virtual。如果没有标记,则在子类中无法覆盖(override)其方法。再次,如果后者的客户使用类的方法名可能改变,从而引起子类中的方法名称的变化。

   所以,一般情况下,需要在一个接口中定义一个客户程序的要求,即使用类适配器模式。但是,如果无法预先定义客户需要的接口,那么也可以使用对象适配器模式,这时需要在客户使用类中用virtual标记可能在子类中被覆盖的方法。

    另外提到一个简单的对.Net的数据进行适配的例子,但是它并没有使用适配器模式(Adapter)。这个适配器将数据库与显示数据的表格协同工作。下面代码仅提供一种思路,无法运行。我们可以通过创建一个类实现一个接口来替代这两条语句(g.DataSource = tb; g.DataBinding();),从而完成数据源的绑定,这采用了(1)中的类适配器模式,体现了绑定的灵活性。代码如下:

/// <summary>
/// 使得 DataTable 与 GridView 协同工作
/// 代码无法运行,仅供理解使用
/// </summary>

public   class  DataAdapterExample
{
    
public void DataAdapterExample()
    
{

        
string strSql = "SELECT * FROM DataAdapterExample";
        DataTable tb 
= new DataTable();
        Database dbTemp 
= BasicOperate.CreateDataBase();
        DbCommand cmdTemp 
= dbTemp.GetSqlStringCommand(strSql);
        tb 
= dbTemp.ExecuteDataSet(cmdTemp).Tables[0];

        GridView g 
= new GridView();
        g.DataSource 
= tb;
        g.DataBinding();

    }

}

本文参考:
[1] 《C# 设计模式》《 Desing Patterns in C#》(美)Steven John Metsker 著, 颜炯 译。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值