故事
随着追求者与日俱增,小雪已经成了一名众人追捧的情人。小雪的手机功能越来越强,也同时给从事外贸工作的小雪增加了很多便利。我想,不久的将来,经典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。