转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9400153

此为Java设计模式透析的拷贝版,专门为Ruby爱好者提供的,不熟悉Ruby语法的朋友请转阅 :

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学习。

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

Ruby设计模式透析之 —— 适配器(Adapter)的更多相关文章

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

    转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9400141 今天一大早,你的leader就匆匆忙忙跑过来找到你:“快,快,紧急任务 ...

  2. Ruby设计模式透析之 —— 组合(Composite)

    转载请注明出处:http://blog.csdn.net/sinyu890807/article/details/9153761 此为Java设计模式透析的拷贝版,专门为Ruby爱好者提供的,不熟悉R ...

  3. 设计模式C++描述----06.适配器(Adapter)模式

    一. 定义 适配器模式将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. Adapter 模式的两种类别:类模式和对象模式. 二. 举例说明 实际中 ...

  4. Java设计模式透析之 —— 单例(Singleton)

    写软件的时候经常需要用到打印日志功能,可以帮助你调试和定位问题,项目上线后还可以帮助你分析数据.但是Java原生带有的System.out.println()方法却很少在真正的项目开发中使用,甚至像f ...

  5. Headfirst设计模式的C++实现——适配器(Adapter)

    duck.h #ifndef _DUCK_H_ #define _DUCK_H_ class DUCK { public: ; ; }; #endif mallard_duck.h #ifndef _ ...

  6. Java设计模式透析之 —— 策略(Strategy)

    今天你的leader兴致冲冲地找到你,希望你能够帮他一个小忙.他如今急着要去开会.要帮什么忙呢?你非常好奇. 他对你说.当前你们项目的数据库中有一张用户信息表.里面存放了非常用户的数据.如今须要完毕一 ...

  7. Java设计模式透析之 —— 模板方法(Template Method)

    今天你还是像往常一样来上班,一如既往地開始了你的编程工作. 项目经理告诉你,今天想在server端添加一个新功能.希望写一个方法.能对Book对象进行处理.将Book对象的全部字段以XML格式进行包装 ...

  8. Java设计模式透析之 —— 组合(Composite)

    听说你们公司最近新推出了一款电子书阅读应用,市场反应很不错,应用里还有图书商城,用户可以在其中随意选购自己喜欢的书籍.你们公司也是对此项目高度重视,加大了投入力度,决定给此应用再增加点功能. 好吧,你 ...

  9. 设计模式--适配器(Adapter)模式

    今天学习另一个设计模式,适配器(Adapter)模式,这是一个共同方向,但有特殊要求,就应用到此设计模式.写到这里,想起很久以前,有写过一篇<ASP.NET的适配器设计模式(Adapter)&g ...

随机推荐

  1. Matlab:拟合(1)

    拟合练习: function f = curvefun(x, tdata) f = (x()*x()*x()) / (x()-x()) * ( exp(-x()*tdata)/(x()-x()) + ...

  2. Java8 时间 API

    前言 Java8 中最为人津津乐道的新改变恐怕当属函数式 API 的加入.但实际上,Java8 所加入的新功能远不止这个. 本文将基于<Java SE8 for the Really Impat ...

  3. UIStackView相关

    从iOS9开始,苹果提供了UIStackView来帮助我们做布局,这玩意儿类似于安卓的线性布局.因为在使用过程中会遇到一些坑,所以写出来供遇到同样问题的人参考.我在这里提供xib和纯代码两种方式创建使 ...

  4. [置顶] JSP中使用taglib出错终极解决办法

    jsp中 <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <c ...

  5. 数据库安全之TDE列加密

    透明数据加密(Transparent Data Encryption) TDE - 基于列的加密 由于有了Oracle的TDE-基于列的加密,你所要做的只是定义需要加密的列,Oracle将为包含加密列 ...

  6. (转)Maven实战(五)坐标详解

    1.为什么要定义Maven坐标      在我们开发Maven项目的时候,需要为其定义适当的坐标,这是Maven强制要求的.在这个基础上,其他Maven项目才能应用该项目生成的构件. 2.Maven坐 ...

  7. 【mac开发.NET】No installed provisioning profiles match the installed iOS signing identities

    编译错误提示 /Library/Frameworks/Mono.framework/External/xbuild/Xamarin/iOS/Xamarin.iOS.Common.targets: Er ...

  8. Core Services 层

    Core Services层为所有的应用程序提供基础系统服务.可能应用程序并不直接使用这些服务,但它们是系统很多部分赖以建构的基础. 高阶特性 下面的部分描述一些比较常见特性,也许您正打算让您的应用程 ...

  9. iOS 在 Xcode 中重命名项目名称

    本教程使用的 Xcode 版本是Xcode 6.3.1,网上有好多的教程,都是在 Xcode 4 上做的讲解,现以本文章讲解一下如何在 Xcode 6.3.1 中重命名你的项目名称,包括你的应用名称. ...

  10. Android EditText的使用及值得注意的地方

    Android上有很多输入法应用,每种输入法都有各自的特点,输入法多数时候是和EditText配合使用,结合我自己的亲身实践分享一下使用EditText过程中遇到的一些问题及解决方法. 设置默认输入法 ...