??xml version="1.0" encoding="utf-8" standalone="yes"?>久久91亚洲人成电影网站,亚洲欧洲日本天天堂在线观看,国产亚洲精品仙踪林在线播放http://m.tkk7.com/qileilove/category/53091.html不想做屌丝的码农Q不是好目l理Q屌丝生涯从此开始!zh-cnThu, 13 Mar 2014 12:28:48 GMTThu, 13 Mar 2014 12:28:48 GMT60一个用于网站自动化试的生态系l实?/title><link>http://m.tkk7.com/qileilove/archive/2014/03/13/410968.html</link><dc:creator>其自然EVO</dc:creator><author>其自然EVO</author><pubDate>Thu, 13 Mar 2014 03:34:00 GMT</pubDate><guid>http://m.tkk7.com/qileilove/archive/2014/03/13/410968.html</guid><wfw:comment>http://m.tkk7.com/qileilove/comments/410968.html</wfw:comment><comments>http://m.tkk7.com/qileilove/archive/2014/03/13/410968.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qileilove/comments/commentRss/410968.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qileilove/services/trackbacks/410968.html</trackback:ping><description><![CDATA[<div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  q是我在从事|站<a target="_self" style="word-break: break-all; color: #202859; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">自动化测?/strong></u></a>?a target="_self" style="word-break: break-all; color: #202859; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">工作</strong></u></a>当中构徏出的一?#8220;生态系l?#8221;?#8220;生态系l?#8221;q个概念是我从公司的前辈w上学到的,他一直以来都认ؓ(f)自动化测试h员不应仅仅局限于~写试代码Q还应该让整个自动化试的过E(试代码的持l集成、分发、执行等Q都自动化,形成一?#8220;pȝ”Q这个系l的自动化程度越高,自动化测试h员就省力?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  <strong style="word-break: break-all; line-height: normal !important;">一、概?/strong></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  q里我画了一张示意图Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350321E3JG.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  之所以称之ؓ(f)“生态系l?#8221;Q是因ؓ(f)建成之后需要的Zؓ(f)q涉很少Q其余的旉都是pȝ内部循环q作。作动化试人员的你只需要提交代码,之后便可以在AutomationDashboard上看到运行的l果了,其余的事情都ql内部消化。当Ӟl果的分析还是需要h来完成,机器q没有聪明到可以灉|分析出各U各栯case fail掉的原因?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  我们可以把整个系l看作一个黑盒子Q那么上面的囑֏以变成:(x)</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350322xbVu.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  实际上这里画的h不仅限于自动化测试h员,也可以是Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  Q?Q品的理者,比如产品l理需要从自动化回归测试知道这ơrelease有无推迟风险Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  Q?Q团队的理者,比如开发经理、QAl理需要从自动化的daily/weekly regression知道最q的代码质量如何Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  Q?Q开发h员,他们也许?x)想通过quick regressionQ提交的产品代码被部|到试环境之后q行的测试)知道自己刚提交的代码有没有破坏系l的基本功能Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;">  Q?Q其他帮忙做自动化测试的开发h员、刚刚开?a target="_self" style="word-break: break-all; color: #202859; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">学习(fn)</strong></u></a>~写自动化测试代码的手动试人员Q他们不必关心生态系l的内部实现?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 11.818181991577148px; background-color: #ffffff;"><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;"> <strong style="word-break: break-all;"> 二、实?/strong></div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  说完概念Q接下来该说说具体实C。我q里讲的是我认ؓ(f)最适合我所试的品的实现Q工具不止一U,方式不止一U。Jenkins可以用TeamCity或其它CI替换Qgit也可以是svn或tfsQAutomationDahsboard可以?NET、SpringMVC、ROR{等实现Q运行测试的slave可以是Windows/Linux/MacQ土豪!Q,M选择一U最适合你所试的品的实现。还有一点就是自动化试代码是用关键字驱动思想实现的,q是另外一个话题了Q有旉另外写篇文?/div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  <strong style="word-break: break-all;">好,q入正题。依ơ说说系l的每个重要l成部分吧:(x)</strong></div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  1、SCMQSource Code ManagementQ。我选的是gitQ可以是git服务器(公司自己搭徏了一个git <a target="_self" style="word-break: break-all; color: #202859;"><u style="word-break: break-all;"><strong style="word-break: break-all;">server</strong></u></a>Q,也可以是一个bare repoQhttp://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/Q??/div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  2、CIQcontinuous integrationQ。我选的是部|方ѝ插件丰富的Jenkins?/div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  <strong style="word-break: break-all;">它的职责是:(x)</strong></div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  Q?Q从git上取Z码,buildQ?NET对应msbuildQ如果是ruby则不用build了,直接部v卛_Q;</div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  Q?Q把build好的*.dll部vQ这里即是拷贝)到所有的slave上;</div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">  Q?Q启动或停止所有slave上的AutomationServiceQ后面还?x)讲到AutomationServiceQ,从而控制测试的执行?span style="font-size: 11.818181991577148px; line-height: 21.60000228881836px;">我在Jenkins的这些个job配置hq是比较J琐的,要细讲又可以另外写一文了。这里就特别提到两个很实用的插g吧:(x)</span></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  Q?QParameterized Trigger PluginQhttps://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+PluginQ:(x)可以在一个build step中触发其它project的build?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350323MpQL.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  它最有用的就是这?#8220;Block until the triggered projects finish their builds”选项Q勾上的话Jenkinsp在所有trigger的project完成build之后Q而非仅仅trigger其它project的buildQ不{它们完成就l箋下一个build stepQ再l箋下一个build stepQ做到真正的依次执行每个build step?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350324cdMj.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  Q?QNodeLabel Parameter PluginQhttps://wiki.jenkins-ci.org/display/JENKINS/NodeLabel+Parameter+PluginQ:(x)在所?#8220;Possible nodes”标有指定标签Q?#8220;Label”Q的Jenkins节点Q就是Jenkins master或Jenkins slaveQ上触发指定projectQ被触发的project是参数化的)?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  比如我有一个project?#8220;StartClassicROLATServiceOnAllNodes”Q它有一个build step是这栯定的Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350325p0dk.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  再来看看“StartClassicROLATServiceOnASingleNode”q个project的设定:(x)</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_2014031013503261mEf.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  q个project有一个Nodecd的参敎ͼ参数?#8220;NodeX”与之前Label Factory中的“NodeX”对应Q?#8220;Possible nodes”选的?#8220;ALL”Q那么列出的所有nodeQmaster?0.107.122.152?0.107.122.153?0.107.122.154Q都在判断范围之内(判断其是否有“Node”标签Q有则执行projectQ?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  另外Q列出的所有node我都为其加了一?#8220;Node”标签?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350327qC46.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  q样Q当我trigger “StartClassicROLATServiceOnAllNodes”之后Q就?x)在master?0.107.122.152?0.107.122.153?0.107.122.154q?个node上同时执?#8220;StartClassicROLATServiceOnASingleNode”?br /><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><strong style="word-break: break-all; line-height: normal !important;"> 3、AutomationDashboardQ这里姑且译?#8220;自动化测试控刉?#8221;吧?/strong>实际上它应该和Jenkins一起ƈU控刉板,不过因ؓ(f)Jenkins有API可以调用Q所以想做的M者也是可以统一成一个web界面的。这个dashboard完全是用.NET+IIS+SQLServer一点点从数据库设计构徏、数据访问层、业务层、表现层做v来的Q要l讲……?#8230;…又会(x)是另外一文了(Oh man, not again!Q。反正我觉得Q虽然我是做自动化测试工作的Q但不应该把自己局限于试。ؓ(f)了更好地q行自动化测试,开发网站、安装配|虚拟机以及其它要用到的工具Q都应该抽时间去学习(fn)、掌握?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  好,来说说这个dashboard。这里只讲两个主要组成部分,一个网站(以下UdashboardQ、一个Windows ServiceQ以下简UATServiceQ和一个console applicationQ以下称ConsoleRunnerQ:(x)</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  <strong style="word-break: break-all; line-height: normal !important;">Q?QdashboardQ它的主要功能:(x)</strong></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  a、展C测试的q行状况Q有多少正在q行/执行完毕Q分别在哪台slave上执行等{?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  b、通过call Jenkins的API来trigger Jenkins的jobQ间接控制测试的执行?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  c、展C测试的l果Q发生错误的是哪个case、出错时间、错误信息、代码回溯(stack traceQ、甚臛_以包含一张出错时的截图?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  主要界面如下Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  a、SummaryQ顾名思义是汇M息,case有多pass多少fail、case按分cL一cL多少{等。(其实q里我少做了一张很重要的图Q就是coverage饼状图)</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_20140310135032827KJ.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  b、QueueQ测试队列,包含当前正在q行的、运行完的、等待运行的test fixture或test caseQ依据测试工L(fng)不同QNUnit、JUnit、RSpec{,fixture的叫法可能不同,M是包含多个test case的集合)。可以启动、停止、终止(l止之后可以清空Q测试执行或清空当前队列?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350329deYC.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  c、TestCaseQ生态系l中的所有测试用例会(x)展示在这里,可以看到它们最后一ơ执行的旉和状态(pass/failQ,点击某条case可以跌{到该条case的所有test result。可以按状态(pass/fail/otherQ筛选用例,可以N部分用例重新执行、或重新执行所有fail的case?#8220;Reload Test Cases”主要是考虑?.dll文g中的test case可能?x)在某次部v之后发生变化Q需要重新加载。不q后来我修改了Jenkins里的job在每ơ部|之后都自动重新加蝲Q所以这个按钮其实没什么用了?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_201403101350321010y4.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  d、TestSuiteQ包含多个fixture的集合是一个suite。勾选多个suite点击“Run Suite”卛_把这些suite中包含的fixtured到Queue?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_20140310135032111vpi.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  q里的suite是对NUnit中的Category的一个补充,点击“New Suite”你可以Q意选择fixture来组成自己想要的suiteQ?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_2014031013503212Z8mE.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  e、TestResultQ展C所有test case的运行结果,可以按test case idq行{选,点击TC#q一列的id只昄q条case的结果?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_20140310135032132kv4.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /></a></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">  点右边的蓝色“i”图标可以跛_q条l果的详l页面,截图功能暂未启用Q根据RunnerMessage和RunnerStackTrace可以知道报错的代码位|,q而尝试重现问题?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><img src="http://www.51testing.com/attachments/2014/03/14982672_2014031013503214aCLS.jpg" border="0" style="word-break: break-all; list-style: none outside none; margin: 0px; padding: 0px; border: none; max-width: 500px;" alt="" /><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;"> Q?QATService。这个Windows ServiceQslave都是WindowsQ稍后会(x)Ԍ被安装到了每个slave上,用以向dashboard询问“现在有没有分配给我的test fixture/caseQ?#8221;Q如果有且当前slaveI闲的话抓q来q行Q运行完毕汇报结果?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  q记得QueueQ队列)吧?无论你在TestCaseq是TestSuite面挑选了test case/suite惌q行Q都只是把它们添加到队列当中Q准地说就是往Queueq张数据库表中INSERT记录Q,而不?x)给它们分配slave。只有当Jenkins启动了slave上的ATService之后QATService才会(x)去Queue表中自己抓取Q就是打上标记说q条fixture/case已经有主了,其它slave׃?x)再LQ还没有q行q且没有分配有slave的test fixture/case?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  Q?QConsoleRunnerQ最开始的那个图中没有d来。这个consoleE序主要供Jenkins调用。Jenkins不是可以让job定时q行么?正好Q定时调用这个console applicationQ传几个参数Q就可以在指定时间往Queue里填充f(xi)ixture/caseQ然后再启动ATService开始执行测试。这样就能实现quick/daily/weekly/full regression的无人值守q行了?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;"> <strong style="word-break: break-all; line-height: normal !important;"> 4、Slave</strong></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  我选择在Windows上运行测试:(x)</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  Q?Q公司IT一般只提供Windows操作pȝ的虚拟机</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  Q?Q品在Windows上的用户占绝大多敎ͼ其实q个有点废话Q桌面操作系lWindows依然是世界王者。诚Ӟ我自׃余时用Linux做开发,Mac在国内外也是相当行的,但GoogleAnalytics昄的统计结果就是大部分讉K都来自Windows。什么,你说iOS/AndroidQ额……Ud端现在仍然是产品的短?#8230;…Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  如果选择Linux的话要注意下selenium webdriver的native event讑֮Qhttp://code.google.com/p/selenium/wiki/AdvancedUserInteractions#Native_events_versus_synthetic_eventsQ?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  关于览器,Firefox、Chrome、IE皆可Qwebdriver的浏览器兼容性已l很不错了。浏览器兼容性是个有点头疼的问题Q想支持很多览器的话有时会(x)增加很多开发、测试成本,我一般在Firefox上跑p够了。什么?数字Q马Ӟ企鹅Q?zhn)惛_了,selenium官方不支持?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  你能扑ֈ多少台slave来执行测试?多多益善哦!找不到那么多实体机就自己配虚拟机吧,分布式运行可以给你的自动化测试生态系l装上火!在更短的旉内运行完更多试Q从而更快地从测试中获得反馈Q?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  嗯,差不多就q么多了。还有很多细节就留在之后的文中再说了。自我感觉这个生态系l还是有很多可以完善、增加的功能Q而且q个实现方式、运作机制可能也q适用于你所试的品,不过现在对于我测的品来说是够用的了?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  不管怎样实现Q我惌辄核心观点是:(x)</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  做自动化试不要局限于自动化测试代码的~写Q我们要自动化的不仅仅是manual test caseQ还应包括整个automation test的processQ测试代码持l集成、部|Ԍ分发Q、执行、结果展C,自动化的环节多、越dQؓ(f)你节U的旉p多,你可以用q些节约的时间做更有意义的事情。hcd明计机Q用代码~写E序Q其实就是一U自动化的过E。以前要靠手工劳动完成的现在都交l电(sh)脑做?#8212;—服务器不正是勤勤x地重复执行着我们写好的程序么Q构动化试生态系l是同样的道理,因ؓ(f)机器能比人更可靠地完成重复劳动?/div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">  如果你还在手动拷?.dllQ还需要打开NUnit手动执行试Q还?台机器上q行试Q那么,现在是该提高生产力的时候了Q?/div></a></div></div></div><img src ="http://m.tkk7.com/qileilove/aggbug/410968.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qileilove/" target="_blank">其自然EVO</a> 2014-03-13 11:34 <a href="http://m.tkk7.com/qileilove/archive/2014/03/13/410968.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>操作pȝ中内存管理的面|换法http://m.tkk7.com/qileilove/archive/2013/11/01/405876.html其自然EVO其自然EVOFri, 01 Nov 2013 02:37:00 GMThttp://m.tkk7.com/qileilove/archive/2013/11/01/405876.htmlhttp://m.tkk7.com/qileilove/comments/405876.htmlhttp://m.tkk7.com/qileilove/archive/2013/11/01/405876.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/405876.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/405876.html  考虑下述面走向Q?/strong>
  1Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?Q?
  当内存块数量分别?Ӟ试问FIFO、LRU、OPTq三U置换算法的~页ơ数各是多少?
  {:(x)~页定义为所有内存块最初都是空的,所以第一ơ用到的面都生一ơ缺c?/div>
  当内存块数量?Ӟ(x)
  发生~页中断的次Cؓ(f)16?/div>
  在FIFO法中,先进入内存的面被先换出。当?要调入时Q内存的状态ؓ(f)4??Q考查?之前调入的页面,分别????Q可?为最先进入内存的Q本ơ应换出Q然后把?调入内存?/div>
  发生~页中断的次Cؓ(f)15?/div>
  在LRU法中,最q最用的面被先换出。当?要调入时Q内存的状态ؓ(f)5??Q考查?之前调入的页面,分别???Q可?为最q一D|间内使用最的Q本ơ应换出Q然后把?调入内存?/div>
  发生~页中断的次Cؓ(f)11?/div>
  在OPT法中,在最q的来才被讉K的页面被先换出。当?要调入时Q内存的状态ؓ(f)1??Q考查?后面要调入的面Q分别ؓ(f)2???#8230;Q可?为最q一D|间内使用最的Q本ơ应换出Q然后把?调入内存?/div>
  OPT法因ؓ(f)要知道后面请求的|Q因此我觉得q个法有个小的bug,如果在某个请求中Q若在该h的页框之后的|序列中至存在一个和当前内存块中不匹配的|Q则按照内存块的序Q从上往下)替换没有出现的页框。比如上面那个OPT例子。对于最后一个页框请求,因ؓ(f)6未命中,?之后没有h的序列,因此应该替换3Q所以替换后的序列ؓ(f)6 Q?2 Q?   当然Q这只是针对做题而言?/div>

其自然EVO 2013-11-01 10:37 发表评论
]]>目实战W记之六Q团队徏讄三种境界http://m.tkk7.com/qileilove/archive/2013/06/04/400153.html其自然EVO其自然EVOTue, 04 Jun 2013 02:32:00 GMThttp://m.tkk7.com/qileilove/archive/2013/06/04/400153.htmlhttp://m.tkk7.com/qileilove/comments/400153.htmlhttp://m.tkk7.com/qileilove/archive/2013/06/04/400153.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/400153.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/400153.html l过自己ȝ和项目经理们探讨Q认为项目或部门团队可分Z个等U:(x)

  一、乌合之众,强权政治Q新手)

  很多新手都会(x)l历q样的过E,新组建的团队冲突不断Q大家对当各U制度措施,报以反感。ؓ(f)保证执行力和目成功Q项目经理会(x)选择强权压制Q尤其是技术比较好的项目经理。大늚逻辑?#8220;我是老大q且我资深,要听我的”。最l的l果是大家对目目标已经完全不感兴趣Q一些冲H升U到个h情感冲突Q项目经理左右突击,上蹿下蟩Q甚是辛苦,忙碌Q确得不到大家的认可?/p>

  此时的项目经理至需要做C点,才有可能q入下个阶段Q用杰克韦尔奇的两句话概况:(x)

  1?#8220;在你成ؓ(f)领导以前Q成功只同自q成长有关。当你成为领g后,成功都同别h的成长有兟?#8221;

  2?#8220;世界上的每一个h都想得到发言权和严Q而且也应当得?#8221;

  所?#8220;发言?#8221;Q是指h们希望有Z(x)说出他们的思想Q拥有自q观点、看法、获得被們֐的感受,无论他们的国c、性别、年龄或者文化背景如何?/p>

  所?#8220;严”Q是指h们本能地和自发地希望׃自己?a href="" target="_self" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;">工作、努力和个性而得到尊重?/p>

  q个阶段之所以命名ؓ(f)乌合之众Q是因ؓ(f)大家对团队根本没有归属感Q甚臛_弃团队,期望团队得到解散Q或者团队目标达成时Qƈ没有取得成就的感觉,而是有终于熬q来的感触?/p>

  二、尊重,民主C会(x) Q老手Q?/strong>

  在经历过挫折或是老前辈们的谆谆教导后Q新手往往都能q入q个阶段。当然有些厉害的人有时也?x)自p到这个阶Dc但是这个阶D里的hQ也有高下之分。在q个阶段的hQ往往可以带团队时Q往往可以做到Q?/p>

  1、尊重,a路开?/p>

  不把人当做机器。制定计划,措施Ӟ都可以征求的大家意见Q当然计划定下来后,执行时是不能含糊的?/p>

  2、善用h才,培养人才

  团队里有人才Ӟ?x)用授权等方式调用q些人的U极性,而不是幼E的打压Qƈ且在团队里没有h才时Q能够积极选拔备选h员,q给予锻炼机?/p>

  3、分享荣?/p>

  q个阶段的项目经理,在交中Q会(x)摈弃?#8220;我怎么P怎么?#8221;Q多使用“我们Q我们团队怎么?#8221;Q尤其是在面对表扬和荣誉时。在目l内也想方设法树(wi)立榜Pq且非常愿意q些自己的上U所L(fng)Q愿意ؓ(f)q些个好前程?/p>

  4、坦?/p>

  坦诚是相处的长远之计Q而忽(zhn),dD些手D只能短期效应,q在长期上让自己的h格受损。关于这炚w目经理大多做得程度不一Q有时说Z些不开心的事,是需要勇气的Q例如在l效沟通时。但是这个阶D늚目l理都了解它重要性?/p>

  5、团队信息透明

  只有信息_透明Q大家才能够为项目出谋划{,才能有坦诚沟通的基础Q大家才能对目归属?#8220;垄断信息Q以昄自己领导的地?#8221;是愚蠢的人才?x)干的事?/p>

  q个阶段之所以命名ؓ(f)民主C会(x)Q这个阶D늚价D是:(x)民主计划Q严格执行,有付出有回报Q集体荣誉。第一个阶D到W二个阶D可能需要时间的U篏Q而第二个阶段到第三个阶段Q有时却可望而不可达?/p>

  三、激情,燃烧军团 Q高手)

  Ȁ情团队的充分必要前提是,团队负责人是非常有激情的。这点很关键Q一个打工者心态,没有把工作当成自׃业经营的人是不会(x)带出有长久激情的团队。检视的原理Q?#8220;看一下大家是不是Z同一个梦惌走CL(fng)”

  要达成团队激情,臛_具备以下几点Q?/p>

  1、老板风格Q老板要有分n成功的决心,例如Q股,期权Ȁ?/p>

  2、企业文化,企业要有文化宣扬集体奋斗的精,企业的命h(hun)D能够深入人心Q得到强烈响应,此时企业的创新精,是从内而外的,从下而上的,大家集体思考,集体q步Q集体创新?/p>

  3、有Ȁ情的中层Q公怸层是企业的中砥柱,如果每个中层是有Ȁ情的Q扩散开来的影响力是很大的,反之Q则Ȁ情容易变成口受?/p>

  q里典型的案例是sony的没落,从井深大的激情军团的消失Q井深大倡导”工作保证本n是一U强有力的激?#8220;Q把q种理念能够深植公司是多么可怕,Ȁ情可以创造出很多奇迹?/p>

  U翰·U特说过“如果你想建造一艘船Q首先要做的不是去采集木材、加工木板和分派工作Q而应该去唤vZ对广阔无垠大L(fng)向往?#8220; 理者的本质是获得追随的人,一个企业,一个团队如果能够拥有一Ҏ(gu)意追随公司成长的人,所产生的正向能量是无比巨大的?/p>

  q种境界的达到需要多方因素的促合Q颇g武侠里的天h合一Q激情团队的理十分简单,保护q种Ȁ情,员工?x)很自主的进行自我管理?/p>

  当然实际工作中,以上每个阶段不孤立存在,可能?x)存在一些阶D늚中间体?/p>

相关链接Q?/p>

目实战W记之一Q高效会(x)议的l织Ҏ(gu)

目实战W记之二Q风险管?/a>

目实战W记之三Q时间估的三步?/a>

目实战W记之四Q团队徏设(重Q?/a>

目实战W记之五Q里E碑理



其自然EVO 2013-06-04 10:32 发表评论
]]>
跟屌丝大哥学?fn)设计模式-抽象工厂模?/title><link>http://m.tkk7.com/qileilove/archive/2012/12/21/393318.html</link><dc:creator>其自然EVO</dc:creator><author>其自然EVO</author><pubDate>Fri, 21 Dec 2012 08:26:00 GMT</pubDate><guid>http://m.tkk7.com/qileilove/archive/2012/12/21/393318.html</guid><wfw:comment>http://m.tkk7.com/qileilove/comments/393318.html</wfw:comment><comments>http://m.tkk7.com/qileilove/archive/2012/12/21/393318.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qileilove/comments/commentRss/393318.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qileilove/services/trackbacks/393318.html</trackback:ping><description><![CDATA[<div><strong>1.3 抽象工厂QAbstract FactoryQ模?br /></strong>    抽象工厂模式可以向客L(fng)提供一个接口,使得客户端在不必指定产品具体cd的情况下Q创建多个品族中的产品对象。这是抽象工厂模式的用意?br />    每个模式都是针对一定问题的解决Ҏ(gu)。抽象工厂模式面对的问题是多产品{l构的系l设计?br />    在学?fn)抽象工厂具体实例之前,应该明白两个重要的概念?x)产品族和产品{?br />    产品族:(x)是指位于不同产品{l构中,功能相关联的产品l成的家族。比如AMD的CPU和ADM芯片的主板,l成一个家族。Intel的CPU?Intel芯片的主板,又组成一个家族。而这两个家族都来自于两个产品{QCPUQ主ѝ一个等U结构是q同的l构的品组成,C意囑֦下:(x)</div><img alt="" src="http://m.tkk7.com/images/blogjava_net/qileilove/aaa1165334942718.png" height="332" width="508" /><br /><br /><br /><div><br />    理解q个产品l构是理解抽象工厂模式的关键所在,所以我不惜p旉来画此图。如果领(zhn)不到此囄含义Q就无法区分工厂Ҏ(gu)模式和抽象工厂模式的区别?br />    从上囑֏以看出,抽象工厂模式的每个工厂创造出来的都是一族品,而不是一个或者一l。组是可以随意组合的Q其实两个就q点点差别,呵呵Q估计现在你已经差不多明白了抽象工厂模式的含义。不废话了,看个例子Q真相将大白于天下!<br /> <div><strong>1.3.1 抽象工厂模式在农Z的实?/strong></div> <div><br /><strong>1.3.1.1 背景</strong></div> <div><br />    聪明的农ZL让自q庄园来有价|“农场”在经历了单工厂模式和工厂模式后,不断的扩大生产。如今,再次面(f)新的大发展,一w要的工作是 引进塑料大棚技术,在大里U植热带QTropicalQ和亚热带(NorthernQ的水果和蔬菜,用以满市场需求,获取更大的利益?/div> <div><br /><strong>1.3.1.2 产品角色?/strong></div> <div><br />    l过分析Q对产品角色q行分析得出下图</div></div><img alt="" src="http://m.tkk7.com/images/blogjava_net/qileilove/abb1165335033921.png" height="231" width="428" /><br /><br /><div>    l过分析Q所谓的各个园丁其实是工厂角色Q而蔬菜和水果则是产品角色。将抽象工厂模式用于农场中,pȝ设计囑֦下:(x)<br /><br /><img alt="" src="http://m.tkk7.com/images/blogjava_net/qileilove/caa1165384624477.png" height="421" width="632" /><br /><br /><div>1.3.1.4.1 抽象工厂QGardener.java <div>package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:Gardener.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:55:23<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  抽象工厂角色Q工厂接?br /> */<br />public interface Gardener {</div> <div>    public Fruit createFruit(String name);</div> <div>1.3.1.4.2 抽象水果产品QFruit.java</div> <div>package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:Fruit.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:54:15<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  抽象产品角色Q水果接?br /> */<br />public interface Fruit {<br />}</div> <div>1.3.1.4.3 抽象蔬菜产品QVeggie.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:Veggie.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:56:22<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  抽象产品角色Q蔬菜接?br /> */<br />public interface Veggie {<br />}</div> <div>1.3.1.4.4 热带水果QTropicalFruit.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:TropicalFruit.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:57:08<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  具体产品角色Q热带水?br /> */<br />public class TropicalFruit implements Fruit {<br />    private String name;</div> <div>}</div> <div>1.3.1.4.5 热带蔬菜QTropicalVeggie.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:TropicalVeggie.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:58:03<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  具体产品角色Q热带蔬?br /> */<br />public class TropicalVeggie implements Veggie {<br />    private String name;</div> <div>    public TropicalVeggie(String name) {<br />        System.out.println("热带工厂为?zhn)创徏了?x)热带水果Q?+name);<br />    }</div> <div>}</div> <div>1.3.1.4.6 亚热带水果:(x)NorthernFruit.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:NorthernFruit.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:58:55<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  具体产品角色Q亚热带水果<br /> */<br />public class NorthernFruit implements Fruit {<br />    private String name;</div> <div>    public NorthernFruit(String name) {<br />        System.out.println("亚热带工厂ؓ(f)(zhn)创ZQ亚热带水果Q?+name);<br />    }</div> <div>}</div> <div><br />1.3.1.4.7 亚热带蔬菜:(x)NorthernVeggie.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:NorthernVeggie.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    22:59:36<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  具体产品角色Q亚热带蔬菜<br /> */<br />public class NorthernVeggie implements Veggie {<br />    private String name;</div> <div>    public NorthernVeggie(String name) {<br />        System.out.println("亚热带工厂ؓ(f)(zhn)创ZQ亚热带蔬菜Q?+name);<br />    }</div> <div>}</div> <div>1.3.1.4.8 热带工厂QTropicalGardener.java<br />/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:TropicalGardener.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    23:01:49<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  具体工厂角色Q热带工?br /> */<br />public class TropicalGardener implements Gardener {<br />    public Fruit createFruit(String name) {<br />        return new TropicalFruit(name);<br />    }</div> <div>    public Veggie createVeggie(String name) {<br />        return new TropicalVeggie(name);<br />    }<br />}</div> <div>1.3.1.4.9 亚热带工厂:(x)NorthernGardener.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:NorthernGardener.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    23:00:31<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  具体工厂角色Q亚热带工厂<br /> */<br />public class NorthernGardener implements Gardener {<br />    public Fruit createFruit(String name) {<br />        return new NorthernFruit(name);<br />    }</div> <div>    public Veggie createVeggie(String name) {<br />        return new NorthernVeggie(name);<br />    }<br />}</div> <div></div> <div>1.3.1.4.10 试c(客户端)QTestApp.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div> <div>/**<br /> * Created by IntelliJ IDEA.<br /> * FileName:TestApp.java<br /> * User:    LavaSoft<br /> * Date:    2006-12-5<br /> * Time:    23:03:22<br /> * 《Java与模式》(--阎宏博士著)MW记<br /> * 工厂模式--抽象工厂模式--一般性模式(农场应用Q?br /> * ReadMe:  试c(客户端)<br /> */<br />public class TestApp {<br />    private void test(){<br />        Veggie tv,nv;<br />        Fruit tf,nf;<br />        TropicalGardener tg=new TropicalGardener();<br />        NorthernGardener ng=new NorthernGardener();</div> <div>        tv=tg.createVeggie("热带菜叶");<br />        nv=ng.createVeggie("东北甜菜");<br />        tf=tg.createFruit("南椰子");<br />        nf=ng.createFruit("雪梨");<br />    }<br />    public static void main(String args[]){<br />        TestApp test=new TestApp();<br />        test.test();<br />    }<br />}</div> <div>1.3.1.4.11 试q行l果<br />    热带工厂为?zhn)创徏了?x)热带水果Q热带菜?br />    亚热带工厂ؓ(f)(zhn)创ZQ亚热带蔬菜Q东北甜?br />    热带工厂为?zhn)创徏了?x)热带水果Qv南椰?br />    亚热带工厂ؓ(f)(zhn)创ZQ亚热带水果Q雪?/div> <div>    Process finished with exit code 0<br />    看完设计囑֒源码Q原理已l很清楚了,q个模式应用很灵z,猴交l你了,看你怎么玩它Q哈哈哈哈。。。?/div> <div><strong>1.3.1.5 奛_丄造万?br /></strong>    奛_丄造物的故事很适合在这里D例子Q女娲的l_按照阴阳划分Q品则按h、兽划分。将抽象工厂模式用于奛_造万物的模拟pȝ设计中。系l设计图如下Q?/div> </div></div><img alt="" src="http://m.tkk7.com/images/blogjava_net/qileilove/d1165335259515.png" height="531" width="685" /><img src ="http://m.tkk7.com/qileilove/aggbug/393318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qileilove/" target="_blank">其自然EVO</a> 2012-12-21 16:26 <a href="http://m.tkk7.com/qileilove/archive/2012/12/21/393318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学?fn)设计模?-工厂Ҏ(gu)模式http://m.tkk7.com/qileilove/archive/2012/12/19/393215.html其自然EVO其自然EVOWed, 19 Dec 2012 08:25:00 GMThttp://m.tkk7.com/qileilove/archive/2012/12/19/393215.htmlhttp://m.tkk7.com/qileilove/comments/393215.htmlhttp://m.tkk7.com/qileilove/archive/2012/12/19/393215.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/393215.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/393215.html阅读全文

其自然EVO 2012-12-19 16:25 发表评论
]]>
跟屌丝大哥学?fn)设计模?--生成器模?Builder)解析例子 http://m.tkk7.com/qileilove/archive/2012/12/18/393166.html其自然EVO其自然EVOTue, 18 Dec 2012 09:16:00 GMThttp://m.tkk7.com/qileilove/archive/2012/12/18/393166.htmlhttp://m.tkk7.com/qileilove/comments/393166.htmlhttp://m.tkk7.com/qileilove/archive/2012/12/18/393166.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/393166.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/393166.html
生成器模式属于对象结构型模式Q其意图是将一个复杂对象的构徏与他的表C分,使得同样的构建创E可以创Z同的表示?/span>
适用性:(x)
1.         当创建复杂对象的法应该独立于该对象的组成部分以及他们的装配方式?/span>
2.         当构造过E必d许被构造的对象有不同的表示时?/span>
 
参与?/span>:
       生成?/span>Builder:为创Z?/span>Product对象的各个部件指定抽象接?/span>(AnimalBuilder)?/span>
       具体生成?/span>ConcreteBuilder:实现Builder接口一构造和装配该品的各个部g?/span>
                     定义q明他所创徏的表C,
                     提供一个检索品的接口(getAnimal)?/span>
导向器:(x)构徏一个适用Builder对象的接口?/span>
ProductQ?/span>Checken,pigQ?/span>:表示被构造的复杂对象?/span>ConcreteBuilder创徏该品的内部表示q定义它的装配过E,包含定义l成部g的类Q包括将q些部g装配成最l的产品?img alt="" src="http://img1.51cto.com/attachment/200707/200707141184406082109.gif" border="0" />
?
当客户需要一个品时Q把需要的参数传递个导向器,导向器根据传递的参数调用具体的生成器Q具体的生成器通过一pd的操?/span>(getAnimal()通过调用其它的接口方法实?/span>)最?x)返回一个品?/span>
Bridge模式的优点:(x)
1.         它你可以改变一个品的内部表示Q?/span>Builder对象提供l导向器一个构造品的抽象接口Q该接口使得生成器可以隐藏这个品的表示和内部结构,他同时也隐藏了该产品是如何装配的Q因Z品时通过抽象接口构造的(注:(x)本例子把接口的实现放在具体类中了)Q你在改变该产品的内部表C时所要做的只是定义一个新的生成器?/span>
2.         他将构造代码和表示代码分开Q这有点cM于模板模式。所不同的是模版模式最l是完成复杂的工作,而生成器的目的是要生成一个复杂的对象?/span>
3.         他得你Ҏ(gu)造过E进行更加精l的控制?/span>Builder模式是在导向者的控制下一步一步构造品的Q仅当该产品完成Ӟ导向者才从生成器中取回品。因?/span>Builder模式能更好的反映产品的构造过E,使你可以更精l的控制构徏q程Q从而能更精l的控制所的品的内部l构?/span>
代码CZ:
AnimalBuilderQ代?/span>
package builder;
public interface AnimalBuilder{
    public void buildName();
    public void buildLegs();
    public void buildMeat();
    public Animal getAnimal();
}
ChickenBuilder?/span>代码Q?/span>
package builder;
public class ChickenBuilder implements AnimalBuilder{
    private Animal chicken = null;
    public ChickenBuilder(){
       chicken = new Animal();
    }
    public void buildName(){
       chicken.setName("chicken");
    }
    public void buildLegs(){
       chicken.setLegs(2);
    }
    public void buildMeat(){
       chicken.setMeat("chicken");
    }
    public Animal getAnimal(){
       buildName();
       buildLegs();
       buildMeat();
       return chicken;
    }
}
Animal代码Q?/span>
package builder;
public class Animal{
    private String name;
    private String meat;
    private int legs;
    public String getName(){
       return name;
    }
    public String getMeat(){
       return meat;
    }
    public int getLegs(){
       return legs;
    }
    public void setName(String aName){
       name = aName;
    }
    public void setMeat(String aMeat){
       meat = aMeat;
    }
    public void setLegs(int alegs){
       legs = alegs;
    }
}
Director代码Q?/span>
package builder;
public class Director{
    public Animal getAnimal(String aName){
       if(aName.equals("chicken")){
           return new ChickenBuilder().getAnimal();
       }
       else if(aName.equals("pig")){
           return new PigBuilder().getAnimal();
       }
       else return null;
    }
}
 
客户端代码:(x)
package builder;
public class Client{
    public static void description(Animal animal){
       String desc = "This animal is called "+animal.getName();
       desc +="\n Its meat is "+animal.getMeat();
       desc +="\n And it has "+animal.getLegs()+" legs.";
       System.out.println(desc);
    }
    public static void main(String[] args){
       String aName = "chicken";
       Director d = new Director();
       Animal animal =d.getAnimal(aName);
       description(animal);
       aName = "pig";
       animal = d.getAnimal(aName);
       description(animal);
    }
}
l论Q生成器模式使得客户可以更加_的控制一个对象的构徏Q每个具体的创徏者包含了创徏和装配一个特定品的所有代码,q些代码只用写一ơ,便可以被不同?/span>Director使用Q从而可以装配出不同的对象?/span>
 


其自然EVO 2012-12-18 17:16 发表评论
]]>跟屌丝大哥学?fn)设计模?--代理模式之动态代?/title><link>http://m.tkk7.com/qileilove/archive/2012/12/13/392932.html</link><dc:creator>其自然EVO</dc:creator><author>其自然EVO</author><pubDate>Thu, 13 Dec 2012 03:53:00 GMT</pubDate><guid>http://m.tkk7.com/qileilove/archive/2012/12/13/392932.html</guid><wfw:comment>http://m.tkk7.com/qileilove/comments/392932.html</wfw:comment><comments>http://m.tkk7.com/qileilove/archive/2012/12/13/392932.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qileilove/comments/commentRss/392932.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qileilove/services/trackbacks/392932.html</trackback:ping><description><![CDATA[<div><p>动态代?/p> <p>java中动态代理机制的引入使得代理模式的思想更加完善与进步,它允许动态的创徏代理q支持对动态的Ҏ(gu)代理的方法进行调用。Java动态代理类位于Java.lang.reflect包下Q一般主要涉及到以下两个c:(x) </p> <p><span>(1). Interface InvocationHandler</span>Q该接口中仅定义了一个方法ObjectQ?span>invoke(Object obj,Method method, Object[] args)</span>。在实际使用ӞW一个参数obj一般是指代理类Qmethod是被代理的方法,如上例中的request()QargsҎ(gu)的参数数l。这个抽象方法在代理cM动态实现?nbsp;</p> <p>(2).ProxyQ该cd为动态代理类Q作用类g上例中的ProxySubjectQ其中主要包含以下内容:(x) </p> <p><span>Protected Proxy(InvocationHandler h)</span>Q构造函敎ͼ估计用于l内部的h赋倹{?nbsp;</p> <p><span>Static Class getProxyClass (ClassLoader loader, Class[] interfaces)</span>Q获得一个代理类Q其中loader是类装蝲器,interfaces是真实类所拥有的全部接口的数组?nbsp;</p> <p><span>Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)</span>Q返回代理类的一个实例,q回后的代理cd以当作被代理cM?可用被代理cȝ在Subject接口中声明过的方??nbsp;</p> <p> </p> <p>所谓Dynamic Proxy是这样一UclassQ它是在q行时生成的classQ在生成它时你必L供一linterfacel它Q然后该class宣U它实现了这些interface。你当然可以把该class的实例当作这些interface中的M一个来用。当然啦Q这个Dynamic Proxy其实是一个ProxyQ它不会(x)替你作实质性的工作Q在生成它的实例时你必须提供一个handlerQ由它接实际的工作?下面我们通过动态代理来重新实现上面发送信息的例子Q?/p> <p><br /></p> <p> <img src="http://hi.csdn.net/attachment/201006/15/0_1276561533dOxg.gif" alt="" /></p> <p>在上面的例子基础上,我们先添加一个通过短信来发送消息的处理c:(x)</p></div><div>public class SmsMessage implements MessageHandler {<br />@Override<br />public void sendMessage(String msg) {<br />// TODO Auto-generated method stub<br />System.out.println("SMS Message :" + msg+" sent !");<br />}<br />}<br />//动态代理类<br />import java.lang.reflect.InvocationHandler;<br />import java.lang.reflect.Method;<br />public class DynamicMessageProxy implements InvocationHandler {<br />private static int count;<br />private MessageHandler msgHandler;<br />public DynamicMessageProxy(MessageHandler handler) {<br />msgHandler = handler;<br />}<br />@Override<br />public Object invoke(Object proxy, Method method, Object[] args)<br />throws Throwable {<br />// TODO Auto-generated method stub<br />System.out.println("++++++++=============+++++++++");<br />System.out.println("proxy:" + proxy.getClass());<br />System.out.println("method:" + method);<br />System.out.println("++++++++=============+++++++++");<br />if (args != null && args.length == 1 && checkMessage((String) args[0])) {<br />count++;<br />System.out.println("Message sent:" + count);<br />return method.invoke(msgHandler, args);<br />}<br />return null;<br />}<br />private boolean checkMessage(String msg) {<br />return msg != null && msg.length() > 10;<br />}<br />}<br />//下面是调?br />import java.lang.reflect.Proxy;<br />public class MainClass {<br />private static void runProxy(MessageHandler handler) {<br />handler.sendMessage("message for test");<br />}<br />/**<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />// TODO Auto-generated method stub<br />// runProxy(new EmailMessage());<br />// System.out.println("++++++++++++++++Proxy++++++++++++++++++");<br />// runProxy(new MessageProxy());<br />MessageHandler handler = new EmailMessage();<br />runProxy(handler);<br />MessageHandler proxy = (MessageHandler) Proxy.newProxyInstance(<br />MessageHandler.class.getClassLoader(),<br />new Class[] { MessageHandler.class }, new DynamicMessageProxy(<br />handler));<br />runProxy(proxy);<br />System.out.println("++++++++++++++++++++++++++++++++++");<br />// 短信方式<br />handler = new SmsMessage();<br />runProxy(handler);<br />proxy = (MessageHandler) Proxy.newProxyInstance(MessageHandler.class<br />.getClassLoader(), new Class[] { MessageHandler.class },<br />new DynamicMessageProxy(handler));<br />runProxy(proxy);<br />}<br />}<br />下面Z上方法的输出Q?br />message for test send!!<br />++++++++=============+++++++++<br />proxy:class $Proxy0<br />method:public abstract void MessageHandler.sendMessage(java.lang.String)<br />++++++++=============+++++++++<br />Message sent:1<br />message for test send!!<br />++++++++++++++++++++++++++++++++++<br />SMS Message :message for test sent !<br />++++++++=============+++++++++<br />proxy:class $Proxy0<br />method:public abstract void MessageHandler.sendMessage(java.lang.String)<br />++++++++=============+++++++++<br />Message sent:2<br />SMS Message :message for test sent !</div><div><p>以上例子中,通过调用Proxy.newProxyInstanceҎ(gu)创徏动态代理对象,该方法需要传入一?<span>cd载器、一l希望代理实现的接口列表、InvocationHandler 接口的一个具体实现。动态代理可以将所有调用重定向到调用处理器Q通常我们?x)向该处理器传递一个时间对象的引用?/span>invoke()Ҏ(gu)中传递进来了代理对象Q当你需要区分请求来源时q是非常有用的,例如你可以通过判断传入的方法名屏蔽掉某些方法的执行Q动态代理机制ƈ不是?x)很频繁使用的方法,它通常用来解决一些特定情况下的问题,因此不要盲目的ؓ(f)了用而用,要根据自q实际需求来军_Q?/p></div><div>动态代理的应用十分q泛Q在struts2的拦截器中就用到了动态代理机制。还是以买Rؓ(f)例子Q现在用动态代理来实现Q其中不懂的接口Ҏ(gu)查查Java api׃(x)明白了,在此不多做解释,代码如下(注意PassengerProxyc?Q? <p style="text-indent: 2em;">imp<wbr>ort java.lang.reflect.*;</p> <p style="text-indent: 2em;">public interface Passenger {<br />public void buyTicket();<br />}</p> <p style="text-indent: 2em;">public class RealPassenger implements Passenger {</p> <p style="text-indent: 2em;">@Override<br />public void buyTicket() {<br />   // TODO Auto-generated method stub<br />   System.out.println("购买了R?);<br />}<br />}</p> <p style="text-indent: 2em;">// 用动态代理实?/p><p style="text-indent: 2em;">/<code>/InvocationHandler</code> 是代理实例的<em>调用处理E序</em> 实现的接口? 每个代理实例都具有一个关联的调用处理E序。对代理实例调用Ҏ(gu)Ӟ对Ҏ(gu)调用q行~码q将其指zֈ//它的调用处理E序?<code>invoke</code> Ҏ(gu)?br />public class PassengerProxy implements InvocationHandler {<br />public Object obj;</p> <p style="text-indent: 2em;">// 把obj交给代理c?br />public Object obj(Object obj) {<br />   this.obj = obj;<br />   return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj<br />     .getClass().getInterfaces(), this);<br />}</p> <p style="text-indent: 2em;">@Override<br />public Object invoke(Object proxy, Method method, Object[] args)<br />    throws Throwable {<br />   // TODO Auto-generated method stub<br />   System.out.println("通过代理");<br />   method.invoke(obj, args);<br />   return null;<br />}<br />}</p> <p style="text-indent: 2em;">public class Client {<br />public static void main(String[] args) {<br />   PassengerProxy proxy = new PassengerProxy();<br />   Passenger passenger = (Passenger) proxy.obj(new RealPassenger());<br />   passenger.buyTicket();<br />}<br />}</p><p style="text-indent: 2em;">再来一个更牛的例子</p><p style="text-indent: 2em;"></p><div><ol start="1"><li><span>/** </span></li><li><span> * 怺接口 </span></li><li><span> *  </span></li><li><span> * @author zhengt </span></li><li><span> * @time Jun 3, 2095 3:13:03 PM </span></li><li><span> */  </span></li><li><span>public interface XiangQinInterface {  </span></li><li>    <span>/** </span></li><li><span>     * 怺Ҏ(gu) </span></li><li><span>     */  </span></li><li>    <span>public void xiangQin();  </span></li><li>}  </li><li><span>/** </span></li><li><span> * 张三怺实现c?nbsp;</span></li><li><span> *  </span></li><li><span> * @author zhengt </span></li><li><span> * @time Jun 3, 2095 3:14:48 PM </span></li><li><span> */  </span></li><li><span>public class ZhangSanXiangQinInterfaceImpl implements XiangQinInterface {  </span></li><li>    <span>public void xiangQin() {  </span></li><li>        System.out.println(<span>"张三ȝԌ娶个漂亮老婆?);  </span></li><li>    }  </li><li>}  </li><li><span>import java.lang.reflect.InvocationHandler;  </span></li><li><span>import java.lang.reflect.Method;  </span></li><li>  </li><li><span>/** </span></li><li><span> * 怺可是一辈子的大事,怺前要准备一下,打扮得帅气些?nbsp;</span></li><li><span> *  </span></li><li><span> * @author zhengt </span></li><li><span> * @time Jun 3, 2095 3:15:48 PM </span></li><li><span> */  </span></li><li><span>public class ReadyInvocationHandler implements InvocationHandler {  </span></li><li>    <span>//怺接口的实现类Q也是张三怺c?nbsp; </span></li><li>    <span>private Object zhangSan = null;  </span></li><li>  </li><li>    <span>public ReadyInvocationHandler(Object realSubject) {  </span></li><li>        <span>this.zhangSan = realSubject;  </span></li><li>    }  </li><li>  </li><li>    <span>public Object invoke(Object proxy, Method m, Object[] args) {  </span></li><li>        Object result = <span>null;  </span></li><li>        <span>try {  </span></li><li>            <span>/** </span></li><li><span>             * 动态代理类$Proxy0调用xiangQinҎ(gu)时会(x)调用它自qxiangQinҎ(gu)Q?nbsp;</span></li><li><span>             * 而它自己的xiangQinҎ(gu)里面调用的是super.h.invoke(this, , )Q也是父类Proxy的h的invokeҎ(gu)Q?nbsp;</span></li><li><span>             * 也就是ReadyInvocationHandlercȝinvokeҎ(gu)?nbsp;</span></li><li><span>             * 所以,invoke(Object proxy, Method m, Object[] args)U的proxy实际上就是动态代理类$Proxy0Q?nbsp;</span></li><li><span>             * 如果你将其强转成XiangQinInterface然后调用它的xiangQinҎ(gu)Q然后它?yu)׃?x)调用super.h.invoke(this, , )Q这样就?x)死循环?nbsp;</span></li><li><span>             */  </span></li><li>            <span>/** </span></li><li><span>             * |上关于q里最多问题就是Object proxy攑֜q里用来做什么呢Q这个我也不知道Q?nbsp;</span></li><li><span>             * 不过臛_我们知道它到底是个什么东西,具体做什么用嘛就不得而知?nbsp;</span></li><li><span>             */  </span></li><li>            System.out.println(proxy.getClass().getSimpleName());  </li><li>            System.out.println(<span>"张三怺前,代理人给他打扮了打扮?);  </span></li><li>            result = m.invoke(zhangSan, args);  </li><li>        } <span>catch (Exception ex) {  </span></li><li>            System.exit(<span>1);  </span></li><li>        }  </li><li>        <span>return result;  </span></li><li>    }  </li><li>}  </li><li><span>import java.lang.reflect.InvocationHandler;  </span></li><li><span>import java.lang.reflect.Method;  </span></li><li><span>import java.lang.reflect.Proxy;  </span></li><li>  </li><li><span>/** </span></li><li><span> * 张三来到了婚介所(怺现场)Q开始相二Ӏ?nbsp;</span></li><li><span> *  </span></li><li><span> * @author zhengt </span></li><li><span> * @time Jun 3, 2095 3:17:16 PM </span></li><li><span> */  </span></li><li><span>public class HunJieSuo {  </span></li><li>    <span>public static void main(String args[]) {  </span></li><li>        <span>//先将张三怺q个怺的实现类实例化,也就是得到XiangQinInterface接口的一个实例对?nbsp; </span></li><li>        XiangQinInterface zhangSan = <span>new ZhangSanXiangQinInterfaceImpl();  </span></li><li>        <span>/** </span></li><li><span>         * 得到ZhangSanXiangQinInterfaceImplq个cȝ一个代理类Q同时ؓ(f)代理cȝ定了一个处理类ReadyInvocationHandler?nbsp;</span></li><li><span>         * 听着很绕口,其实是每次调用ZhangSanXiangQinInterfaceImplq个子类的xiangQinҎ(gu)Ӟ </span></li><li><span>         * 不是zhangSanq个ZhangSanXiangQinInterfaceImplcȝ实例去调用, </span></li><li><span>         * 而是q个ZhangSanXiangQinInterfaceImpl的代理类ReadyInvocationHandler去调用它自己的invokeҎ(gu), </span></li><li><span>         * q个invokeҎ(gu)里呢可以调用zhangSanq个实例的xiangQinҎ(gu) </span></li><li><span>         */  </span></li><li>        <span>/** </span></li><li><span>         * 在javaU怎样实现动态代理呢 </span></li><li><span>         * W一步,我们要有一个接口,q要有一个接口的实现c,而这个实现类呢就是我们要代理的对象, </span></li><li><span>         * 所谓代理呢也就是在调用实现cȝҎ(gu)Ӟ可以在方法执行前后做额外的工作,q个是代理?nbsp;</span></li><li><span>         * W二步,我们要自己写一个在要代理类的方法执行时Q能够做额外工作的类Q而这个类必须l承InvocationHandler接口Q?nbsp;</span></li><li><span>         * Z么要l承它呢Q因Z理类的实例在调用实现cȝҎ(gu)的时候,不会(x)调真正的实现cȝq个Ҏ(gu)Q?nbsp;</span></li><li><span>         * 而是转而调用这个类的invokeҎ(gu)Q承时必须实现的方法)Q在q个Ҏ(gu)中你可以调用真正的实现类的这个方法?nbsp;</span></li><li><span>         * W三步,在要用代理类的实例去调用实现cȝҎ(gu)的时候,写出下面两段代码?nbsp;</span></li><li><span>         */  </span></li><li>        XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance(  </li><li>                zhangSan.getClass().getClassLoader(),  </li><li>                zhangSan.getClass().getInterfaces(),  </li><li>                <span>new ReadyInvocationHandler(zhangSan));  </span></li><li>        proxy.xiangQin();  </li><li>        <span>/** </span></li><li><span>         * q里要解释下中部那段镉K的代码的意思,以及具体做了哪些工作Q?nbsp;</span></li><li><span>         * W一Q根据zhangSan.getClass().getClassLoader()q个要代理类的类加蝲器和 </span></li><li><span>         * zhangSan.getClass().getInterfaces()要代理类所实现的所有的接口 </span></li><li><span>         * 作ؓ(f)参数调用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces) </span></li><li><span>         * 的方法返回代理类的java.lang.Class对象Q也是得到了java动态生成的代理c?Proxy0的Class对象?nbsp;</span></li><li><span>         * 同时Qjavaq让q个动态生成的$Proxy0cdC要代理类的实现的所有接口,q承了Proxy接口?nbsp;</span></li><li><span>         * W二Q实例化q个动态生成的$Proxy0cȝ一个实例,实例化代理类的构造函Cؓ(f)Proxy(InvocationHandler h)Q?nbsp;</span></li><li><span>         * 也就是说要实例化q个动态生成的$Proxy0c,必须l它一个InvocationHandler参数Q也是我们自己实现的用来在代理c?nbsp;</span></li><li><span>         * Ҏ(gu)执行前后做额外工作的cReadyInvocationHandler?nbsp;</span></li><li><span><span>         * q?D代?Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan))</span> </span></li><li><span>         * 得到的其实是一个类名叫$Proxy0 extends Proxy implements XiangQinInterface的类?nbsp;</span></li><li><span>         * W三Q将q个$Proxy0cd制{型成XiangQinInterfacecdQ调用xiangQinҎ(gu)?nbsp;</span></li><li><span>         */  </span></li><li>    }  </li><li>}  <br /></li></ol></div><div>|上看到一个牛q这个动态代理的源代码,现把|址留在q里Q希望对|友们有帮助?<br /><a target="_blank" >http://hi.baidu.com/malecu/blog/item/45d4952b31bc0e27d52af17a.html</a> </div><div><div><div>在目前的Java开发包中包含了对动态代理的支持Q但是其实现只支持对接口的的实现?<br /> <br />  其实C要通过是java.lang.reflect.Proxycdjava.lang.reflect.InvocationHandler接口?<br /> <br />  ProxycM要用来获取动态代理对象,InvocationHandler接口用来U束调用者实玎ͼ如下QDiaoSi接口定义?业务Ҏ(gu)QDiaoSiNanImpl是DiaoSi接口的实玎ͼ<div>DiaoSiNanHandler? InvocationHandler接口实现。代码如下:(x)<br /><div>业务接口: </div></div></div><div>package proxy;<br /><br />public interface DiaoSi {<br />void luGuan();<br />}<br /></div><div><div> 业务接口实现Q?</div></div><div>public class DiaoSiNan implements DiaoSi {<br /><br />    @Override<br />    public void luGuan() {<br />        // TODO Auto-generated method stub<br />        System.out.println("我是撸管?);<br />    }<br /><br />}</div><div> InvocationHandler实现Q需要在接口Ҏ(gu)调用前后加入一部䆾处理工作Q这里仅仅在Ҏ(gu)调用前后向后台输Z句字W串Q其代码如下Q?</div><div>package proxy;<br /><br />import java.lang.reflect.InvocationHandler;<br />import java.lang.reflect.Method;<br /><br />public class DiaoSiNanHander implements InvocationHandler{<br />    //要代理的原始对象 <br />    <br />private Object diaosinan; <br />/**<br /><br />* 构造函数?br /><br />* @param obj 要代理的原始对象?br /><br />*/ <br />public DiaoSiNanHander(Object diaosinan) {<br /><br />    this.diaosinan = diaosinan;<br />}<br />    @Override<br />    <br />    public Object invoke(Object proxy, Method method, Object[] args)<br />            throws Throwable {<br />        // TODO Auto-generated method stub<br />        Object result ;<br />        doBefore(); <br />        //调用原始对象的方?<br />        result = method.invoke(this.diaosinan ,args); <br />        //Ҏ(gu)调用之后 <br />        doafter();<br />        return result;<br /><br />        <br />    }<br />    private void doafter() {<br />        // TODO Auto-generated method stub<br />System.out.println("after method invoke!"); <br />    }<br />    private void doBefore() {<br />        // TODO Auto-generated method stub<br />        System.out.println("before method invoke!"); <br />    }<br /><br /><br />}<br /></div><div>试代码Q?</div><div>package proxy;<br /><br />import java.lang.reflect.InvocationHandler;<br />import java.lang.reflect.Proxy;<br /><br />public class Test {<br />public static void main(String[] args) {<br />DiaoSi ds = new DiaoSiNan();<br /><br />DiaoSiNanHander handler = new DiaoSiNanHander(ds);<br /><br />DiaoSi proxy = (DiaoSi) Proxy.newProxyInstance(<br /><br />ds.getClass().getClassLoader(),<br /><br />ds.getClass().getInterfaces(),<br /><br />handler);<br />/*public static Object newProxyInstance(ClassLoader loader,<br />        Class<?>[] interfaces,<br />        InvocationHandler h)<br />throws IllegalArgumentException<br />{<br />if (h == null) {<br />throw new NullPointerException();<br />}*/<br />proxy.luGuan();<br /><br />        <br /><br />}<br />}<br /><div>Ø 首先获取一个业务接口的实现对象; <br /> <br />  Ø 获取一个InvocationHandler实现Q此处是<div>DiaoSiNanHanderHandler对象;</div> <br />  Ø 创徏动态代理对? <br /> <br />  Ø 通过动态代理对象调用luGuan()Ҏ(gu)Q此时会(x)在原始对象DiaoSiNan.luGuan()Ҏ(gu)前后输出两句字符丌Ӏ?<br /> <br />  q行试c输出如? <br /> <br />  <div>before method invoke!<br />我试撸管?br />after method invoke!<br /></div><br /> <br />  此处TestcM的方法调用代码比较多Q在我们的实际应用中可以通过配置文g来来化客L(fng)的调用实现。另外也可以通过动态代理来实现单的AOP?</div></div><br /><p><br /></p></div><br /></div><br /><p> </p></div><img src ="http://m.tkk7.com/qileilove/aggbug/392932.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qileilove/" target="_blank">其自然EVO</a> 2012-12-13 11:53 <a href="http://m.tkk7.com/qileilove/archive/2012/12/13/392932.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学?fn)设计模?--代理模式http://m.tkk7.com/qileilove/archive/2012/12/13/392930.html其自然EVO其自然EVOThu, 13 Dec 2012 03:20:00 GMThttp://m.tkk7.com/qileilove/archive/2012/12/13/392930.htmlhttp://m.tkk7.com/qileilove/comments/392930.htmlhttp://m.tkk7.com/qileilove/archive/2012/12/13/392930.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/392930.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/392930.htmlJava 代理模式详解

代理模式是我们比较常用的设计模式之一。其中新思想是ؓ(f)了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象q行通信Q代理模式一般涉及到的角色有Q?nbsp;

抽象角色Q声明真实对象和代理对象的共同接口; 

代理角色Q代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在Q何时刻都能代替真实对象。同Ӟ代理对象可以在执行真实对象操作时Q附加其他的操作Q相当于对真实对象进行封装?nbsp;

真实角色Q代理角色所代表的真实对象,是我们最l要引用的对象?

 

以下以发送消息ؓ(f)例来说明一个简单的代理模式的基本实玎ͼ(x)

首先明确目的Q有一条消息,需要把q个消息发送出去,Ҏ(gu)q个目的定义对应接口MessageHandler。需要的附加操作Q假N要验证消息的长度不能过指定长度q且不能为空Qƈ且我们需要统计相关信息发送到ơ数Q超q指定的ơ数我们需要输报。我们通过代理模式来实现这个附加的操作。下面ؓ(f)对应的类关系囑֏CZ代码?/p>




//接口定义
public interface MessageHandler {
public void sendMessage(String msg);
}
//通过Email方式发送消息的实现c?br />public class EmailMessage implements MessageHandler {
@Override
public void sendMessage(String msg) {
// TODO Auto-generated method stub
System.out.println(msg+" send!!");
}
}
//消息处理的代理类
public class MessageProxy implements MessageHandler {
private static int count;
private MessageHandler emailMsg;
@Override
public void sendMessage(String msg) {
// TODO Auto-generated method stub
if(checkMessage(msg))
{
if(emailMsg==null) emailMsg=new EmailMessage();
count++;
emailMsg.sendMessage(msg);
System.out.println("Message sent:"+count);
}
}
private boolean checkMessage(String msg) {
return msg != null && msg.length() > 10;
}
}
//调用c?br />public class MainClass {
private static void runProxy(MessageHandler handler)
{
handler.sendMessage("message for test");
}
/**
 * @param args
 */
public static void main(String[] args) {
// TODO Auto-generated method stub
runProxy(new EmailMessage());
System.out.println("++++++++++++++++Pjroxy++++++++++++++++++");
runProxy(new MessageProxy());
}
}
输出
message for test send!!
++++++++++++++++Pjroxy++++++++++++++++++
message for test send!!
Message sent:1

在例子中我们可以方便的在消息发送过E中d各种需要的附加处理方式Q也能方便的替换消息的处理方式,如将通过Email发送消息替换ؓ(f)通过短信发送消息,而调用方不会(x)有丝毫察觉!在Q何你惌一些额外操作分d具体对象之外Q特别是希望能够很容易做Z改,或者想在具体对象的Ҏ(gu)执行前插入一些额外操作的时候,代理显得十分有用!

 例如Q假设有一l对象都实现同一个接口,实现同样的方法,但这l对象中有一部分对象需要有单独的方法,传统的笨办法是在每一个应用端都加上这个单独的Ҏ(gu)Q但是代码重用性低Q耦合性高?  如果用代理的Ҏ(gu)则很好的解决了这个问?/div>
 假设有一个Italk接口Q有I的Ҏ(gu)talkQ)Q说话)Q所有的people对象都实玎ͼimplementsQ这个接口,实现talkQ)Ҏ(gu)Q?前端有很多地斚wpeople实例化,执行talkҎ(gu)Q后来发现这些前端里有一些除了要说话以外q要唱歌QsingQ,那么我们既不能在Italk?口里增加sing()Ҏ(gu)Q又不能在每个前端都增加singҎ(gu)Q我们只有增加一个代理类talkProxyQ这个代理类里实现talk和singҎ(gu)Q?然后在需要singҎ(gu)的客L(fng)调用代理cd可,代码如下Q?h3>接口cItalk  public interface Italk {
  public void talk(String msg);
  }

实现cpeople

  public class People implements Italk
 {   public String username;  
 public String age;  
 public String getName()
{   
return username;
  }   
public void setName(String name) {
  this.username= name;   
}  
 public String getAge() {  
 return age;   }   
public void setAge(String age) {
  this.age = age;   }  
 public People(String name1, String age1) {
  this.username= name1;  
 this.age = age1;  
 }
  public void talk(String msg) {
  System.out.println(msg+"!你好,我是"+username+"Q我q龄?+age);
  }   
}

代理ctalkProxy

  public class TalkProxy implements Italk
 {   Italk talker;  
 public TalkProxy (Italk talker)
{
  //super();   
this.talker=talker;  
 }   
public void talk(String msg)
{   
talker.talk(msg);  
 }   
public void talk(String msg,String singname)
 {   
talker.talk(msg);
  sing(singname);
  }   
private void sing(String singname)
{  
 System.out.println("唱歌Q?+singname);
  }  
 }
  }

应用端myProxyTest

  public class MyProxyTest {  
 /**代理模式   * @param args   */  
 public static void main(String[] args)
 {   
//不需要执行额外方法的  
 Italk people1=new People(" people1.talk("No ProXY Test");  
 System.out.println("-----------------------------");  
 //需要执行额外方法的   
TalkProxy talker=new TalkProxy(people1);   
talker.talk("ProXY Test","七里?);
  }  
 }
所谓代理,是指h与代理元Q被代理的对象)h相同的接口的c,客户端必通过代理与被?理的目标cM互,而代理一般在交互的过E中Q交互前后)Q进行某些特别的处理。Proxy模式是很常见的模式,在我们生zM处处可见Q例如我们买火R不 一定非要到火R站去乎ͼ可以C些火车票的代售点M。寄信不一定是自己dQ可以把信委托给邮局Q由邮局把信送到目的地?

代理l构如下图所C?/p>

Java 代理/动态代理模?Proxy) - stevinzhu - stevinzhu的博? src=

以通过代售点买火Rؓ(f)例,代码实现如下Q?/p>

//提供买票的公共接?br />interface Passenger {
public void buyTicket();
}

//乘客实体
public class RealPassenger implements Passenger {
@Override
public void buyTicket() {
   // TODO Auto-generated method stub
   System.out.print("购买了火车票");
}
}

//代售?br />public class Proxy implements Passenger {
Passenger passenger;

public Proxy(Passenger p) {
   this.passenger = p;
}

@Override
public void buyTicket() {
   // TODO Auto-generated method stub
   System.out.println("通过代售?);
   passenger.buyTicket();
}
}

//试c?br />public class Client {
public static void main(String[] args) {
   Passenger passenger = new RealPassenger();
   Passenger proxy = new Proxy(passenger);
   proxy.buyTicket();
}
}

输出l果Q?br />通过代售?br />购买了火车票

?上的也可叫做静态代理,是ؓ(f)了区别代理模式在Java中的另一U实?#8212;—动态代理?/p>

接下来会(x)为大家带来动态代?br />



其自然EVO 2012-12-13 11:20 发表评论
]]>跟屌丝大哥一起学?fn)设计模?--中介者模?/title><link>http://m.tkk7.com/qileilove/archive/2012/12/12/392858.html</link><dc:creator>其自然EVO</dc:creator><author>其自然EVO</author><pubDate>Wed, 12 Dec 2012 05:23:00 GMT</pubDate><guid>http://m.tkk7.com/qileilove/archive/2012/12/12/392858.html</guid><wfw:comment>http://m.tkk7.com/qileilove/comments/392858.html</wfw:comment><comments>http://m.tkk7.com/qileilove/archive/2012/12/12/392858.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qileilove/comments/commentRss/392858.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qileilove/services/trackbacks/392858.html</trackback:ping><description><![CDATA[     摘要: 中介者模式(MediatorQ:(x)用一个中介对象来装一pd的对象交互。中介者各对象不需要显式地怺引用Q从而其耦合松散Q而且可以独立地改变它们之间的交互。通用cdQD例:(x)在一个公叔R面,有很多部门、员工(我们l称他们互相为Colleague“同事”Q,Z完成一定的dQ?#8220;同事”之间肯定有许多需要互盔R合、交的q程。如果由各个“同事...  <a href='http://m.tkk7.com/qileilove/archive/2012/12/12/392858.html'>阅读全文</a><img src ="http://m.tkk7.com/qileilove/aggbug/392858.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qileilove/" target="_blank">其自然EVO</a> 2012-12-12 13:23 <a href="http://m.tkk7.com/qileilove/archive/2012/12/12/392858.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学?fn)设计模?--观察者模?/title><link>http://m.tkk7.com/qileilove/archive/2012/12/11/392774.html</link><dc:creator>其自然EVO</dc:creator><author>其自然EVO</author><pubDate>Tue, 11 Dec 2012 03:51:00 GMT</pubDate><guid>http://m.tkk7.com/qileilove/archive/2012/12/11/392774.html</guid><wfw:comment>http://m.tkk7.com/qileilove/comments/392774.html</wfw:comment><comments>http://m.tkk7.com/qileilove/archive/2012/12/11/392774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/qileilove/comments/commentRss/392774.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/qileilove/services/trackbacks/392774.html</trackback:ping><description><![CDATA[<h2><a id="viewpost1_TitleUrl" href="http://m.tkk7.com/supercrsky/articles/202544.html" style="color: #0066aa; text-decoration: initial;">Java 观察者模式的析</a></h2><div style="font-size: 13px; line-height: 19px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; background-color: #ffffff;">单地_(d)观察者模式定义了一个一对多的依赖关p,让一个或多个观察者对象监察一个主题对象。这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象,使这些观察者对象能够自动更新?br /> <strong>观察者模式的l构</strong><br /><br />  观察者(ObserverQ模式是对象的行为型模式Q又叫做发表-订阅QPublish/SubscribeQ模式、模?视图QModel/ViewQ模式、源-收听者(Source/ListenerQ模式或从属者(DependentsQ模式?br /><br /> 本模式的cdl构如下Q?br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="371" alt="" src="http://www.yesky.com/20020603/observer.gif" width="557" /><br />?、观察者模式的静态结构可从类图中看清楚?/td></tr></tbody></table><p style="margin: 10px 0px;">  在观察者模式里有如下的角色Q?br /> .<strong> 抽象主题QSubjectQ角?/strong>Q主题角色把所有的观察者对象的引用保存在一个列表里Q每个主题都可以有Q何数量的观察者。主题提供一个接口可以加上或撤销观察者对象;主题角色又叫做抽象被观察?Observable)角色Q?nbsp;<br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="154" alt="" src="http://www.yesky.com/20020603/role1.gif" width="154" /><br />?、抽象主题角Ԍ有时又叫做抽象被观察者角Ԍ可以用一个抽象类或者一个接口实玎ͼ在具体的情况下也不排除用具体类实现?/td></tr></tbody></table></p><p style="margin: 10px 0px;">  .<strong> 抽象观察者(ObserverQ角?/strong>Qؓ(f)所有的具体观察者定义一个接口,在得到通知时更新自己; <br /></p><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="122" alt="" src="http://www.yesky.com/20020603/role3.gif" width="154" /><br />?、抽象观察者角Ԍ可以用一个抽象类或者一个接口实玎ͼ在具体的情况下也不排除用具体类实现?/td></tr></tbody></table><p style="margin: 10px 0px;">  .<strong> 具体主题QConcreteSubjectQ角?/strong>Q保存对具体观察者对象有用的内部状态;在这U内部状态改变时l其观察者发Z个通知Q具体主题角色又叫作具体被观察者角Ԍ</p><img height="179" alt="" src="http://www.yesky.com/20020603/role2.gif" width="171" style="font-size: 12px; line-height: normal;" /><br style="font-size: 12px; line-height: normal;" /><span style="font-size: 12px; line-height: normal;">?、具体主题角Ԍ通常用一个具体子cd现?br /><br /></span><p style="margin: 10px 0px;">Q?strong>具体观察者(ConcreteObserverQ角?/strong>Q保存一个指向具体主题对象的引用Q和一个与主题的状态相W的状态。具体观察者角色实现抽象观察者角色所要求的更新自q接口Q以便本n的状态与主题的状态自恰?nbsp;<br /></p><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="122" alt="" src="http://www.yesky.com/20020603/role4.gif" width="160" /><br />?、具体观察者角Ԍ通常用一个具体子cd现?/td></tr></tbody></table><span style="font-size: 12px; line-height: normal;"><br /></span><p style="margin: 10px 0px;">下面l出一个示意性实现的Java代码。首先在q个C意性的实现里,用一个Java接口实现抽象主题角色Q这是下面的Subject接口Q?br /></p><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><br />public interface Subject<br />{<br />public void attach(Observer observer);<br /><br />public void detach(Observer observer);<br /><br />void notifyObservers();<br />}<br /></td></tr></tbody></table>代码清单1、Subject接口的源代码?nbsp;<br /><br />  q个抽象主题接口规定Z个子cdd现的操作Q即 attach() 用来增加一个观察者对象;detach() 用来删除一个观察者对象;和notifyObservers() 用来通知各个观察者刷新它们自己。抽象主题角色实际上要求子类保持一个以所有的观察者对象ؓ(f)元素的列表?br /><br />  具体主题则是实现了抽象主题Subject接口的一个具体类Q它l出了以上的三个操作的具体实现。从下面的源代码可以看出Q这里给出的Java实现使用了一个Java向量来保存所有的观察者对象,?attach() ?detach() 操作则是Ҏ(gu)向量的元素增减操作?br /><br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><br />import java.util.Vector;<br />import java.util.Enumeration;<br /><br />public class ConcreteSubject implements Subject<br />{<br />public void attach(Observer observer)<br />{<br />observersVector.addElement(observer);<br />}<br /><br />public void detach(Observer observer)<br />{<br />observersVector.removeElement(observer);<br />}<br /><br />public void notifyObservers()<br />{<br />Enumeration enumeration = observers();<br />while (enumeration.hasMoreElements())<br />{<br />((Observer)enumeration.nextElement()).update();<br />}<br />}<br /><br />public Enumeration observers()<br />{<br />return (QVector) observersVector.clone()).elements();<br />}<br />private Vector observersVector = new java.util.Vector();<br />}<br /></td></tr></tbody></table>代码清单2、ConcreteSubjectcȝ源代码?nbsp;<br />  抽象观察者角色的实现实际上是最为简单的一个,它是一个Java接口Q只声明了一个方法,即update()。这个方法被子类实现后,一被调用便h自己?br /><br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;">public interface Observer<br />{<br />void update();<br />}</td></tr></tbody></table>代码清单3、Observer接口的源代码?nbsp;<br /><br />  具体观察者角色的实现其实只涉及update()Ҏ(gu)的实现。这个方法怎么实现与应用密切相养I因此本类只给Z个框架?br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;">public class ConcreteObserver implements Observer<br />{<br />public void update()<br />{<br />// Write your code here<br />}<br />}</td></tr></tbody></table>代码清单4、ConcreteObservercȝ源代码?nbsp;<br /><br />  虽然观察者模式的实现Ҏ(gu)可以有设计师自己定Q但是因ZAWT1.1开始视H系l的事g模型采用观察者模式,因此观察者模式在Java语言里的C较ؓ(f)重要。正因ؓ(f)q个原因QJava语言l出了它自己对观察者模式的支持。因此,本文读者在自己的系l中应用观察者模式时Q不妨利用Java语言所提供的支持?br />  <strong>Java语言提供的对观察者模式的支持</strong><br /><br />  在Java语言的java.util库里面,提供了一个ObservablecM及一个Observer接口Q构成Java语言对观察者模式的支持?br /><br />  <strong>Observer接口</strong><br /><br />  q个接口只定义了一个方法,update()。当被观察者对象的状态发生变化时Q这个方法就?x)被调用。这个方法的实现应当调用每一个被观察者对象的notifyObservers()Ҏ(gu)Q从而通知所有的观察对象?br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="115" alt="" src="http://www.yesky.com/20020603/observerinterface.gif" width="258" /><br />?、java.util提供的Observer接口的类图?/td></tr></tbody></table><br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><br />package java.util;<br /><br />public interface Observer<br />{<br />/**<br />* 当被观察的对象发生变化时Q这个方法会(x)被调用?br />*/<br />void update(Observable o, Object arg);<br />}<br /></td></tr></tbody></table>代码清单5、java.util.Observer接口的源代码?nbsp;<br /><br />  <strong>Observablec?/strong><br /><br />  被观察者类都是java.util.Observablecȝ子类。java.util.Observable提供公开的方法支持观察者对象,q些Ҏ(gu)中有两个对Observable的子c非帔R要:(x)一个是setChanged()Q另一个是notifyObservers()。第一个方法setChanged()被调用之后会(x)讄一个内部标记变量,代表被观察者对象的状态发生了变化。第二个是notifyObservers()Q这个方法被调用Ӟ?x)调用所有登记过的观察者对象的update()Ҏ(gu)Qɘq些观察者对象可以更新自己?br /><br />  java.util.Observablec还有其它的一些重要的Ҏ(gu)。比如,观察者对象可以调用java.util.ObservablecȝaddObserver()Ҏ(gu)Q将对象一个一个加入到一个列表上。当有变化时Q这个列表可以告诉notifyObservers()Ҏ(gu)那些观察者对象需要通知。由于这个列表是U有的,因此java.util.Observable的子对象q不知道观察者对象一直在观察着它们?br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="281" alt="" src="http://www.yesky.com/20020603/observable.gif" width="223" /><br />?、Java语言提供的被观察者的cd?/td></tr></tbody></table><br />  被观察者类Observable的源代码Q?br /><br /><span style="line-height: normal; color: #0000ff;">package</span><span style="line-height: normal;"> java.util;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="line-height: normal; color: #0000ff;">public</span> <span style="line-height: normal; color: #0000ff;">class</span><span style="line-height: normal;"> Observable<br /><img id="Codehighlighter1_44_1304_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /></span><span id="Codehighlighter1_44_1304_Open_Text" style="line-height: normal;">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span> changed = <span style="color: #0000ff;">false</span>;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">private</span> Vector obs;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_100_121_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_100_121_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"> ?个观察者构造一个被观察者?</span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> Observable()<br /><img id="Codehighlighter1_144_166_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_144_166_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs = <span style="color: #0000ff;">new</span> Vector();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_169_193_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_169_193_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 一个观察者加到观察者列表上面?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span> addObserver(Observer o)<br /><img id="Codehighlighter1_244_291_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_244_291_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">if</span> (!obs.contains(o))<br /><img id="Codehighlighter1_268_289_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_268_289_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs.addElement(o);<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_294_320_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_294_320_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 一个观察者对象从观察者列表上删除?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span> deleteObserver(Observer o)<br /><img id="Codehighlighter1_374_398_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_374_398_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs.removeElement(o);<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_401_434_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_401_434_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 相当?nbsp;notifyObservers(null)<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> notifyObservers()<br /><img id="Codehighlighter1_466_491_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_466_491_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />notifyObservers(<span style="color: #0000ff;">null</span>);<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_494_590_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_494_590_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 如果本对象有变化Q那时hasChanged Ҏ(gu)?x)返回trueQ?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 调用本方法通知所有登记在案的观察者,卌用它们的update()Ҏ(gu)Q?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 传入this和arg作ؓ(f)参量?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> notifyObservers(Object arg)<br /><img id="Codehighlighter1_632_861_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_632_861_Open_Text">{<br /><img id="Codehighlighter1_634_664_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_634_664_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 临时存放当前的观察者的状态。参见备忘录模式?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />Object[] arrLocal;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span>)<br /><img id="Codehighlighter1_706_772_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_706_772_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">if</span> (!changed) <span style="color: #0000ff;">return</span>;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />arrLocal = obs.toArray();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />clearChanged();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = arrLocal.length-1; i>=0; i--)<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />((Observer)arrLocal[i]).update(<span style="color: #0000ff;">this</span>, arg);<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_864_880_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_864_880_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 观察者列表清I?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span> deleteObservers()<br /><img id="Codehighlighter1_925_952_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_925_952_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs.removeAllElements();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_955_975_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_955_975_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* ?#8220;已变?#8221;设ؓ(f)true<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span> setChanged()<br /><img id="Codehighlighter1_1018_1036_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1018_1036_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />changed = <span style="color: #0000ff;">true</span>;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_1039_1061_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1039_1061_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* ?#8220;已变?#8221;重置为false<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">void</span> clearChanged()<br /><img id="Codehighlighter1_1106_1125_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1106_1125_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />changed = <span style="color: #0000ff;">false</span>;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_1128_1146_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1128_1146_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* 探测本对象是否已变化<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">boolean</span> hasChanged()<br /><img id="Codehighlighter1_1189_1207_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1189_1207_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">return</span> changed;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_1210_1238_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1210_1238_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />* q还被观察对象(x对象Q的观察者L?br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">synchronized</span> <span style="color: #0000ff;">int</span> countObservers()<br /><img id="Codehighlighter1_1281_1302_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1281_1302_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">return</span> obs.size();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span><span style="line-height: normal;"><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /></span>代码清单6、java.util.Observer接口的源代码?nbsp;<br /><br />  q个ObservablecM表一个被观察者对象。一个被观察者对象可以有C观察者对象,一个观察者可以是一个实现Observer接口的对象。在被观察者对象发生变化时Q它?x)调用Observable的notifyObserversҎ(gu)Q此Ҏ(gu)调用所有的具体观察者的update()Ҏ(gu)Q从而所有的观察者都被通知更新自己。见下面的类图:(x)<br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="211" alt="" src="http://www.yesky.com/20020603/javautilmethods.gif" width="585" /><br />?、用Java语言提供的对观察者模式的支持?/td></tr></tbody></table><br />  发通知的次序在q里没有指明。ObserverablecL提供的缺省实C(x)按照Observers对象被登记的ơ序通知它们Q但是Observerablecȝ子类可以Ҏ(gu)q一ơ序。子cdƈ可以在单独的U程里通知观察者对象;或者在一个公用的U程里按照次序执行?nbsp;<br /><br />  当一个可观察者对象刚刚创立时Q它的观察者集合是I的。两个观察者对象在它们的equals()Ҏ(gu)q回trueӞ被认为是两个相等的对象?nbsp;<br />  <strong>怎样使用Java对观察者模式的支持</strong><br /><br />  Z说明怎样使用Java所提供的对观察者模式的支持Q本节给Z个非常简单的例子。在q个例子里,被观察对象叫做WatchedQ也是被监视者;而观察者对象叫做Watcher。Watched对象l承自java.util.Obsevablec;而W(xu)atcher对象实现了java.util.Observer接口。另外有一个对象TesterQ扮演客L(fng)的角艌Ӏ?nbsp;<br /><br />  q个单的pȝ的结构如下图所C?nbsp;<br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="371" alt="" src="http://www.yesky.com/20020603/watching.gif" width="511" /><br />?、一个用Observer接口和Observablecȝ例子?/td></tr></tbody></table><br />  在客L(fng)改变Watched对象的内部状态时QW(xu)atched׃(x)通知Watcher采取必要的行动?nbsp;<br /><span style="line-height: normal;"><br /></span><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 647.7666625976563px; word-break: break-all; background-color: #eeeeee;"><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">package</span> com.javapatterns.observer.watching;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">import</span> java.util.Observer;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Tester<br /><img id="Codehighlighter1_93_466_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_93_466_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">private</span> Watched watched;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">static</span> <span style="color: #0000ff;">private</span> Observer watcher;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> main(String[] args)<br /><img id="Codehighlighter1_200_464_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_200_464_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched = <span style="color: #0000ff;">new</span> Watched();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watcher = <span style="color: #0000ff;">new</span> Watcher(watched);<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In C, we create bugs.");<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In Java, we inherit bugs.");<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In Java, we inherit bugs.");<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In Visual Basic, we visualize bugs."); <br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /></div></td></tr></tbody></table><br />  代码清单7、Testercȝ源代码?nbsp;<br /><span style="line-height: normal;"><br /><br /></span> 代码清单7、Testercȝ源代码?nbsp;<br /><br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 647.7666625976563px; word-break: break-all; background-color: #eeeeee;"><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">package</span> com.javapatterns.observer.watching;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">import</span> java.util.Observable;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Watched <span style="color: #0000ff;">extends</span> Observable<br /><img id="Codehighlighter1_115_319_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_115_319_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">private</span> String data = "";<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> String retrieveData()<br /><img id="Codehighlighter1_173_188_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_173_188_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">return</span> data;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> changeData(String data)<br /><img id="Codehighlighter1_227_317_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_227_317_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">if</span> ( !<span style="color: #0000ff;">this</span>.data.equals( data) )<br /><img id="Codehighlighter1_261_295_Open_Image" src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_261_295_Open_Text">{<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">this</span>.data = data;<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />setChanged();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />notifyObservers();<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span></div></td></tr></tbody></table><br /><br />代码清单9、Watchercȝ源代码?nbsp;<br /><br />  可以看出Q虽然客L(fng)Watched对象的内部状态赋g四次Q但是值的改变只有三次Q?br /><br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 647.7666625976563px; word-break: break-all; background-color: #eeeeee;"><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In C, we create bugs.");<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In Java, we inherit bugs.");<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In Java, we inherit bugs.");<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In Visual Basic, we visualize bugs."); </div></td></tr></tbody></table><br />  代码清单10、被观察者的内部状态发生了改变?nbsp;<br /><br />  对应圎ͼW(xu)atcher对象汇报了三ơ改变,下面是q行旉E序打印出的信息Q?br /><table width="100%" bgcolor="#ffffff" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><br /><div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 647.7666625976563px; word-break: break-all; background-color: #eeeeee;"><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />Data has been changed to: 'In C, we create bugs.'<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />Data has been changed to: 'In Java, we inherit bugs.'<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" />Data has been changed to: 'In Visual Basic, we visualize bugs.'<br /><img src="http://m.tkk7.com/Images/OutliningIndicators/None.gif" align="top" alt="" /></div></td></tr></tbody></table><br />  代码清单11、运行的l果?nbsp;<br /><br /> <strong>菩萨的守瓉</strong><br /><br />  惛_q齐天大圣ؓ(f)解救师傅唐僧Q前往南v普陀p菩萨降伏妖怪红孩儿Q?#8220;菩萨听说...恨了一壎ͼ手中宝珠净瓶往心里扑的一?..只见那v当中Q翻波蟩,d个瓶来,原来是一个怪物驮着出来...要知此怪名和姓Q兴风作恶乌龟?#8221; <br /><br />  使用面向对象的语a描述Q乌龟便是一个观察者对象,它观察的主题是菩萨。一旦菩萨将净瓶掼到v里,p征着菩萨作ؓ(f)主题调用了notifyObservers()Ҏ(gu)。在西游CQ观察者对象有两个Q一个是乌龟Q另一个是(zhn)空。?zhn)I的反应在这里暂时不考虑Q而乌龟的反应便是瓶子驮回v岸?nbsp;<br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="184" alt="" src="http://www.yesky.com/20020603/turtle.gif" width="447" /><br />?0、菩萨和菩萨的守瓶乌龟?/td></tr></tbody></table><strong>Java中的DEM事g机制</strong><br /><br />  <strong>AWT中的DEM机制</strong><br /><br />  责Q链模式一章中曾谈刎ͼAWT1.0的事件处理的模型是基于责任链的。这U模型不适用于复杂的pȝQ因此在AWT1.1版本及以后的各个版本中,事g处理模型均ؓ(f)Z观察者模式的委派事g模型QDelegation Event Model或DEMQ?nbsp;<br /><br />  在DEM模型里面Q主题(SubjectQ角色负责发布(publishQ事Ӟ而观察者角色向特定的主题订阅(subscribeQ它所感兴的事g。当一个具体主题生一个事件时Q它?yu)׃?x)通知所有感兴趣的订阅者?nbsp;<br /><br />  使用q种发布-订阅机制的基本设计目标,是提供一U将发布者与订阅者松散地耦合在一L(fng)联系形式Q以及一U能够动态地登记、取消向一个发布者的订阅h的办法。显Ӟ实现q一构思的技巧,是设计抽象接口,q把抽象层和具体层分开。这在观察者模式里可以清楚地看到?nbsp;<br /><br />  使用DEM的用词,发布者叫做事件源Qevent sourceQ,而订阅者叫做事件聆听者(event listenerQ。在Java里面Q事件由cM表,事g的发布是通过同步地调用成员方法做到的?nbsp;<br /><br />  <strong>Servlet技术中的的DEM机制</strong><br /><br />  AWT中所使用的DEM事g模型实际上被应用C所有的Java事g机制上。Servlet技术中的事件处理机制同样也是用的DEM模型?nbsp;<br /><br />  <strong>SAX2技术中的DEM机制</strong><br /><br />  DEM事g模型也被应用CSAX2的事件处理机制上?nbsp;<br /><br />  <strong>观察者模式的效果</strong><br /><br />  观察者模式的效果有以下的<strong>优点</strong>Q?nbsp;<br /><br />  W一、观察者模式在被观察者和观察者之间徏立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表,每一个具体观察者都W合一个抽象观察者的接口。被观察者ƈ不认识Q何一个具体观察者,它只知道它们都有一个共同的接口?nbsp;<br /><br />  ׃被观察者和观察者没有紧密地耦合在一P因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔CP那么q个对象必然跨越抽象化和具体化层ơ?nbsp;<br /><br />  W二、观察者模式支持广播通讯。被观察者会(x)向所有的登记q的观察者发出通知Q?nbsp;<br /><br />  观察者模式有下面?strong>~点</strong>Q?nbsp;<br /><br />  W一、如果一个被观察者对象有很多的直接和间接的观察者的话,所有的观察者都通知C(x)p很多旉?nbsp;<br /><br />  W二、如果在被观察者之间有循环依赖的话Q被观察者会(x)触发它们之间q行循环调用Q导致系l崩溃。在使用观察者模式是要特别注意这一炏V?nbsp;<br /><br />  W三、如果对观察者的通知是通过另外的线E进行异步投递的话,pȝ必须保证投递是以自恰的方式q行的?nbsp;<br /><br />  W四、虽然观察者模式可以随时观察者知道所观察的对象发生了变化Q但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的?nbsp;<br /><br />  <strong>观察者模式与其它模式的关p?/strong><br /><br />  观察者模式用了备忘录模?Memento Pattern)暂时观察者对象存储在被观察者对象里面?br /><br />  <strong>问答?/strong><br /><br />  W一题、我和妹妹跟妈妈_(d)(x)“妈妈Q我和妹妹在院子里玩Q饭做好了叫我们一声?#8221;请问q是什么模式?能否l出cd说明Q?br /><br />  <strong>问答题答?/strong><br /><br />  W一题答案、这是观察者模式。我和妹妹让妈妈告诉我们饭做好了Q这h们就可以来吃饭了。换用较为技术化的语a来说Q当pȝ的主题(饭)发生变化Ӟ告诉系l的其它部䆾Q观察者们Q也是妈妈、我和妹妹)Q其可以调整内部状态(有开始吃饭的准备Q,q取相应的行动Q吃饭)?br /><br />  pȝ的类图说明如下?br /><br /><table width="100%" style="width: 667px;"><tbody><tr><td style="font-size: 12px;"><img height="248" alt="" src="http://www.yesky.com/20020603/dinner.gif" width="402" /><br />?1、系l的cd?/td></tr></tbody></table><br /><br /><div fc05="" fc11="" nbw-blog="" ztag="" js-fs2"="" style="line-height: 25px; font-size: 14px; word-wrap: break-word; color: #8b8989; margin: 15px 0px; padding-top: 5px; padding-bottom: 5px; overflow: hidden; font-family: Arial, Helvetica, simsun, u5b8bu4f53; background-color: #000000;"><p style="margin: 0px 0px 10px; padding: 0px;">|上商店中的商品在名U、h(hun)格发生变化时Q必自动通知?x)员QJava的API为我们提供了Observer接口和ObservablecL实现所谓观察者模式?br />Observable(可观察者)cd许在自n发生改变Ӟ通知其它对象Q实现接口ObserverQ观察者)?/p><p style="margin: 0px 0px 10px; padding: 0px;">下面是一个可观察者(产品c)Q?br />import java.util.*;<br />public class product extends Observable{ <br />   private String name;////产品?br />   private float price;////h</p><p style="margin: 0px 0px 10px; padding: 0px;">   public String getName(){ return name;}<br />   public void setName(String name){<br />    this.name=name;<br />   ////讄变化?nbsp;<br />    setChanged();<br />    notifyObservers(name);////通知观察?/p><p style="margin: 0px 0px 10px; padding: 0px;">   }   </p><p style="margin: 0px 0px 10px; padding: 0px;">   public float getPrice(){ return price;}<br />   public void setPrice(float price){<br />    this.price=price;<br />   ////讄变化?br />    setChanged();<br />    notifyObservers(new Float(price));</p><p style="margin: 0px 0px 10px; padding: 0px;">   }</p><p style="margin: 0px 0px 10px; padding: 0px;">   ////以下可以是数据库更新 插入命o.<br />   public void saveToDb(){<br />   System.out.println("saveToDb");<br />    }</p><p style="margin: 0px 0px 10px; padding: 0px;">}</p><p style="margin: 0px 0px 10px; padding: 0px;">下面是两个观察者:(x)<br />import java.util.*;<br />public class NameObserver implements Observer{</p><p style="margin: 0px 0px 10px; padding: 0px;">   private String name=null;<br />   public void update(Observable obj,Object arg){<br />     if (arg instanceof String){<br />      name=(String)arg;<br />      ////产品名称改变值在name?br />      System.out.println("NameObserver :name changet to "+name);</p><p style="margin: 0px 0px 10px; padding: 0px;">     }</p><p style="margin: 0px 0px 10px; padding: 0px;">      }<br />   }</p><p style="margin: 0px 0px 10px; padding: 0px;">import java.util.*;<br />public class PriceObserver implements Observer{<br />   private float price=0;<br />   public void update(Observable obj,Object arg){<br />     if (arg instanceof Float){</p><p style="margin: 0px 0px 10px; padding: 0px;">      price=((Float)arg).floatValue();<br />  <br />      System.out.println("PriceObserver :price changet to "+price);</p><p style="margin: 0px 0px 10px; padding: 0px;">     }</p><p style="margin: 0px 0px 10px; padding: 0px;"><br />   }</p><p style="margin: 0px 0px 10px; padding: 0px;">}<br />下面是测试类Q?br />public class Test {</p><p style="margin: 0px 0px 10px; padding: 0px;">   public static void main(String args[]){<br />    Product product=new Product();<br />    NameObserver nameobs=new NameObserver();<br />    PriceObserver priceobs=new PriceObserver();</p><p style="margin: 0px 0px 10px; padding: 0px;">    ////加入观察?br />    product.addObserver(nameobs);<br />    product.addObserver(priceobs);</p><p style="margin: 0px 0px 10px; padding: 0px;">    product.setName("applet");<br />    product.setPrice(9.22f);</p>   }<br />}</div><div style="color: #8b8989; font-family: Arial, Helvetica, simsun, u5b8bu4f53; font-size: 12px; line-height: normal; background-color: #000000;"></div><div style="color: #8b8989; font-family: Arial, Helvetica, simsun, u5b8bu4f53; font-size: 12px; line-height: normal; background-color: #000000;"></div><div style="color: #8b8989; font-family: Arial, Helvetica, simsun, u5b8bu4f53; font-size: 12px; line-height: normal; background-color: #000000;"></div><div style="color: #8b8989; font-family: Arial, Helvetica, simsun, u5b8bu4f53; font-size: 12px; line-height: normal; background-color: #000000;"><div></div></div><div tbar="" fc03="" clearfix"="" style="zoom: 1; margin: 5px 0px; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; text-align: right; color: #c31010; line-height: 20px; font-family: Arial, Helvetica, simsun, u5b8bu4f53; font-size: 12px; background-color: #000000;"><div style="height: 24px; line-height: 24px;"><div rdif"="" style="float: left; height: 24px;"></div></div></div><p> </p></div><img src ="http://m.tkk7.com/qileilove/aggbug/392774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/qileilove/" target="_blank">其自然EVO</a> 2012-12-11 11:51 <a href="http://m.tkk7.com/qileilove/archive/2012/12/11/392774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学设计模式-单例模式http://m.tkk7.com/qileilove/archive/2012/12/07/392604.html其自然EVO其自然EVOFri, 07 Dec 2012 06:55:00 GMThttp://m.tkk7.com/qileilove/archive/2012/12/07/392604.htmlhttp://m.tkk7.com/qileilove/comments/392604.htmlhttp://m.tkk7.com/qileilove/archive/2012/12/07/392604.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/392604.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/392604.html概念Q?/span>
  java中单例模式是一U常见的设计模式Q?/span>单例模式分三U:(x)懒汉式单例、饿汉式单例、登记式单例三种?br />哈哈 我们可以q样?屌丝单例模式Q懒汉式屌丝单例Q饿汉式屌丝单例Q登记式屌丝单例?br />
  单例模式有一下特点:(x)
  1、单例类只能有一个实例?span style="margin: 0px; padding: 0px;">
  2、单例类必须自己自己创徏自己的唯一实例?span style="margin: 0px; padding: 0px;">
  3、单例类必须l所有其他对象提供这一实例?br />

单例模式保某个cd有一个实例,而且自行实例化ƈ向整个系l提供这个实例?/span>在计机pȝ中,U程池、缓存、日志对象、对话框、打印机、显卡的驱动E序对象常被设计成单例。这些应用都或多或少h资源理器的功能。每台计机可以有若q个打印机,但只能有一?/span>Printer SpoolerQ以避免两个打印作业同时输出到打印机中。每台计机可以有若q通信端口Q系l应当集中管理这些通信端口Q以避免一个通信端口同时被两个请求同时调用。MQ选择单例模式是Z避免不一致状态,避免政出多头?/span>

首先看一个经典的单例实现?br />

public class Singleton {

    private static Singleton uniqueInstance = null;

 

    private Singleton() {

       // Exists only to defeat instantiation.

    }

 

    public static Singleton getInstance() {

       if (uniqueInstance == null) {

           uniqueInstance = new Singleton();

       }

       return uniqueInstance;

    }

    // Other methods...

}

Singleton通过构造方法限定ؓ(f)private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()Ҏ(gu)讉K。(事实上,通过Java反射机制是能够实例化构造方法ؓ(f)private的类的,那基本上?x)所有的Java单例实现失效?/strong>此问题在此处不做讨论Q姑且掩耳盗铃地认ؓ(f)反射机制不存在。)

但是以上实现没有考虑U程安全问题。所谓线E安全是指:(x)如果你的代码所在的q程中有多个U程在同时运行,而这些线E可能会(x)同时q行q段代码。如果每ơ运行结果和单线E运行的l果是一L(fng)Q而且其他的变量的g和预期的是一L(fng)Q就是线E安全的。或者说Q一个类或者程序所提供的接口对于线E来说是原子操作或者多个线E之间的切换不会(x)D该接口的执行l果存在二义?/span>,也就是说我们不用考虑同步的问题。显然以上实现ƈ不满线E安全的要求Q在q发环境下很可能出现多个Singleton实例?br />

public class TestDiaoSiStream {
     private String DiaoSiname;
     public String getDiaoSiname() {
         return DiaoSiname;
     }
     public void setDiaoSiname(String DiaoSiname) {
         this.DiaoSiname = DiaoSiname;
     } 
     //该类只能有一个实?/div>
     private TestDiaoSiStream(){}    //U有无参构造方?/div>
     //该类必须自行创徏
     //?U方?/div>
     /*private static final TestDiaoSiStream ds=new TestDiaoSiStream();*/
     private static TestDiaoSiStream ds1=null;
     //q个cd自动向整个pȝ提供q个实例对象
     public static TestDiaoSiStream getTestDiaoSiTest(){
         if(ds1==null){
             ds1=new TestDiaoSiStream();
         }
         return ds1;
     }
     public void getInfo(){
         System.out.println("output message "+DiaoSiname);
     }
 }

public class TestMain {
     public static void main(String [] args){
         TestDiaoSiStream  ds=TestDiaoSiStream.getTestDiaoSiTest();
         ds.setDiaoSiname("奶娃");
         System.out.println(ds.getDiaoSiname());
         TestDiaoSiStream ds1=TestDiaoSiStream.getTestDiaoSiTest();
         ds1.setDiaoSiname("奶娃");
         System.out.println(ds1.getDiaoSiname());
         ds.getInfo();
         ds1.getInfo();
         if(ds==ds1){
             System.out.println("创徏的是同一个屌丝实?);
         }else if(ds!=ds1){
             System.out.println("创徏的不是同一个屌丝实?);
         }else{
             System.out.println("application error");
         }
     }
 }

q行l果Q?br style="margin: 0px; padding: 0px;" />  奶娃
  奶娃
  output message 奶娃
  output message 奶娃
  创徏的是同一?span style="color: #000000; font-family: 宋体; line-height: 20.066667556762695px; text-indent: 28px;">屌丝
实例

l论Q由l果可以得知单例模式Z个面向对象的应用E序提供了对象惟一的访问点Q不它实现何种功能Q?span style="margin: 0px; padding: 0px; color: #800000;">整个应用E序都会(x)同n一个实例对?/span>?/span>

1.饿汉式单例类

//饿汉式单例类.在类初始化时Q已l自行实例化 
 public class Singleton1 {
     //U有的默认构造子
     private Singleton1() {}
     //已经自行实例?nbsp;
     private static final Singleton1 single = new Singleton1();
     //静态工厂方?nbsp;
     public static Singleton1 getInstance() {
         return single;
     }
 }

2.懒汉式单例类
//懒汉式单例类.在第一ơ调用的时候实例化 
 public class Singleton2 {
     //U有的默认构造子
     private Singleton2() {}
     //注意Q这里没有final    
     private static Singleton2 single=null;
     //静态工厂方?nbsp;
     public synchronized  static Singleton2 getInstance() {
          if (single == null) {  
              single = new Singleton2();
          }  
         return single;
     }
 }
3.登记式单例类

import java.util.HashMap;
 import java.util.Map;
 //登记式单例类.
 //cMSpring里面的方法,类名注册,下次从里面直接获取?/div>
 public class Singleton3 {
     private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
     static{
         Singleton3 single = new Singleton3();
         map.put(single.getClass().getName(), single);
     }
     //保护的默认构造子
     protected Singleton3(){}
     //静态工厂方?q还此类惟一的实?/div>
     public static Singleton3 getInstance(String name) {
         if(name == null) {
             name = Singleton3.class.getName();
             System.out.println("name == null"+"--->name="+name);
         }
         if(map.get(name) == null) {
             try {
                 map.put(name, (Singleton3) Class.forName(name).newInstance());
             } catch (InstantiationException e) {
                 e.printStackTrace();
             } catch (IllegalAccessException e) {
                 e.printStackTrace();
             } catch (ClassNotFoundException e) {
                 e.printStackTrace();
             }
         }
         return map.get(name);
     }
     //一个示意性的商业Ҏ(gu)
     public String about() {    
         return "Hello, I am RegSingleton.";    
     }    
     public static void main(String[] args) {
         Singleton3 single3 = Singleton3.getInstance(null);
         System.out.println(single3.about());
     }
 }



其自然EVO 2012-12-07 14:55 发表评论
]]>跟屌丝学设计模式之责任链模式http://m.tkk7.com/qileilove/archive/2012/12/06/392531.html其自然EVO其自然EVOThu, 06 Dec 2012 03:19:00 GMThttp://m.tkk7.com/qileilove/archive/2012/12/06/392531.htmlhttp://m.tkk7.com/qileilove/comments/392531.htmlhttp://m.tkk7.com/qileilove/archive/2012/12/06/392531.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/392531.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/392531.html阅读全文

其自然EVO 2012-12-06 11:19 发表评论
]]>
java设计模式-桥接模式Q屌丝男学设计模式)http://m.tkk7.com/qileilove/archive/2012/12/05/392498.html其自然EVO其自然EVOWed, 05 Dec 2012 08:21:00 GMThttp://m.tkk7.com/qileilove/archive/2012/12/05/392498.htmlhttp://m.tkk7.com/qileilove/comments/392498.htmlhttp://m.tkk7.com/qileilove/archive/2012/12/05/392498.html#Feedback0http://m.tkk7.com/qileilove/comments/commentRss/392498.htmlhttp://m.tkk7.com/qileilove/services/trackbacks/392498.html本文介绍设计模式中的桥接Q?a target="_self" style="color: #336699; text-decoration: initial;">BridgeQ模式的概念Q用法,以及实际应用中怎么样?a target="_self" style="color: #336699; text-decoration: initial;">桥接模式q行开发?/span>

Bridge模式的概?/strong>

Bridge 模式是构造型的设计模式之一。Bridge模式Zcȝ最设计原则,通过使用装Q聚合以及承等行ؓ(f)来让不同的类承担不同的责仅R它的主要特Ҏ(gu)把抽象(abstractionQ与行ؓ(f)实现QimplementationQ分d来,从而可以保持各部分的独立性以及应对它们的功能扩展?br />

Bridge模式的应用场?/strong>

面向对象的程序设计(OOPQ里有类l承Q子cȝ承父c)的概念,如果一个类或接口有多个具体实现子类Q如果这些子cd有以下特性:(x)
- 存在相对q列的子cd性?br />- 存在概念上的交叉?br />- 可变性?br />我们可以用Bridge模式来对其进行抽象与具体Q对相关c进行重构?br />

ZҎ(gu)理解Q我们D例说明一下,比如屌丝QDiaoSiQ,假设?个子c,男屌丝类QManDiaoSiQ与奛_丝类QWomanDiaoQ,它们有[Ih矮]q个动作行ؓ(f)Q通过不同Ih矮特征的讄Q可以将它们讄为比如ؓ(f)拥有黑木耳男屌丝或(拥有撸管王的奛_丝)Q和拥有紫木耳男屌丝或(拥有撸神的女屌丝Q的各种屌丝?br />q样Q不是黑木耳男屌丝q是紫木耳男屌丝Q又或是有撸王的女屌丝q是有撸的奛_丝,它们都可以是屌丝cȝ子类Q而且Q?br />- 存在相对q列的子cd性。屌丝的U类Q与屌丝Ih矮的规格是屌丝的2个ƈ列的属性,没有概念上的重复?br />- 存在概念上的交叉。不是男屌丝还是女屌丝Q都是穷挫矮Q黑I丑的屌丝?br />- 可变性。除了男屌丝Q女屌丝之外Q可能还有h妖屌丝;除了有黑木耻I撸管王)与木耻I撸神Q特征的屌丝之外Q还可能有黑木耻I撸圣Q的屌丝{等?/p>

q样一来,我们怎么来设计屌丝类呢?

Ҏ(gu)一

通过l承设计所有可能存在的子类。可能我们会(x)惛_下面的这U承关p:(x)
屌丝ȝQDiaoSi
屌丝子类 - 按种cdc:(x)ManDiaoSiQ?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao
屌丝子类 - 按特征分c:(x)拥有黑木耳男屌丝Q拥?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的奛_?/span>Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳男屌丝Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有撸神的女屌丝
q样讄特征q个动作q各个子类加以实现?/p>

但如果以后需要增加一U?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">人妖屌丝QGuyDiaoSiQ,以及增加一个特征规格黑木耻I需要实现的子类会(x)有:(x)
拥有黑木耳男屌丝Q拥?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的奛_?/span>Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳男屌丝Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有撸神的女屌丝  拥有紫黑木耳男屌丝 拥有撸管王的人妖屌丝 拥有紫黑木耳h妖屌?nbsp;拥有紫木耳h妖屌?/span>
 {等?br />也就是说Q这U设计方法,子类数目随几何U数增长?br />而且Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有黑木耳男屌丝
Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳h妖屌?/span>的特征规格相同,它们的特征设|动作应该是一L(fng)Q但现在把它们分成不同的子类Q难以避免执行重复的动作行ؓ(f)?/p>

 

Ҏ(gu)?/strong>

分别为男屌丝以及奛_丝实现设|不同特征的Ҏ(gu)
屌丝ȝQDiaoSi
屌丝子类Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">ManDiaoSiQ?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao

然后在男屌丝c里分别提供黑木耻I撸管王)以及紫木耻I撸神Q特征的讄Ҏ(gu)Q?br />ManDiaoSi extends DiaoSi
 {
    public setFeatures黑木?);
    public setFeatures紫木?);
}

在女屌丝c里也分别提供撸王以及撸神特征的设|方法:(x)
WomanDiao extends DiaoSi
 {
    public setFeatures撸管?);
    public setFeatures撸神();
}

q种情况Q子cȝ数量是被控制了。但一斚wQ如果每增加一U特征规|需要修Ҏ(gu)有的屌丝子类Q另一斚wQ即使特征的讄行ؓ(f)一P但是不同的屌丝子cd需要提供完全一L(fng)Ҏ(gu)?br />

在实际的应用开发中Q以?U方法都?x)造成q一发而动全nQ而且?x)存在大量的重复代码?/p>

Bridge模式可以很好的解册c问题?br />Client
    Bridge模式的用?br />Abstraction
    抽象cL口(接口或抽象类Q?br />    l护对行为实玎ͼImplementorQ的引用
Refined Abstraction
    Abstraction子类
Implementor
    行ؓ(f)实现cL?(Abstraction接口定义了基于Implementor接口的更高层ơ的操作)
ConcreteImplementor
    Implementor子类

 

Bridge模式的应用范?/strong>

我们来看看怎么应用Bridge模式来设计汽车类?/p>

抽象 - Abstractionc:(x)屌丝cd其子c:(x)
屌丝ȝQDiaoSi
屌丝子类 - 按种cdc:(x)ManDiaoSiQ?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao
屌丝子类 - 按特征分c:(x)拥有黑木耳男屌丝Q拥?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的奛_?/span>Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳男屌丝Q?span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有撸神的女屌丝

行ؓ(f)实现 - ImplementorQ屌丝特征设|的行ؓ(f)cd子类
 setFeaturesQ屌丝特征的讄接口
 setFeatures黑木?);
setFeatures紫木?);

代码Q?/p>

package ITfarmer.designpatterns.study.bridge;

//试

public class Client
{
    public static void main( String[] argv )
    {
        Features 黑木? new  男屌丝特?);

         Features ?/span>木? new  奛_丝特?/span>();
       
        DiaoSi 拥有黑木耳的男屌? new  ManDiaoSi( 黑木?nbsp;);
         DiaoSi 拥有紫木耳的男屌? new  ManDiaoSi( 紫木?nbsp;);
        拥有黑木耳的男屌?setFeatures();
        拥有紫木耳的男屌?setFeatures();
       
        DiaoSi 拥有黑木耳的奛_? new WomanDiao( 黑木?);
        Vehicle 拥有紫木耳的奛_? new WomanDiao( 紫木?);
      拥有黑木耳的奛_?setFeatures();
        拥有紫木耳的奛_?setFeatures();
       
    }
}

package ITfarmer.designpatterns.study.bridge;


 *
 * @author
 * @since 2012/12/05
 */
public abstract class DiaoSi
{
    private Features features;

    Vehicle( Features features)
    {
        this.setFeatures features);
    }
   
    public abstract void setFeatures();

    public void setFeaturesFeatures features)
    {
        this.featuresfeatures;
    }

    public Features getFeatures()
    {
        return  features;
    }
}

package ITfarmer.designpatterns.study.bridge;

//Abstraction子类Q这里ؓ(f)屌丝抽象cȝ子类

public class ManDiaoSi extends DiaoSi
{
    public ManDiaoSi (Features features
)
    {
        super( features
 );
    }
   
    @Override
    public void setFeatures()
    {
        System.out.print("男屌丝的特征: ");
        getFeatures.setFeatures();
    }
}

package ITfarmer.designpatterns.study.bridge;

//Abstraction子类Q这里ؓ(f)屌丝抽象cȝ子类

public class WomanDiaoSi extends DiaoSi
{
    public WomanDiaoSi ( Features features
 )
    {
        super( features
);
    }

    @Override
    public void  setFeatures()
    {
        System.out.print("奛_丝的特征: ");
        getFeatures().seFeatures();
    }

}

package ITfarmer.designpatterns.study.bridge;

//屌丝cȝ行ؓ(f)接口

public interface Features
{
    public void setFeatures();
}

package ITfarmer.designpatterns.study.bridge;

/** ConcreteImplementor */
//行ؓ(f)实现子类

public class 男屌丝特?implements Features
{

    public void setFeatures()
    {
        System.out.println("黑木?或?撸管?);
    }   
   
}

package ITfarmer.designpatterns.study.bridge;

/** ConcreteImplementor */
//行ؓ(f)实现子类

public class  奛_丝特?nbsp;implements Features
{

    public void setFeatures()
    {
        System.out.println("黑木?或?撸管?);
    }   
   
}

结QBridge模式是一U抽象与其实现相分离的模式。它主要应用于:(x)当事物是一l变化量Q和对这些事物的操作Ҏ(gu)(实现)也是一l变化量的情况,也就是说它们都是多变的?/span>

 



其自然EVO 2012-12-05 16:21 发表评论
]]>
վ֩ģ壺 57paoƵѲ| ɫѹۿ| ӯӯӰԺƵۿһ| ˶վ| þƵۿ| av³˿һ| þƵ99| ӰԺ߹ۿ| ߹ۿѸƵ| һ͵| ŷëƬAƵ޷| ɫaƬѿ| һ߹ۿƷ| ѹۿ| ޾ƷŮþþþ9999| ѹƵС| Ůۺһ| ѹʵj߹ۿ| AëƬëƬ| þþþAVվ| ëƬ߹ۿվ| պa| ޾ƷAAƬѽ | ޾ƷƵ߹ۿ| ԶƵ߹ۿѲ| ޾Ʒ㶮| һëƬ߲Ųշ| 99ƷƷ| 2020޾Ʒר| ޹ƷëƬa| 9ᆱƷƵ| Ļ| A޾VƷ| 鶹Ƶѹۿ| 2018Ƶ| ŷһ| ĻӰԺѲ| պѵƵ߹ۿ㽶| պAVһ | Ұ߹ۿ3 | ƷۺרĻѲ |