今天一大早,你的 leader 就匆匆忙忙跑过来找到你:"快,快,紧急任务!最近 ChinaJoy 马上就要开始了,老板要求提供一种直观的方式,可以查看到我们新上线的游戏中每个服的在线人数."
你看了看日期,不是吧!这哪里是马上要开始了,分明是已经开始了!这怎么可能来得及呢?
"没关系的." 你的 leader 安慰你道:"功能其实很简单的,接口都已经提供好了,你只需要调用一下就行了."
好吧,你勉为其难地接受了,对于这种突如其来的新需求,你早已习惯.
你的 leader 向你具体描述了一下需求,你们的游戏目前有三个服,一服已经开放一段时间了,二服和三服都是新开的服.设计的接口非常轻便,你只需要调用 Utility.getOnlinePlayerCount(int),传入每个服对应的数值就可以获取到相应服在线玩家的数量了,如一服传入 1,二服传入 2,三服则传入 3.如果你传入了一个不存在的服,则会返回 - 1.然后你只要将得到的数据拼装成 XML 就好,具体的显示功能由你的 leader 来完成.
好吧,听起来功能并不是很复杂,如果现在就开始动工好像还来得及,于是你马上敲起了代码.
首先定义一个用于统计在线人数的接口 PlayerCount,代码如下:
接着定义三个统计类实现了 PlayerCount 接口,分别对应了三个不同的服,如下所示:
[java] view plain copy
public interface PlayerCount {
String getServerName();
int getPlayerCount();
}
然后定义一个 XMLBuilder 类,用于将各服的数据封装成 XML 格式,代码如下:
[java] view plain copy
public class ServerOne implements PlayerCount {
@Override
public String getServerName() {
return "一服";
}
@Override
public int getPlayerCount() {
return Utility.getOnlinePlayerCount(1);
}
}
[java] view plain copy
public class ServerTwo implements PlayerCount {
@Override
public String getServerName() {
return "二服";
}
@Override
public int getPlayerCount() {
return Utility.getOnlinePlayerCount(2);
}
}
[java] view plain copy
public class ServerThree implements PlayerCount {
@Override
public String getServerName() {
return "三服";
}
@Override
public int getPlayerCount() {
return Utility.getOnlinePlayerCount(3);
}
}
这样的话,所有代码就完工了,如果你想查看一服在线玩家数只需要调用:
[java] view plain copy
public class XMLBuilder {
public static String buildXML(PlayerCount player) {
StringBuilder builder = new StringBuilder();
builder.append("<root>");
builder.append("").append(player.getServerName()).append("</server>");
builder.append(""</player_count>");
builder.append("</root>");
return builder.toString();
}
}
查看二服在线玩家数只需要调用:
[java] view plain copy
XMLBuilder.buildXML(new ServerOne());
查看三服在线玩家数只需要调用:
[java] view plain copy
XMLBuilder.buildXML(new ServerTwo());
咦?你发现查看一服在线玩家数的时候,返回值永远是 - 1,查看二服和三服都很正常.
[java] view plain copy
XMLBuilder.buildXML(new ServerThree());
你只好把你的 leader 叫了过来:"我感觉我写的代码没有问题,但是查询一服在线玩家数总是返回 - 1,为什么会这样呢?"
"哎呀!" 你的 leader 猛然想起,"这是我的问题,前面没跟你解释清楚.由于我们的一服已经开放一段时间了,查询在线玩家数量的功能早就有了,使用的是 ServerFirst 这个类.当时写 Utility.getOnlinePlayerCount() 这个方法主要是为了针对新开的二服和三服,就没把一服的查询功能再重复做一遍."
听到你的 leader 这么说,你顿时松了一口气:"那你修改一下 Utility.getOnlinePlayerCount() 就好了,应该没我什么事了吧?"
"晤...本来应该是这样的...可是,Utility 和 ServerFirst 这两个类都已经被打到 Jar 包里了,没法修改啊..." 你的 leader 有些为难.
"什么?这不是坑爹吗,难道要我把接口给改了?" 你已经泪流满面了.
"这倒不用,这种情况下可以使用适配器模式,这个模式就是为了解决接口之间不兼容的问题而出现的."
其实适配器模式的使用非常简单,核心思想就是只要能让两个互不兼容的接口能正常对接就行了.上面的代码中,XMLBuilder 中使用 PlayerCount 这个接口来拼装 XML,而 ServerFirst 并没有实现 PlayerCount 这个接口,这个时候就需要一个适配器类来为 XMLBuilder 和 ServerFirst 之间搭起一座桥梁,毫无疑问,ServerOne 就将充当适配器类的角色.修改 ServerOne 的代码,如下所示:
这样通过 ServerOne 的适配,XMLBuilder 和 ServerFirst 之间就成功完成对接了!使用的时候我们甚至无需知道有 ServerFirst 这个类,只需要正常创建 ServerOne 的实例就行了.
[java] view plain copy
public class ServerOne implements PlayerCount {
private ServerFirst mServerFirst;
public ServerOne() {
mServerFirst = new ServerFirst();
}
@Override
public String getServerName() {
return "一服";
}
@Override
public int getPlayerCount() {
return mServerFirst.getOnlinePlayerCount();
}
}
需要值得注意的一点是,适配器模式不并是那种会让架构变得更合理的模式,更多的时候它只是充当救火队员的角色,帮助解决由于前期架构设计不合理导致的接口不匹配的问题.更好的做法是在设计的时候就尽量把以后可能出现的情况多考虑一些,在这个问题上不要向你的 leader 学习.
适配器:将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.
来源: http://www.bubuko.com/infodetail-2476108.html