设计模式学习笔记--Adapter适配器模式

一、如何定义:
  适配器模式是一种结构型模式,它把一个类的接口变换成客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。
二、如何理解:
  就以本例的故事作为对适配器模式的理解:有一个厨师,他会做许多种菜品,如果你给他说我要麻婆豆腐,Ok,他听得懂你说的,并直接给你炒了一份麻婆豆腐。现在,我们来到皇潮大酒店吃饭,这个酒店的菜谱上提供的不再是具体的菜名,而是按照荤菜,素菜,汤菜等菜品上菜,具体什么菜由他们来给你配,你无权直接点菜名(有点过份哈),但不管是什么菜,都是由那个厨师在做,我们不是直接和厨师打交道,而是和酒店打交道,按照酒店提供的服务接口(即:荤,素、汤)点菜。过了一段时间,我们到另一家名叫兴隆大酒店的馆子吃饭,这家酒店的菜谱也不直接提供菜名,而是按川菜,鲁菜,粤菜等菜系的方式上菜,具体什么菜还是由他们来给你配,但巧的是,上次在皇潮大酒店做工的那个厨师已经跳槽到了这家兴隆大酒店,所以实际的具体菜品还是那些,只不过,这次我们不是按荤、素、汤来点菜,而是按兴隆大酒店给我们提供的服务接口(川、鲁、粤)来点菜。所以,这个故事中,我们遇到了三种点菜的方式,一是直接提供菜名给厨师,则他来直接炒菜给我们。二是按荤,素、汤三类来配套餐。三是按菜系名来配套餐。其中,第一种是我们原系统中已经有的方式了。后两种是我们系统在扩展过程中新出现的需求,如何重复使用同一个厨师(代码复用),而不是分别请不同的厨师来满足后面两种需求呢?

三、适配器模式所涉及的角色包括:
  1、目标(Target)角色:这是客户所期待的接口(就是上面故事中提到的按荤素汤来点菜或按川鲁粤来点菜)。因为C#不支持多继承,所以Target必须是接口,不可以是类。
  2、源(Adaptee)角色:需要适配的类(就是上面提到的厨师)。
  3、适配器(Adapter)角色:把源接口转换成目标接口。这一角色必须是类。(通过此类,把厨师能接受的相关菜品转换成酒店能接受的菜品分类方式)

四、适配器模式的两种形式
 适配器模式有类的适配器模式和对象的适配器模式两种。我们将分别实现这两种Adapter模式

五、故事的实现
程序如图:
                        
1、源(Adaptee)角色定义
  定义厨师师傅类

Code

2、目标(Target)角色定义
  皇潮酒店要求的菜谱接口

 

Code

  兴隆酒店要求的菜谱接口

Code

3、适配器(Adapter)角色定义
  对象的Adapter模式示意性实现(用此方式实现皇潮酒店的菜谱要求):


Code

  类的Adapter模式示意性实现(用此方式实现兴隆酒店的菜谱要求):

Code

4、客户端调用


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

namespace AdapterPattern
{
    
class Program
    {
        
static void Main(string[] args)
        {
            EmpireAdapter emp 
= new EmpireAdapter();
            Console.WriteLine(
"-----我要荤菜类清单-----");
            emp.HunCai();
            Console.WriteLine(
"-----我要素菜类清单-----");
            emp.ShuCai();
            Console.WriteLine(
"-----我要汤菜类清单-----");
            emp.TangCai();

            XingLongAdapter xla 
= new XingLongAdapter();
            Console.WriteLine(
"-----我要川菜清单-----");
            xla.ChuanCai();
            Console.WriteLine(
"-----我要鲁菜清单-----");
            xla.LuCai();
            Console.WriteLine(
"-----我要粤菜清单-----");
            xla.YueCai();

            Console.Read();
        }
    }
}

六、何时采用
  从代码角度来说, 如果需要调用的类所遵循的接口并不符合系统的要求或者说并不是客户所期望的,那么可以考虑使用适配器。
  从应用角度来说, 如果因为产品迁移、合作模块的变动,导致双方一致的接口产生了不一致,或者是希望在两个关联不大的类型之间建立一种关系的情况下可以考虑适配器模式。


七、实现要点
   适配器模式是否能成功运用的关键在于代码本身是否是基于接口编程的,如果不是的话,那么适配器无能为力。
   适配器模式的实现很简单,基本的思想就是适配器一定是遵循目标接口的。
   适配器模式的变化比较多,可以通过继承和组合方式进行适配,适配器可以是一组适配器产品,适配器也可以是抽象类型。
   适配器模式和Facade的区别是,前者是遵循接口的,后者可以是不遵循接口的,比较灵活。
   适配器模式和Proxy的区别是,前者是为对象提供不同的接口,或者为对象提供相同接口,并且前者有一点后补的味道,后者是在设计时就会运用的。

八、注意事项
   在对两个无关类进行适配的时候考虑一下适配的代价,一个非常庞大的适配器可能会对系统性能有影响。
运行效果如下图:

                         

前往:设计模式学习笔记清单
posted @ 2009-09-30 12:32  wsdj  阅读(970)  评论(3编辑  收藏  举报