Ruby设计模式透析之——适配器(Adapter)


Java设计模式透析之 —— 适配器(Adapter)

今天一大早,你的leader就匆匆忙忙跑过来找到你:“快,快,紧急任务!最近ChinaJoy马上就要开始了,老板要求提供一种直观的方式,可以查看到我们新上线的游戏中每个服的在线人数。”

你看了看日期,不是吧!这哪里是马上要开始了,分明是已经开始了!这怎么可能来得及呢?

“没关系的。”你的leader安慰你道:“功能其实很简单的,接口都已经提供好了,你只需要调用一下就行了。”

好吧,你勉为其难地接受了,对于这种突如其来的新需求,你早已习惯。

你的leader向你具体描述了一下需求,你们的游戏目前有三个服,一服已经开放一段时间了,二服和三服都是新开的服。设计的接口非常轻便,你只需要调用Utility.online_player_count(Fixnum),传入每个服对应的数值就可以获取到相应服在线玩家的数量了,如一服传入1,二服传入2,三服则传入3。如果你传入了一个不存在的服,则会返回-1。然后你只要将得到的数据拼装成XML就好,具体的显示功能由你的leader来完成。

好吧,听起来功能并不是很复杂,如果现在就开始动工好像还来得及,于是你马上敲起了代码。

首先定义一个用于统计在线人数的父类PlayerCount,代码如下:

class PlayerCount

	def server_name
		raise "You should override this method in subclass."
	end
	
	def player_count
		raise "You should override this method in subclass."
	end

end

接着定义三个统计类继承PlayerCount,分别对应了三个不同的服,如下所示:

class ServerOne < PlayerCount

	def server_name
		"一服"
	end
	
	def player_count
		Utility.online_player_count(1)
	end

end
class ServerTwo < PlayerCount

	def server_name
		"二服"
	end
	
	def player_count
		Utility.online_player_count(2)
	end

end
class ServerThree < PlayerCount

	def server_name
		"三服"
	end
	
	def player_count
		Utility.online_player_count(3)
	end

end

然后定义一个XMLBuilder类,用于将各服的数据封装成XML格式,代码如下:

class XMLBuilder

	def self.build_xml player
		builder = ""
		builder << "<root>"
		builder << "<server>" << player.server_name << "</server>"
		builder << "<player_count>" << player.player_count.to_s << "</player_count>"
		builder << "</root>"
	end

end

这样的话,所有代码就完工了,如果你想查看一服在线玩家数只需要调用:

XMLBuilder.build_xml(ServerOne.new)

查看二服在线玩家数只需要调用:

XMLBuilder.build_xml(ServerTwo.new)

查看三服在线玩家数只需要调用:

XMLBuilder.build_xml(ServerThree.new)

咦?你发现查看一服在线玩家数的时候,返回值永远是-1,查看二服和三服都很正常。

你只好把你的leader叫了过来:“我感觉我写的代码没有问题,但是查询一服在线玩家数总是返回-1,为什么会这样呢?”

“哎呀!”你的leader猛然想起,“这是我的问题,前面没跟你解释清楚。由于我们的一服已经开放一段时间了,查询在线玩家数量的功能早就有了,使用的是ServerFirst这个类。当时写Utility.online_player_count()这个方法主要是为了针对新开的二服和三服,就没把一服的查询功能再重复做一遍。这种情况下可以使用适配器模式,这个模式就是为了解决接口之间不兼容的问题而出现的。”

其实适配器模式的使用非常简单,核心思想就是只要能让两个互不兼容的接口能正常对接就行了。上面的代码中,XMLBuilder中使用PlayerCount来拼装XML,而ServerFirst并没有继承PlayerCount,这个时候就需要一个适配器类来为XMLBuilder和ServerFirst之间搭起一座桥梁,毫无疑问,ServerOne就将充当适配器类的角色。修改ServerOne的代码,如下所示:

class ServerOne < PlayerCount

	def initialize
		@serverFirst = ServerFirst.new
	end

	def server_name
		"一服"
	end
	
	def player_count
		@serverFirst.online_player_count
	end

end

这样通过ServerOne的适配,XMLBuilder和ServerFirst之间就成功完成对接了!使用的时候我们甚至无需知道有ServerFirst这个类,只需要正常创建ServerOne的实例就行了。

需要值得注意的一点是,适配器模式不并是那种会让架构变得更合理的模式,更多的时候它只是充当救火队员的角色,帮助解决由于前期架构设计不合理导致的接口不匹配的问题。更好的做法是在设计的时候就尽量把以后可能出现的情况多考虑一些,在这个问题上不要向你的leader学习。

适配器:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

优质内容筛选与推荐>>
1、HTML 表单
2、【Maven】2.使用Nexus3搭建Maven私服+上传第三方jar包到本地maven仓库
3、RMI与RPC的区别
4、线程池(Executor)
5、maven 之在Eclipse中使用maven


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号