设计模式系列漫谈之十 - 适配器模式

故事
         随着追求者与日俱增,小雪已经成了一名众人追捧的情人。小雪的手机功能越来越强,也同时给从事外贸工作的小雪增加了很多便利。我想,不久的将来,经典Design Pattern必将制造出比“芙蓉姐姐”还要大红大紫的“模式小姐”。

         可是,现在的小雪又遇到新的烦恼。前天的产品交易会上,小雪认识了一名来中国投资的日本商人。几个小时交谈,小雪的美丽、聪慧、善良给这名日本商人留下深刻的印象,并彼此留下了通讯方式。事后,小雪才想起她的手机不支持日文显示,怎么办呢?

         我们建议,在不改变原来功能的基础上,增加一个能够把日文短信翻译成中文短信的功能,然后按照原来的方式进行发送。

适配器模式的解决方案
      适配器模式,又成为包装模式(Wrapper),就是把一个类的接口包装客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。适配器模式有类的适配器模式和对象的适配器模式两种。我将分别使用两种Adapter模式达到小雪的要求。

1) 类的Adapter模式,需要定义的角色:
目标角色(IJapanMessage):这是客户所期待的接口。
源角色(NOKIA、MOTOROLA、SANSUNG):需要适配的类。
实现代码见:设计模式系列漫谈之二 - 工厂方法模式
适配器角色(NOKIAAdapter、MOTOROLAAdapter、SANSUNGAdapter):把源接口转换成目标接口。这一角色必须是类,并且继承源角色类。

目标角色接口如下:

namespace XiaoXue
{
   
public interface IJapanMessage
   {
        
void SendJapanMessage(object japanmsg);
   }
}

 适配器角色类如下:

namespace XiaoXue
{
    
public class NOKIAAdapter : NOKIA,IJapanMessage
    {
        
public void SendJapanMessage(object japanmsg)
        {
              
//把日文japanmsg翻译为中文msg
             
             
base.SendMessage(msg);
        }
    }

    
public class MOTOROLAAdapter : MOTOROLA,IJapanMessage
    {
        
public void SendJapanMessage(object japanmsg)
        {
            
//把日文japanmsg翻译为中文msg
             
             
base.SendMessage(msg);
        }
    }

    
public class SANSUNGAdapter : SANSUNG,IJapanMessage
    {
        
public void SendJapanMessage(object japanmsg)
        {
            
//把日文japanmsg翻译为中文msg
             
             
base.SendMessage(msg);
        }
    }
}

由于增加适配器角色,工厂类如下:

namespace XiaoXue
{
   
public class JapanMessageFactory
    {
       
public static IJapanMessage CreateJapanMessage(string Type)
        {
           IJapanMessage message
= null;
           
switch (Type)
           {
                
case "NOKIA":
                    message 
= new NOKIAAdapter();
                    
break;
               
case "MOTOROLA":
                   message 
= new MOTOROLAAdapter();
                   
break;
                
case "SANSUNG":
                    message 
= new SANSUNGAdapter();
                   
break;
            }
            
return message;
       }
   }
}

客户端调用方法:

IMessage message=JapanMessageFactory.CreateJapanMessage("NOKIA");
//发送日文短信
((IJapanMessage)message).SendJapanMessage("ありがとうございます"); 

2) 对象的Adapter模式
目标角色(IJapanMessage):这是客户所期待的接口。
源角色(NOKIA、MOTOROLA、SANSUNG):需要适配的类。
实现代码见:设计模式系列漫谈之二 - 工厂方法模式
配器角色(NOKIAAdapter、MOTOROLAAdapter、SANSUNGAdapter):通过聚合方式包装(Wrap)源角色对象,实现源接口转换成目标接口。

目标角色接口同上

适配器角色如下:

namespace XiaoXue
{
    
public class NOKIAAdapter : IJapanMessage
    {
          
private NOKIA _nokia;
          
public NOKIAAdapter(NOKIA nokia)
         {
                
this._nokia=nokia;
         }
        
public void SendJapanMessage(object japanmsg)
        {
            
//把日文japanmsg翻译为中文msg
            _nokia.SendMessage(msg);
        }
        
public void SendMessage(object msg)
        {
            _nokia.SendMessage(msg);
        }
    }

    
public class MOTOROLAAdapter :IJapanMessage
    {
        
private MOTOROLA _motorola;
        
public MOTOROLAAdapter(MOTOROLA motorola)
        {   
            
this._motorola=motorola;
        }
        
public void SendJapanMessage(object japanmsg)
        {
            
//把日文japanmsg翻译为中文msg
            _motorola.SendMessage(msg);
        }
        
public void SendMessage(object msg)
        {
            _motorola.SendMessage(msg);
        }
    }

    
public class SANSUNGAdapter : IJapanMessage
    {
        
private SANSUNG _sansung;
        
public SANSUNGAdapter(SANSUNG sansung)
        {
               
this._sansung=sansung;
        }
        
public void SendJapanMessage(object japanmsg)
        {
              
//把日文japanmsg翻译为中文msg
               _sansung.SendMessage(msg);
        }
        
public void SendMessage(object msg)
        {
            _sansung.SendMessage(msg);
        }
    }
}

由于增加适配器角色,工厂类实现如下:

namespace XiaoXue
{
   
public class JapanMessageFactory
    {
       
public static IJapanMessage CreateJapanMessage(string Type)
        {
           IJapanMessage japanMessage
= null;
           
switch (Type)
           {
                
case "NOKIA":
                    japanMessage
= new NOKIAAdapter(new NOKIA());
                    
break;
               
case "MOTOROLA":
                   japanMessage
= new MOTOROLAAdapter(new MOTOROLA());
                   
break;
                
case "SANSUNG":
                    picture 
= new SANSUNGAdapter(new SANSUNG());
                   
break;
            }
            
return japanMessage;
       }
   }
}


客户端调用方法:

IJapanMessage message=JapanMessageFactory.CreateJapanMessage("NOKIA");
//发送日文彩信
message.SendJapanMessage ("ありがとうございます"); 


为了更能说明适配器模式,引用一个生活例子:我使用的Dell笔记本的输入电压是19.5V,但是我们生活电压一般为220V,那么我就必须用通过专用的笔记本电源把220V转换为19.5V,那么这个笔记本电源就是Adapter。

posted @ 2007-12-23 07:37  李华星  阅读(465)  评论(0编辑  收藏  举报