设计模式系列漫谈之十 - 适配器模式
故事
随着追求者与日俱增,小雪已经成了一名众人追捧的情人。小雪的手机功能越来越强,也同时给从事外贸工作的小雪增加了很多便利。我想,不久的将来,经典Design Pattern必将制造出比“芙蓉姐姐”还要大红大紫的“模式小姐”。
可是,现在的小雪又遇到新的烦恼。前天的产品交易会上,小雪认识了一名来中国投资的日本商人。几个小时交谈,小雪的美丽、聪慧、善良给这名日本商人留下深刻的印象,并彼此留下了通讯方式。事后,小雪才想起她的手机不支持日文显示,怎么办呢?
我们建议,在不改变原来功能的基础上,增加一个能够把日文短信翻译成中文短信的功能,然后按照原来的方式进行发送。
适配器模式的解决方案
适配器模式,又成为包装模式(Wrapper),就是把一个类的接口包装客户端所期待的另一种接口,从而使原本接口不匹配而无法在一起工作的两个类能够在一起工作。适配器模式有类的适配器模式和对象的适配器模式两种。我将分别使用两种Adapter模式达到小雪的要求。
1) 类的Adapter模式,需要定义的角色:
目标角色(IJapanMessage):这是客户所期待的接口。
源角色(NOKIA、MOTOROLA、SANSUNG):需要适配的类。 实现代码见:设计模式系列漫谈之二 - 工厂方法模式
适配器角色(NOKIAAdapter、MOTOROLAAdapter、SANSUNGAdapter):把源接口转换成目标接口。这一角色必须是类,并且继承源角色类。
目标角色接口如下:
{
public interface IJapanMessage
{
void SendJapanMessage(object japanmsg);
}
}
适配器角色类如下:
{
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);
}
}
}
由于增加适配器角色,工厂类如下:
{
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;
}
}
}
客户端调用方法:
//发送日文短信
((IJapanMessage)message).SendJapanMessage("ありがとうございます");
2) 对象的Adapter模式
目标角色(IJapanMessage):这是客户所期待的接口。
源角色(NOKIA、MOTOROLA、SANSUNG):需要适配的类。 实现代码见:设计模式系列漫谈之二 - 工厂方法模式
适配器角色(NOKIAAdapter、MOTOROLAAdapter、SANSUNGAdapter):通过聚合方式包装(Wrap)源角色对象,实现源接口转换成目标接口。
目标角色接口同上
适配器角色如下:
{
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);
}
}
}
由于增加适配器角色,工厂类实现如下:
{
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;
}
}
}
客户端调用方法:
//发送日文彩信
message.SendJapanMessage ("ありがとうございます");
为了更能说明适配器模式,引用一个生活例子:我使用的Dell笔记本的输入电压是19.5V,但是我们生活电压一般为220V,那么我就必须用通过专用的笔记本电源把220V转换为19.5V,那么这个笔记本电源就是Adapter。