﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-qileilove-随笔分类-设计模式学习</title><link>http://www.blogjava.net/qileilove/category/53091.html</link><description>不想做屌丝的码农，不是好项目经理！屌丝生涯从此开始！</description><language>zh-cn</language><lastBuildDate>Thu, 13 Mar 2014 12:28:48 GMT</lastBuildDate><pubDate>Thu, 13 Mar 2014 12:28:48 GMT</pubDate><ttl>60</ttl><item><title>一个用于网站自动化测试的生态系统实现</title><link>http://www.blogjava.net/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://www.blogjava.net/qileilove/archive/2014/03/13/410968.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/410968.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2014/03/13/410968.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/410968.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/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;">　　这是我在从事网站<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;生态系统&#8221;。&#8220;生态系统&#8221;这个概念是我从公司的前辈身上学到的，他一直以来都认为自动化测试人员不应仅仅局限于编写测试代码，还应该让整个自动化测试的过程（测试代码的持续集成、分发、执行等）都自动化，形成一个&#8220;系统&#8221;，这个系统的自动化程度越高，自动化测试人员就越省力。</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;">　　这里我画了一张示意图：</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 href="http://www.51testing.com/batch.download.php?aid=44896" 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;">　　之所以称之为&#8220;生态系统&#8221;，是因为建成之后需要的人为干涉很少，其余的时间都是系统内部循环运作。作为自动化测试人员的你只需要提交代码，之后便可以在AutomationDashboard上看到运行的结果了，其余的事情都由系统内部消化。当然，结果的分析还是需要人来完成，机器还没有聪明到可以灵活分析出各种各样让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;">　　我们可以把整个系统看作一个黑盒子，那么上面的图可以变成：</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 href="http://www.51testing.com/batch.download.php?aid=44897" 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;">　　实际上这里画的人不仅限于自动化测试人员，也可以是：</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;">　　（1）产品的管理者，比如产品经理需要从自动化回归测试知道这次release有无推迟风险；</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;">　　（2）团队的管理者，比如开发经理、QA经理需要从自动化的daily/weekly regression知道最近的代码质量如何；</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;">　　（3）开发人员，他们也许会想通过quick regression（提交的产品代码被部署到测试环境之后运行的测试）知道自己刚提交的代码有没有破坏系统的基本功能；</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;">　　（4）其他帮忙做自动化测试的开发人员、刚刚开始<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>编写自动化测试代码的手动测试人员，他们不必关心生态系统的内部实现。</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;">　　说完概念，接下来该说说具体实现了。我这里讲的是我认为最适合我所测试的产品的实现，工具不止一种，方式不止一种。Jenkins可以用TeamCity或其它CI替换，git也可以是svn或tfs，AutomationDahsboard可以用.NET、SpringMVC、ROR等等实现，运行测试的slave可以是Windows/Linux/Mac（土豪！），总之选择一种最适合你所测试的产品的实现。还有一点就是自动化测试代码是用关键字驱动思想实现的，这是另外一个话题了，有时间另外写篇文。</div><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;">　　1、SCM（Source Code Management）。我选的是git，可以是git服务器（公司自己搭建了一个git&nbsp;<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>），也可以是一个bare repo（http://www.saintsjd.com/2011/01/what-is-a-bare-git-repository/） 。</div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">　　2、CI（continuous integration）。我选的是部署方便、插件丰富的Jenkins。</div><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;">　　（1）从git上取出代码，build（.NET对应msbuild，如果是ruby则不用build了，直接部署即可）；</div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">　　（2）把build好的*.dll部署（这里即是拷贝）到所有的slave上；</div><div style="word-break: break-all; line-height: normal !important; margin: 10px 0px;">　　（3）启动或停止所有slave上的AutomationService（后面还会讲到AutomationService），从而控制测试的执行。<span style="font-size: 11.818181991577148px; line-height: 21.60000228881836px;">我在Jenkins的这些个job配置起来还是比较繁琐的，要细讲又可以另外写一篇文了。这里就特别提到两个很实用的插件吧：</span></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　（1）Parameterized Trigger Plugin（https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin）：可以在一个build step中触发其它project的build。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44898" 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&#8221;选项，勾上的话Jenkins就能在所有trigger的project完成build之后（而非仅仅trigger其它project的build，不等它们完成就继续下一个build step）再继续下一个build step，做到真正的依次执行每个build step。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44899" 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;">　　（2）NodeLabel Parameter Plugin（https://wiki.jenkins-ci.org/display/JENKINS/NodeLabel+Parameter+Plugin）：在所有&#8220;Possible nodes&#8221;标有指定标签（&#8220;Label&#8221;）的Jenkins节点（就是Jenkins master或Jenkins slave）上触发指定project（被触发的project是参数化的）。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　比如我有一个project叫&#8220;StartClassicROLATServiceOnAllNodes&#8221;，它有一个build step是这样设定的：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44900" 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;">　　再来看看&#8220;StartClassicROLATServiceOnASingleNode&#8221;这个project的设定：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44901" 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;">　　这个project有一个Node类型的参数，参数名&#8220;NodeX&#8221;与之前Label Factory中的&#8220;NodeX&#8221;对应，&#8220;Possible nodes&#8221;选的是&#8220;ALL&#8221;，那么列出的所有node（master、10.107.122.152、10.107.122.153、10.107.122.154）都在判断范围之内（判断其是否有&#8220;Node&#8221;标签，有则执行project）。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　另外，列出的所有node我都为其加了一个&#8220;Node&#8221;标签。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44902" 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;">　　这样，当我trigger &#8220;StartClassicROLATServiceOnAllNodes&#8221;之后，就会在master、10.107.122.152、10.107.122.153、10.107.122.154这4个node上同时执行&#8220;StartClassicROLATServiceOnASingleNode&#8221;。<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、AutomationDashboard，这里姑且译作&#8220;自动化测试控制面板&#8221;吧。</strong>实际上它应该和Jenkins一起并称控制面板，不过因为Jenkins有API可以调用，所以想做的画两者也是可以统一成一个web界面的。这个dashboard完全是用.NET+IIS+SQLServer一点点从数据库设计构建、数据访问层、业务层、表现层做起来的，要细讲&#8230;&#8230;额&#8230;&#8230;又会是另外一篇文了（Oh man, not again!）。反正我觉得，虽然我是做自动化测试工作的，但不应该把自己局限于测试。为了更好地进行自动化测试，开发网站、安装配置虚拟机以及其它要用到的工具，都应该抽时间去学习、掌握。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　好，来说说这个dashboard。这里只讲两个主要组成部分，一个网站（以下简称dashboard）、一个Windows Service（以下简称ATService）和一个console application（以下称ConsoleRunner）：</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;">（1）dashboard，它的主要功能：</strong></div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　a、展示测试的运行状况：有多少正在运行/执行完毕，分别在哪台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的job，间接控制测试的执行。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　c、展示测试的结果：发生错误的是哪个case、出错时间、错误信息、代码回溯（stack trace）、甚至可以包含一张出错时的截图。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　主要界面如下：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;">　　a、Summary，顾名思义是汇总信息，case有多少pass多少fail、case按分类每一类有多少等等。（其实这里我少做了一张很重要的图，就是coverage饼状图）</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44903" 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、Queue，测试队列，包含当前正在运行的、运行完的、等待运行的test fixture或test case（依据测试工具的不同，NUnit、JUnit、RSpec等，fixture的叫法可能不同，总之就是包含多个test case的集合）。可以启动、停止、终止（终止之后可以清空）测试执行或清空当前队列。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44904" 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、TestCase，生态系统中的所有测试用例会展示在这里，可以看到它们最后一次执行的时间和状态（pass/fail），点击某条case可以跳转到该条case的所有test result。可以按状态（pass/fail/other）筛选用例，可以勾选部分用例重新执行、或重新执行所有fail的case。&#8220;Reload Test Cases&#8221;主要是考虑到*.dll文件中的test case可能会在某次部署之后发生变化，需要重新加载。不过后来我修改了Jenkins里的job在每次部署之后都自动重新加载，所以这个按钮其实没什么用了。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44905" 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、TestSuite，包含多个fixture的集合是一个suite。勾选多个suite点击&#8220;Run Suite&#8221;即可把这些suite中包含的fixture添加到Queue。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44906" 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;">　　这里的suite是对NUnit中的Category的一个补充，点击&#8220;New Suite&#8221;你可以任意选择fixture来组成自己想要的suite：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44907" 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、TestResult，展示所有test case的运行结果，可以按test case id进行筛选，点击TC#这一列的id就只显示这条case的结果。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44908" 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;">　　点右边的蓝色&#8220;i&#8221;图标可以跳到这条结果的详细页面，截图功能暂未启用，根据RunnerMessage和RunnerStackTrace可以知道报错的代码位置，进而尝试重现问题。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; font-size: 11.818181991577148px;"><a href="http://www.51testing.com/batch.download.php?aid=44909" 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;">　（2）ATService。这个Windows Service（slave都是Windows，稍后会讲）被安装到了每个slave上，用以向dashboard询问&#8220;现在有没有分配给我的test fixture/case？&#8221;，如果有且当前slave空闲的话就抓过来运行，运行完毕汇报结果。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　还记得Queue（队列）吧？无论你在TestCase还是TestSuite页面挑选了test case/suite想要运行，都只是把它们添加到队列当中（准确地说就是往Queue这张数据库表中INSERT记录），而不会给它们分配slave。只有当Jenkins启动了slave上的ATService之后，ATService才会去Queue表中自己抓取（就是打上标记说这条fixture/case已经有主了，其它slave就不会再去抓）还没有运行过且没有分配有slave的test fixture/case。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　（3）ConsoleRunner，最开始的那个图中没有画出来。这个console程序主要供Jenkins调用。Jenkins不是可以让job定时运行么？正好，定时调用这个console application，传几个参数，就可以在指定时间往Queue里填充fixture/case，然后再启动ATService开始执行测试。这样就能实现quick/daily/weekly/full regression的无人值守运行了。</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上运行测试：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　（1）公司IT一般只提供Windows操作系统的虚拟机</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　（2）产品在Windows上的用户占绝大多数（其实这个有点废话，桌面操作系统Windows依然是世界王者。诚然，我自己业余时用Linux做开发，Mac在国内外也是相当流行的，但GoogleAnalytics显示的统计结果就是大部分访问都来自Windows。什么，你说iOS/Android？额&#8230;&#8230;移动端现在仍然是产品的短板&#8230;&#8230;）</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设定（http://code.google.com/p/selenium/wiki/AdvancedUserInteractions#Native_events_versus_synthetic_events）。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　关于浏览器，Firefox、Chrome、IE皆可，webdriver的浏览器兼容性已经很不错了。浏览器兼容性是个有点头疼的问题，想支持很多浏览器的话有时会增加很多开发、测试成本，我一般在Firefox上跑就足够了。什么？数字？马桶？企鹅？您想多了，selenium官方不支持。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　你能找到多少台slave来执行测试？多多益善哦！找不到那么多实体机就自己配虚拟机吧，分布式运行可以给你的自动化测试生态系统装上火箭！在更短的时间内运行完更多测试，从而更快地从测试中获得反馈！</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　嗯，差不多就这么多了。还有很多细节就留在之后的文中再说了。自我感觉这个生态系统还是有很多可以完善、增加的功能，而且这个实现方式、运作机制可能也并非适用于你所测试的产品，不过现在对于我测的产品来说是够用的了。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　不管怎样实现，我想表达的核心观点是：</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　做自动化测试不要局限于自动化测试代码的编写，我们要自动化的不仅仅是manual test case，还应包括整个automation test的process！测试代码持续集成、部署（分发）、执行、结果展示，自动化的环节越多、越彻底，为你节约的时间就越多，你可以用这些节约的时间做更有意义的事情。人类发明计算机，用代码编写程序，其实就是一种自动化的过程。以前要靠手工劳动完成的现在都交给电脑做了&#8212;&#8212;服务器不正是勤勤恳恳地重复执行着我们写好的程序么？构建自动化测试生态系统是同样的道理，因为机器能比人更可靠地完成重复劳动。</div><div style="word-break: break-all; line-height: 21.60000228881836px; margin: 10px 0px; color: #333333; font-size: 11.818181991577148px;">　　如果你还在手动拷贝*.dll，还需要打开NUnit手动执行测试，还在1台机器上运行测试，那么，现在就是该提高生产力的时候了！</div></a></div></div></div><img src ="http://www.blogjava.net/qileilove/aggbug/410968.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2014-03-13 11:34 <a href="http://www.blogjava.net/qileilove/archive/2014/03/13/410968.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>操作系统中内存管理的页面置换算法</title><link>http://www.blogjava.net/qileilove/archive/2013/11/01/405876.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Fri, 01 Nov 2013 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2013/11/01/405876.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/405876.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2013/11/01/405876.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/405876.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/405876.html</trackback:ping><description><![CDATA[<div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　<strong style="word-break: break-all; line-height: normal !important; ">考虑下述页面走向：</strong></div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　1，2，3，4，2，1，5，6，2，1，2，3，7，6，3，2，1，2，3，6</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　当内存块数量分别为3时，试问FIFO、LRU、OPT这三种置换算法的缺页次数各是多少?</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　答：缺页定义为所有内存块最初都是空的，所以第一次用到的页面都产生一次缺页。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　<strong style="word-break: break-all; line-height: normal !important; ">当内存块数量为3时：</strong></div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; text-align: center; "><a href="http://www.51testing.com/batch.download.php?aid=42936" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important; "><img src="http://www.51testing.com/attachments/2013/10/14982672_201310291028121FEzB.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.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　发生缺页中断的次数为16。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　在FIFO算法中，先进入内存的页面被先换出。当页6要调入时，内存的状态为4、1、5，考查页6之前调入的页面，分别为5、1、2、4，可见4为最先进入内存的，本次应换出，然后把页6调入内存。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; text-align: center; "><a href="http://www.51testing.com/batch.download.php?aid=42937" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important; "><img src="http://www.51testing.com/attachments/2013/10/14982672_201310291028122yOi9.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.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　发生缺页中断的次数为15。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　在LRU算法中，最近最少使用的页面被先换出。当页6要调入时，内存的状态为5、2、1，考查页6之前调入的页面，分别为5、1、2，可见2为最近一段时间内使用最少的，本次应换出，然后把页6调入内存。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; text-align: center; "><a href="http://www.51testing.com/batch.download.php?aid=42938" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important; "><img src="http://www.51testing.com/attachments/2013/10/14982672_201310291028123DBHP.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.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　发生缺页中断的次数为11。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　在OPT算法中，在最远的将来才被访问的页面被先换出。当页6要调入时，内存的状态为1、2、5，考查页6后面要调入的页面，分别为2、1、2、&#8230;，可见5为最近一段时间内使用最少的，本次应换出，然后把页6调入内存。</div><div style="word-break: break-all; line-height: 21.59375px; margin: 10px 0px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff; ">　　OPT算法因为要知道后面请求的页框，因此我觉得这个算法有个小小的bug,如果在某个请求中，若在该请求的页框之后的页框序列中至少存在一个和当前内存块中不匹配的页框，则按照内存块的顺序（从上往下）替换没有出现的页框。比如上面那个OPT例子。对于最后一个页框请求，因为6未命中，且6之后没有请求的序列，因此应该替换3，所以替换后的序列为6 ， 2 ，1 &nbsp; 当然，这只是针对做题而言。</div><img src ="http://www.blogjava.net/qileilove/aggbug/405876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2013-11-01 10:37 <a href="http://www.blogjava.net/qileilove/archive/2013/11/01/405876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>项目实战笔记之六：团队建设的三种境界</title><link>http://www.blogjava.net/qileilove/archive/2013/06/04/400153.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Tue, 04 Jun 2013 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2013/06/04/400153.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/400153.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2013/06/04/400153.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/400153.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/400153.html</trackback:ping><description><![CDATA[<p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　经过自己总结和项目经理们探讨，认为项目或部门团队建设可分为三个等级：</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><strong style="word-break: break-all; line-height: normal !important;">　　一、乌合之众，强权政治（新手）</strong></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　很多新手都会经历这样的过程，新组建的团队冲突不断，大家对当各种制度措施，报以反感。为保证执行力和项目成功，项目经理会选择强权压制，尤其是技术比较好的项目经理。大抵的逻辑是&#8220;我是老大并且我资深，要听我的&#8221;。最终的结果是大家对项目目标已经完全不感兴趣，一些冲突升级到个人情感冲突，项目经理左右突击，上蹿下跳，甚是辛苦，忙碌，确得不到大家的认可。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　此时的项目经理至少需要做到两点，才有可能进入下个阶段，用杰克韦尔奇的两句话概况：</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　1、&#8220;在你成为领导以前，成功只同自己的成长有关。当你成为领导以后，成功都同别人的成长有关。&#8221;</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　2、&#8220;世界上的每一个人都想得到发言权和尊严，而且也应当得到&#8221;</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　所谓&#8220;发言权&#8221;，是指人们希望有机会说出他们的思想，拥有自己的观点、看法、获得被倾听的感受，无论他们的国籍、性别、年龄或者文化背景如何。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　所谓&#8220;尊严&#8221;，是指人们本能地和自发地希望由于自己的<a href="" target="_self" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;"><u style="word-break: break-all;"><strong style="word-break: break-all;">工作</strong></u></a>、努力和个性而得到尊重。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　这个阶段之所以命名为乌合之众，是因为大家对团队根本没有归属感，甚至厌弃团队，期望团队得到解散，或者团队目标达成时，并没有取得成就的感觉，而是有终于熬过来的感触。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><strong style="word-break: break-all; line-height: normal !important;">　　二、尊重，民主社会 （老手）</strong></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　在经历过挫折或是老前辈们的谆谆教导后，新手往往都能进入这个阶段。当然有些厉害的人有时也会自己跳到这个阶段。但是这个阶段里的人，也有高下之分。在这个阶段的人，往往可以带团队时，往往可以做到：</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　1、尊重，言路开明</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　不把人当做机器。制定计划，措施时，都可以征求的大家意见，当然计划定下来后，执行时是不能含糊的。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　2、善用人才，培养人才</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　团队里有人才时，会使用授权等方式调用这些人的积极性，而不是幼稚的打压，并且在团队里没有人才时，能够积极选拔备选人员，并给予锻炼机会</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　3、分享荣誉</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　这个阶段的项目经理，在交流中，会摈弃掉&#8220;我怎么样，怎么样&#8221;，多使用&#8220;我们，我们团队怎么样&#8221;，尤其是在面对表扬和荣誉时。在项目组内也想方设法树立榜样，并且非常愿意这些人被自己的上级所获知，愿意为这些人谋个好前程。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　4、坦诚</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　坦诚是相处的长远之计，而忽悠，画大饼这些手段只能短期效应，并在长期上让自己的人格受损。关于这点项目经理大多做得程度不一，有时说出一些不开心的事，是需要勇气的，例如在绩效沟通时。但是这个阶段的项目经理都了解它重要性。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　5、团队信息透明</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　只有信息足够透明，大家才能够为项目出谋划策，才能有坦诚沟通的基础，大家才能对项目归属。&#8220;垄断信息，以显示自己领导的地位&#8221;是愚蠢的人才会干的事情</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　这个阶段之所以命名为民主社会，这个阶段的价值观是：民主计划，严格执行，有付出有回报，集体荣誉。第一个阶段到第二个阶段可能需要时间的积累，而第二个阶段到第三个阶段，有时却可望而不可达。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><strong style="word-break: break-all; line-height: normal !important;">　　三、激情，燃烧军团 （高手）</strong></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　激情团队的充分必要前提是，团队负责人是非常有激情的。这点很关键，一个打工者心态，没有把工作当成自己事业经营的人是不会带出有长久激情的团队。检视的原理：&#8220;看一下大家是不是为了同一个梦想而走到一起的&#8221;</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　要达成团队激情，至少具备以下几点：</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　1、老板风格，老板要有分享成功的决心，例如：股票，期权激励</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　2、企业文化，企业要有文化宣扬集体奋斗的精神，企业的使命价值观能够深入人心，得到强烈响应，此时企业的创新精神，将是从内而外的，从下而上的，大家集体思考，集体进步，集体创新。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　3、有激情的中层，公司中层是企业的中流砥柱，如果每个中层是有激情的，扩散开来的影响力是很大的，反之，则激情容易变成口号。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　这里典型的案例是sony的没落，从井深大的激情军团的消失，井深大倡导&#8221;工作保证本身就是一种强有力的激励&#8220;，把这种理念能够深植公司是多么可怕，激情可以创造出很多奇迹。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　约翰&#183;科特说过&#8220;如果你想建造一艘船，首先要做的不是去采集木材、加工木板和分派工作，而应该去唤起人们对广阔无垠大海的向往。&#8220; 管理者的本质是获得追随的人，一个企业，一个团队如果能够拥有一批愿意追随公司成长的人，所产生的正向能量是无比巨大的。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　这种境界的达到需要多方因素的促合，颇似于武侠里的天人合一，激情团队的管理将十分简单，保护这种激情，员工会很自主的进行自我管理。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">　　当然实际工作中，以上每个阶段不孤立存在，可能会存在一些阶段的中间体。</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;">相关链接：</p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><a href="http://www.51testing.com/?action-viewnews-itemid-846762" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;">项目实战笔记之一：高效会议的组织方法</a></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><a href="http://www.51testing.com/?action-viewnews-itemid-805590" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;">项目实战笔记之二：风险管理</a></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><a href="http://www.51testing.com/?action-viewnews-itemid-846763" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none;">项目实战笔记之三：时间估算的三步曲</a></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><a href="http://www.51testing.com/?action-viewnews-itemid-846838" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none;">项目实战笔记之四：团队建设（尊重）</a></p><p style="word-break: break-all; margin: 10px 0px; padding: 0px; line-height: 21.59375px; color: #333333; font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: #ffffff;"><a href="http://www.51testing.com/?action-viewnews-itemid-846906" target="_blank" style="word-break: break-all; color: #202859; text-decoration: none; line-height: normal !important;">项目实战笔记之五：里程碑管理</a></p><img src ="http://www.blogjava.net/qileilove/aggbug/400153.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2013-06-04 10:32 <a href="http://www.blogjava.net/qileilove/archive/2013/06/04/400153.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学习设计模式－抽象工厂模式</title><link>http://www.blogjava.net/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://www.blogjava.net/qileilove/archive/2012/12/21/393318.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/393318.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/21/393318.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/393318.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/393318.html</trackback:ping><description><![CDATA[<div><strong>1.3&nbsp;抽象工厂（Abstract Factory）模式<br /></strong>&nbsp;&nbsp;&nbsp; 抽象工厂模式可以向客户端提供一个接口，使得客户端在不必指定产品具体类型的情况下，创建多个产品族中的产品对象。这就是抽象工厂模式的用意。<br />&nbsp;&nbsp;&nbsp; 每个模式都是针对一定问题的解决方案。抽象工厂模式面对的问题是多产品等级结构的系统设计。<br />&nbsp;&nbsp;&nbsp; 在学习抽象工厂具体实例之前，应该明白两个重要的概念：产品族和产品等级。<br />&nbsp;&nbsp;&nbsp;   产品族：是指位于不同产品等级结构中，功能相关联的产品组成的家族。比如AMD的CPU和ADM芯片的主板，组成一个家族。Intel的CPU和 Intel芯片的主板，又组成一个家族。而这两个家族都来自于两个产品等级：CPU，主板。一个等级结构是由相同的结构的产品组成，示意图如下：</div><img alt="" src="http://www.blogjava.net/images/blogjava_net/qileilove/aaa1165334942718.png" height="332" width="508" /><br /><br /><br /><div><br />&nbsp;&nbsp;&nbsp; 理解这个产品结构是理解抽象工厂模式的关键所在，所以我不惜花费时间来画此图。如果领悟不到此图的含义，就无法区分工厂方法模式和抽象工厂模式的区别。<br />&nbsp;&nbsp;&nbsp; 从上图可以看出，抽象工厂模式的每个工厂创造出来的都是一族产品，而不是一个或者一组。组是可以随意组合的！其实两个就这点点差别，呵呵，估计现在你已经差不多明白了抽象工厂模式的含义。不废话了，看个例子，真相将大白于天下！<br />    <div><strong>1.3.1&nbsp;抽象工厂模式在农场中的实现</strong></div>  <div><br /><strong>1.3.1.1&nbsp;背景</strong></div>  <div><br />&nbsp;&nbsp;&nbsp;   聪明的农场主总是让自己的庄园越来越有价值，&#8220;农场&#8221;在经历了简单工厂模式和工厂模式后，不断的扩大生产。如今，再次面临新的大发展，一项重要的工作就是 引进塑料大棚技术，在大棚里种植热带（Tropical）和亚热带（Northern）的水果和蔬菜，用以满足市场需求，获取更大的利益。</div>  <div><br /><strong>1.3.1.2&nbsp;产品角色图</strong></div>  <div><br />&nbsp;&nbsp;&nbsp; 经过分析，对产品角色进行分析得出下图</div></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/qileilove/abb1165335033921.png" height="231" width="428" /><br /><br /><div>&nbsp;&nbsp;&nbsp; 经过分析，所谓的各个园丁其实就是工厂角色，而蔬菜和水果则是产品角色。将抽象工厂模式用于农场中，系统设计图如下：<br /><br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/qileilove/caa1165384624477.png" height="421" width="632" /><br /><br /><div>1.3.1.4.1&nbsp;抽象工厂：Gardener.java  <div>package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:Gardener.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:55:23<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 抽象工厂角色：工厂接口<br />&nbsp;*/<br />public interface Gardener {</div>  <div>&nbsp;&nbsp;&nbsp; public Fruit createFruit(String name);</div>      <div>1.3.1.4.2&nbsp;抽象水果产品：Fruit.java</div>  <div>package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:Fruit.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:54:15<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 抽象产品角色：水果接口<br />&nbsp;*/<br />public interface Fruit {<br />}</div>    <div>1.3.1.4.3&nbsp;抽象蔬菜产品：Veggie.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:Veggie.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:56:22<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 抽象产品角色：蔬菜接口<br />&nbsp;*/<br />public interface Veggie {<br />}</div>    <div>1.3.1.4.4&nbsp;热带水果：TropicalFruit.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:TropicalFruit.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:57:08<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 具体产品角色：热带水果<br />&nbsp;*/<br />public class TropicalFruit implements Fruit {<br />&nbsp;&nbsp;&nbsp; private String name;</div>        <div>}</div>    <div>1.3.1.4.5&nbsp;热带蔬菜：TropicalVeggie.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:TropicalVeggie.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:58:03<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 具体产品角色：热带蔬菜<br />&nbsp;*/<br />public class TropicalVeggie implements Veggie {<br />&nbsp;&nbsp;&nbsp; private String name;</div>  <div>&nbsp;&nbsp;&nbsp; public TropicalVeggie(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("热带工厂为您创建了：热带水果－"+name);<br />&nbsp;&nbsp;&nbsp; }</div>      <div>}</div>    <div>1.3.1.4.6&nbsp;亚热带水果：NorthernFruit.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:NorthernFruit.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:58:55<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 具体产品角色：亚热带水果<br />&nbsp;*/<br />public class NorthernFruit implements Fruit {<br />&nbsp;&nbsp;&nbsp; private String name;</div>  <div>&nbsp;&nbsp;&nbsp; public NorthernFruit(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("亚热带工厂为您创建了：亚热带水果－"+name);<br />&nbsp;&nbsp;&nbsp; }</div>      <div>}</div>  <div><br />1.3.1.4.7&nbsp;亚热带蔬菜：NorthernVeggie.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:NorthernVeggie.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 22:59:36<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 具体产品角色：亚热带蔬菜<br />&nbsp;*/<br />public class NorthernVeggie implements Veggie {<br />&nbsp;&nbsp;&nbsp; private String name;</div>  <div>&nbsp;&nbsp;&nbsp; public NorthernVeggie(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("亚热带工厂为您创建了：亚热带蔬菜－"+name);<br />&nbsp;&nbsp;&nbsp; }</div>      <div>}</div>    <div>1.3.1.4.8&nbsp;热带工厂：TropicalGardener.java<br />/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:TropicalGardener.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 23:01:49<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 具体工厂角色：热带工厂<br />&nbsp;*/<br />public class TropicalGardener implements Gardener {<br />&nbsp;&nbsp;&nbsp; public Fruit createFruit(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new TropicalFruit(name);<br />&nbsp;&nbsp;&nbsp; }</div>  <div>&nbsp;&nbsp;&nbsp; public Veggie createVeggie(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new TropicalVeggie(name);<br />&nbsp;&nbsp;&nbsp; }<br />}</div>    <div>1.3.1.4.9&nbsp;亚热带工厂：NorthernGardener.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:NorthernGardener.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 23:00:31<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 具体工厂角色：亚热带工厂<br />&nbsp;*/<br />public class NorthernGardener implements Gardener {<br />&nbsp;&nbsp;&nbsp; public Fruit createFruit(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new NorthernFruit(name);<br />&nbsp;&nbsp;&nbsp; }</div>  <div>&nbsp;&nbsp;&nbsp; public Veggie createVeggie(String name) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new NorthernVeggie(name);<br />&nbsp;&nbsp;&nbsp; }<br />}</div>  <div></div>  <div>1.3.1.4.10&nbsp;测试类（客户端）：TestApp.java<br />package com.lavasoft.patterns.abstractfactory.ybms;</div>  <div>/**<br />&nbsp;* Created by IntelliJ IDEA.<br />&nbsp;* FileName:TestApp.java<br />&nbsp;* User:&nbsp;&nbsp;&nbsp; LavaSoft<br />&nbsp;* Date:&nbsp;&nbsp;&nbsp; 2006-12-5<br />&nbsp;* Time:&nbsp;&nbsp;&nbsp; 23:03:22<br />&nbsp;* 《Java与模式》（--阎宏博士著）读书笔记<br />&nbsp;* 工厂模式--抽象工厂模式--一般性模式（农场应用）<br />&nbsp;* ReadMe:&nbsp; 测试类（客户端）<br />&nbsp;*/<br />public class TestApp {<br />&nbsp;&nbsp;&nbsp; private void test(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Veggie tv,nv;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Fruit tf,nf;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TropicalGardener tg=new TropicalGardener();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NorthernGardener ng=new NorthernGardener();</div>  <div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tv=tg.createVeggie("热带菜叶");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nv=ng.createVeggie("东北甜菜");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tf=tg.createFruit("海南椰子");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nf=ng.createFruit("雪梨");<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public static void main(String args[]){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestApp test=new TestApp();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test.test();<br />&nbsp;&nbsp;&nbsp; }<br />}</div>    <div>1.3.1.4.11&nbsp;测试运行结果<br />&nbsp;&nbsp;&nbsp; 热带工厂为您创建了：热带水果－热带菜叶<br />&nbsp;&nbsp;&nbsp; 亚热带工厂为您创建了：亚热带蔬菜－东北甜菜<br />&nbsp;&nbsp;&nbsp; 热带工厂为您创建了：热带水果－海南椰子<br />&nbsp;&nbsp;&nbsp; 亚热带工厂为您创建了：亚热带水果－雪梨</div>  <div>&nbsp;&nbsp;&nbsp; Process finished with exit code 0<br />&nbsp;&nbsp;&nbsp; 看完设计图和源码，原理已经很清楚了，这个模式应用很灵活，猴交给你了，看你怎么玩它！哈哈哈哈。。。。</div>  <div><strong>1.3.1.5&nbsp;女娲举绳造万物<br /></strong>&nbsp;&nbsp;&nbsp; 女娲举绳造物的故事很适合在这里举例子，女娲的绳子按照阴阳划分，产品则按人、兽划分。将抽象工厂模式用于女娲造万物的模拟系统设计中。系统设计图如下：</div>  </div></div><img alt="" src="http://www.blogjava.net/images/blogjava_net/qileilove/d1165335259515.png" height="531" width="685" /><img src ="http://www.blogjava.net/qileilove/aggbug/393318.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-21 16:26 <a href="http://www.blogjava.net/qileilove/archive/2012/12/21/393318.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学习设计模式--工厂方法模式</title><link>http://www.blogjava.net/qileilove/archive/2012/12/19/393215.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Wed, 19 Dec 2012 08:25:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2012/12/19/393215.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/393215.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/19/393215.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/393215.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/393215.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 东汉《风俗通》记录了一则神话故事：&#8220;开天辟辟，未有人民，女娲搏，黄土作人&#8230;&#8230;&#8221;，讲述的内容就是大家非常熟悉的女娲造人的故事。开天辟地之初，大地上并没有生物，只有苍茫大地，纯粹而洁净的自然环境，寂静而又寂寞，于是女娲决定创造一个新物种（即人类）来增加世界的繁荣，怎么制造呢？&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 别忘了女娲是神仙，...&nbsp;&nbsp;<a href='http://www.blogjava.net/qileilove/archive/2012/12/19/393215.html'>阅读全文</a><img src ="http://www.blogjava.net/qileilove/aggbug/393215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-19 16:25 <a href="http://www.blogjava.net/qileilove/archive/2012/12/19/393215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学习设计模式---生成器模式(Builder)解析例子 </title><link>http://www.blogjava.net/qileilove/archive/2012/12/18/393166.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Tue, 18 Dec 2012 09:16:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2012/12/18/393166.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/393166.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/18/393166.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/393166.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/393166.html</trackback:ping><description><![CDATA[<div><div style=" text-indent: 21pt"><span style="font-family: 宋体;">生成器模式属于对象结构型模式，其意图是将一个复杂对象的构建与他的表示分离，使得同样的构建创建过程可以创建不同的表示。</span></div> <div style=" text-indent: 21pt"><span style="font-family: 宋体;">适用性：</span></div> <div style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;"><span>1.<span style="font: 7pt ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时</span></div> <div style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;"><span>2.<span style="font: 7pt ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">当构造过程必须允许被构造的对象有不同的表示时。</span></div> <div style="margin: 0cm 0cm 0pt 21pt">&nbsp;</div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-family: 宋体;">参与者</span>:</div> <div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">生成器</span>Builder:<span style="font-family: 宋体;">为创建一个</span>Product<span style="font-family: 宋体;">对象的各个部件指定抽象接口</span>(AnimalBuilder)<span style="font-family: 宋体;">。</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">具体生成器</span>ConcreteBuilder:<span style="font-family: 宋体;">实现</span>Builder<span style="font-family: 宋体;">接口一构造和装配该产品的各个部件。</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">定义并明确他所创建的表示，</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">提供一个检索产品的接口</span>(getAnimal)<span style="font-family: 宋体;">。</span></div> <div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt"><span style="font-family: 宋体;">导向器：构建一个适用</span>Builder<span style="font-family: 宋体;">对象的接口。</span></div> <div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt">Product<span style="font-family: 宋体;">（</span>Checken,pig<span style="font-family: 宋体;">）</span>:<span style="font-family: 宋体;">表示被构造的复杂对象。</span>ConcreteBuilder<span style="font-family: 宋体;">创建该产品的内部表示并定义它的装配过程，包含定义组成部件的类，包括将这些部件装配成最终的产品。<img alt="" src="http://img1.51cto.com/attachment/200707/200707141184406082109.gif" border="0" /></span></div> <div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt" align="center"><span style="font-family: 宋体;">图1</span></div><span style="font-family: 宋体;"> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-family: 宋体;">当客户需要一个产品时，把需要的参数传递个导向器，导向器根据传递的参数调用具体的生成器，具体的生成器通过一系列的操作</span>(getAnimal()<span style="font-family: 宋体;">通过调用其它的接口方法实现</span>)<span style="font-family: 宋体;">最会返回一个产品。</span></div> <div style="margin: 0cm 0cm 0pt 21pt">Bridge<span style="font-family: 宋体;">模式的优点：</span></div> <div style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;"><span>1.<span style="font: 7pt ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">它使你可以改变一个产品的内部表示，</span>Builder<span style="font-family: 宋体;">对象提供给导向器一个构造产品的抽象接口，该接口使得生成器可以隐藏这个产品的表示和内部结构，他同时也隐藏了该产品是如何装配的，因为产品时通过抽象接口构造的</span>(<span style="font-family: 宋体;">注：本例子把接口的实现放在具体类中了</span>)<span style="font-family: 宋体;">，你在改变该产品的内部表示时所要做的只是定义一个新的生成器。</span></div> <div style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;"><span>2.<span style="font: 7pt ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">他将构造代码和表示代码分开，这有点类似于模板模式。所不同的是模版模式最终是完成复杂的工作，而生成器的目的是要生成一个复杂的对象。</span></div> <div style="margin: 0cm 0cm 0pt 42pt; text-indent: -21pt;"><span>3.<span style="font: 7pt ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">他使得你对构造过程进行更加精细的控制。</span>Builder<span style="font-family: 宋体;">模式是在导向者的控制下一步一步构造产品的，仅当该产品完成时，导向者才从生成器中取回产品。因此</span>Builder<span style="font-family: 宋体;">模式能更好的反映产品的构造过程，使你可以更精细的控制构建过程，从而能更精细的控制所的产品的内部结构。</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-family: 宋体;">代码示例</span>:</div> <div style="margin: 0cm 0cm 0pt 21pt;"><span style="font-size: 10pt; color: black; font-family: ">AnimalBuilder</span><span style="font-family: 宋体;">：代码</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">package</span></strong><span style="font-size: 10pt; color: black; font-family: "> builder;</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">interface</span></strong><span style="font-size: 10pt; color: black; font-family: "> AnimalBuilder{</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> buildName();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> buildLegs();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> buildMeat();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong><span style="font-size: 10pt; color: black; font-family: "> Animal getAnimal();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">}</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-size: 10pt; color: black; font-family: ">ChickenBuilder</span><span style="font-size: 10pt; color: black; font-family: 宋体;">的</span><span style="font-family: 宋体;">代码：</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">package</span></strong><span style="font-size: 10pt; color: black; font-family: "> builder;</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">class</span></strong><span style="font-size: 10pt; color: black; font-family: "> ChickenBuilder </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">implements</span></strong><span style="font-size: 10pt; color: black; font-family: "> AnimalBuilder{</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">private</span></strong><span style="font-size: 10pt; color: black; font-family: "> Animal </span><span style="font-size: 10pt; color: #0000c0; font-family: ">chicken</span><span style="font-size: 10pt; color: black; font-family: "> = </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">null</span></strong><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong><span style="font-size: 10pt; color: black; font-family: "> ChickenBuilder(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">chicken</span><span style="font-size: 10pt; color: black; font-family: "> = </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">new</span></strong><span style="font-size: 10pt; color: black; font-family: "> Animal();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> buildName(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">chicken</span><span style="font-size: 10pt; color: black; font-family: ">.setName(</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"chicken"</span><span style="font-size: 10pt; color: black; font-family: ">);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> buildLegs(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">chicken</span><span style="font-size: 10pt; color: black; font-family: ">.setLegs(2);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> buildMeat(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">chicken</span><span style="font-size: 10pt; color: black; font-family: ">.setMeat(</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"chicken"</span><span style="font-size: 10pt; color: black; font-family: ">);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong><span style="font-size: 10pt; color: black; font-family: "> Animal getAnimal(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildName();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildLegs();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buildMeat();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <span style="font-size: 10pt; color: #0000c0; font-family: ">chicken</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">}</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-size: 10pt; color: black; font-family: ">Animal</span><span style="font-family: 宋体;">代码：</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">package</span></strong><span style="font-size: 10pt; color: black; font-family: "> builder;</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">class</span></strong><span style="font-size: 10pt; color: black; font-family: "> Animal{</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">private</span></strong><span style="font-size: 10pt; color: black; font-family: "> String </span><span style="font-size: 10pt; color: #0000c0; font-family: ">name</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">private</span></strong><span style="font-size: 10pt; color: black; font-family: "> String </span><span style="font-size: 10pt; color: #0000c0; font-family: ">meat</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">private</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">int</span></strong> <span style="font-size: 10pt; color: #0000c0; font-family: ">legs</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong><span style="font-size: 10pt; color: black; font-family: "> String getName(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <span style="font-size: 10pt; color: #0000c0; font-family: ">name</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong><span style="font-size: 10pt; color: black; font-family: "> String getMeat(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <span style="font-size: 10pt; color: #0000c0; font-family: ">meat</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">int</span></strong><span style="font-size: 10pt; color: black; font-family: "> getLegs(){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <span style="font-size: 10pt; color: #0000c0; font-family: ">legs</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> setName(String aName){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">name</span><span style="font-size: 10pt; color: black; font-family: "> = aName;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> setMeat(String aMeat){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">meat</span><span style="font-size: 10pt; color: black; font-family: "> = aMeat;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> setLegs(</span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">int</span></strong><span style="font-size: 10pt; color: black; font-family: "> alegs){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10pt; color: #0000c0; font-family: ">legs</span><span style="font-size: 10pt; color: black; font-family: "> = alegs;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">}</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-size: 10pt; color: black; font-family: ">Director</span><span style="font-family: 宋体;">代码：</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">package</span></strong><span style="font-size: 10pt; color: black; font-family: "> builder;</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">class</span></strong><span style="font-size: 10pt; color: black; font-family: "> Director{</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong><span style="font-size: 10pt; color: black; font-family: "> Animal getAnimal(String aName){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">if</span></strong><span style="font-size: 10pt; color: black; font-family: ">(aName.equals(</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"chicken"</span><span style="font-size: 10pt; color: black; font-family: ">)){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">new</span></strong><span style="font-size: 10pt; color: black; font-family: "> ChickenBuilder().getAnimal();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">else</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">if</span></strong><span style="font-size: 10pt; color: black; font-family: ">(aName.equals(</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"pig"</span><span style="font-size: 10pt; color: black; font-family: ">)){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">new</span></strong><span style="font-size: 10pt; color: black; font-family: "> PigBuilder().getAnimal();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">else</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">return</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">null</span></strong><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">}</span></div> <div style="margin: 0cm 0cm 0pt 21pt">&nbsp;</div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-family: 宋体;">客户端代码：</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">package</span></strong><span style="font-size: 10pt; color: black; font-family: "> builder;</span></div> <div align="left"><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">class</span></strong><span style="font-size: 10pt; color: black; font-family: "> Client{</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">static</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> description(Animal animal){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String desc = </span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"This animal is called "</span><span style="font-size: 10pt; color: black; font-family: ">+animal.getName();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; desc +=</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"\n Its meat is "</span><span style="font-size: 10pt; color: black; font-family: ">+animal.getMeat();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; desc +=</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"\n And it has "</span><span style="font-size: 10pt; color: black; font-family: ">+animal.getLegs()+</span><span style="font-size: 10pt; color: #2a00ff; font-family: ">" legs."</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.</span><em><span style="font-size: 10pt; color: #0000c0; font-family: ">out</span></em><span style="font-size: 10pt; color: black; font-family: ">.println(desc);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">public</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">static</span></strong> <strong><span style="font-size: 10pt; color: #7f0055; font-family: ">void</span></strong><span style="font-size: 10pt; color: black; font-family: "> main(String[] args){</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String aName = </span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"chicken"</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Director d = </span><strong><span style="font-size: 10pt; color: #7f0055; font-family: ">new</span></strong><span style="font-size: 10pt; color: black; font-family: "> Director();</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Animal animal =d.getAnimal(aName);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>description</em>(animal);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; aName = </span><span style="font-size: 10pt; color: #2a00ff; font-family: ">"pig"</span><span style="font-size: 10pt; color: black; font-family: ">;</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; animal = d.</span><u><span style="font-size: 10pt; color: blue; font-family: ">getAnimal</span></u><span style="font-size: 10pt; color: black; font-family: ">(aName);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>description</em>(animal);</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">&nbsp;&nbsp;&nbsp; }</span></div> <div align="left"><span style="font-size: 10pt; color: black; font-family: ">}</span></div> <div style="margin: 0cm 0cm 0pt 21pt"><span style="font-family: 宋体;">结论：生成器模式使得客户可以更加精细的控制一个对象的构建，每个具体的创建者包含了创建和装配一个特定产品的所有代码，这些代码只用写一次，便可以被不同的</span>Director<span style="font-family: 宋体;">使用，从而可以装配出不同的对象。</span></div> </span><div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt" align="center">&nbsp;</div> <div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt"></div></div><img src ="http://www.blogjava.net/qileilove/aggbug/393166.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-18 17:16 <a href="http://www.blogjava.net/qileilove/archive/2012/12/18/393166.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学习设计模式---代理模式之动态代理</title><link>http://www.blogjava.net/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://www.blogjava.net/qileilove/archive/2012/12/13/392932.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392932.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/13/392932.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392932.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392932.html</trackback:ping><description><![CDATA[<div><p>动态代理</p> <p>java中动态代理机制的引入使得代理模式的思想更加完善与进步，它允许动态的创建代理并支持对动态的对所代理的方法进行调用。Java动态代理类位于Java.lang.reflect包下，一般主要涉及到以下两个类：&nbsp;</p> <p><span>(1). Interface InvocationHandler</span>：该接口中仅定义了一个方法Object：<span>invoke(Object obj,Method method, Object[] args)</span>。在实际使用时，第一个参数obj一般是指代理类，method是被代理的方法，如上例中的request()，args为该方法的参数数组。这个抽象方法在代理类中动态实现。&nbsp;</p> <p>(2).Proxy：该类即为动态代理类，作用类似于上例中的ProxySubject，其中主要包含以下内容：&nbsp;</p> <p><span>Protected Proxy(InvocationHandler h)</span>：构造函数，估计用于给内部的h赋值。&nbsp;</p> <p><span>Static Class getProxyClass (ClassLoader loader, Class[] interfaces)</span>：获得一个代理类，其中loader是类装载器，interfaces是真实类所拥有的全部接口的数组。&nbsp;</p> <p><span>Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)</span>：返回代理类的一个实例，返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)。&nbsp;</p> <p>&nbsp;</p> <p>所谓Dynamic Proxy是这样一种class：它是在运行时生成的class，在生成它时你必须提供一组interface给它，然后该class就宣称它实现了这些interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦，这个Dynamic Proxy其实就是一个Proxy，它不会替你作实质性的工作，在生成它的实例时你必须提供一个handler，由它接管实际的工作。 下面我们通过动态代理来重新实现上面发送信息的例子！</p> <p><br /></p> <p>&nbsp;<img src="http://hi.csdn.net/attachment/201006/15/0_1276561533dOxg.gif" alt="" /></p>  <p>在上面的例子基础上，我们先添加一个通过短信来发送消息的处理类：</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 &amp;&amp; args.length == 1 &amp;&amp; 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 &amp;&amp; msg.length() &gt; 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 />&nbsp;* @param args<br />&nbsp;*/<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 />下面为以上方法的输出：<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方法创建动态代理对象，该方法需要传入一个 <span>类加载器、一组希望代理实现的接口列表、InvocationHandler 接口的一个具体实现。动态代理可以将所有调用重定向到调用处理器，通常我们会向该处理器传递一个时间对象的引用。</span>invoke()方法中传递进来了代理对象，当你需要区分请求来源时这是非常有用的，例如你可以通过判断传入的方法名屏蔽掉某些方法的执行！动态代理机制并不是会很频繁使用的方法，它通常用来解决一些特定情况下的问题，因此不要盲目的为了使用而使用，要根据自己的实际需求来决定！</p></div><div>动态代理的应用十分广泛，在struts2的拦截器中就用到了动态代理机制。还是以买车票为例子，现在用动态代理来实现，其中不懂的接口方法查查Java api就会明白了，在此不多做解释，代码如下(注意PassengerProxy类)：  <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 />&nbsp;&nbsp; // TODO Auto-generated method stub<br />&nbsp;&nbsp; System.out.println("购买了车票");<br />}<br />}</p>  <p style="text-indent: 2em;">// 用动态代理实现</p><p style="text-indent: 2em;">/<code>/InvocationHandler</code> 是代理实例的<em>调用处理程序</em> 实现的接口。  每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时，将对方法调用进行编码并将其指派到//它的调用处理程序的 <code>invoke</code> 方法。<br />public class PassengerProxy implements InvocationHandler {<br />public Object obj;</p>  <p style="text-indent: 2em;">// 把obj交给代理类<br />public Object obj(Object obj) {<br />&nbsp;&nbsp; this.obj = obj;<br />&nbsp;&nbsp; return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj<br />&nbsp;&nbsp;&nbsp;&nbsp; .getClass().getInterfaces(), this);<br />}</p>  <p style="text-indent: 2em;">@Override<br />public Object invoke(Object proxy, Method method, Object[] args)<br />&nbsp;&nbsp;&nbsp; throws Throwable {<br />&nbsp;&nbsp; // TODO Auto-generated method stub<br />&nbsp;&nbsp; System.out.println("通过代理");<br />&nbsp;&nbsp; method.invoke(obj, args);<br />&nbsp;&nbsp; return null;<br />}<br />}</p>  <p style="text-indent: 2em;">public class Client {<br />public static void main(String[] args) {<br />&nbsp;&nbsp; PassengerProxy proxy = new PassengerProxy();<br />&nbsp;&nbsp; Passenger passenger = (Passenger) proxy.obj(new RealPassenger());<br />&nbsp;&nbsp; passenger.buyTicket();<br />}<br />}</p><p style="text-indent: 2em;">再来一个更牛的例子</p><p style="text-indent: 2em;"></p><div><ol start="1"><li><span>/**&nbsp;</span></li><li><span>&nbsp;*&nbsp;相亲接口&nbsp;</span></li><li><span>&nbsp;*&nbsp;&nbsp;</span></li><li><span>&nbsp;*&nbsp;@author&nbsp;zhengt&nbsp;</span></li><li><span>&nbsp;*&nbsp;@time&nbsp;Jun&nbsp;3,&nbsp;2095&nbsp;3:13:03&nbsp;PM&nbsp;</span></li><li><span>&nbsp;*/&nbsp;&nbsp;</span></li><li><span>public&nbsp;interface&nbsp;XiangQinInterface&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>/**&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;相亲方法&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;void&nbsp;xiangQin();&nbsp;&nbsp;</span></li><li>}&nbsp;&nbsp;</li><li><span>/**&nbsp;</span></li><li><span>&nbsp;*&nbsp;张三相亲实现类&nbsp;</span></li><li><span>&nbsp;*&nbsp;&nbsp;</span></li><li><span>&nbsp;*&nbsp;@author&nbsp;zhengt&nbsp;</span></li><li><span>&nbsp;*&nbsp;@time&nbsp;Jun&nbsp;3,&nbsp;2095&nbsp;3:14:48&nbsp;PM&nbsp;</span></li><li><span>&nbsp;*/&nbsp;&nbsp;</span></li><li><span>public&nbsp;class&nbsp;ZhangSanXiangQinInterfaceImpl&nbsp;implements&nbsp;XiangQinInterface&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;void&nbsp;xiangQin()&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span>"张三去相亲，娶个漂亮老婆。");&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li><li><span>import&nbsp;java.lang.reflect.InvocationHandler;&nbsp;&nbsp;</span></li><li><span>import&nbsp;java.lang.reflect.Method;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li><span>/**&nbsp;</span></li><li><span>&nbsp;*&nbsp;相亲可是一辈子的大事，相亲前要准备一下，打扮得帅气些。&nbsp;</span></li><li><span>&nbsp;*&nbsp;&nbsp;</span></li><li><span>&nbsp;*&nbsp;@author&nbsp;zhengt&nbsp;</span></li><li><span>&nbsp;*&nbsp;@time&nbsp;Jun&nbsp;3,&nbsp;2095&nbsp;3:15:48&nbsp;PM&nbsp;</span></li><li><span>&nbsp;*/&nbsp;&nbsp;</span></li><li><span>public&nbsp;class&nbsp;ReadyInvocationHandler&nbsp;implements&nbsp;InvocationHandler&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>//相亲接口的实现类，也就是张三相亲类&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>private&nbsp;Object&nbsp;zhangSan&nbsp;=&nbsp;null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;ReadyInvocationHandler(Object&nbsp;realSubject)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>this.zhangSan&nbsp;=&nbsp;realSubject;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;Object&nbsp;invoke(Object&nbsp;proxy,&nbsp;Method&nbsp;m,&nbsp;Object[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;result&nbsp;=&nbsp;<span>null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>try&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>/**&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;动态代理类$Proxy0调用xiangQin方法时会调用它自己的xiangQin方法，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;而它自己的xiangQin方法里面调用的是super.h.invoke(this,&nbsp;,&nbsp;)，也就是父类Proxy的h的invoke方法，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;也就是ReadyInvocationHandler类的invoke方法。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;所以，invoke(Object&nbsp;proxy,&nbsp;Method&nbsp;m,&nbsp;Object[]&nbsp;args)种的proxy实际上就是动态代理类$Proxy0，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;如果你将其强转成XiangQinInterface然后调用它的xiangQin方法，然后它就会调用super.h.invoke(this,&nbsp;,&nbsp;)，这样就会死循环。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>/**&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;网上关于这里最多问题就是Object&nbsp;proxy放在这里用来做什么呢？这个我也不知道，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;不过至少我们知道它到底是个什么东西，具体做什么用嘛就不得而知了&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(proxy.getClass().getSimpleName());&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span>"张三相亲前，代理人给他打扮了打扮。");&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result&nbsp;=&nbsp;m.invoke(zhangSan,&nbsp;args);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>catch&nbsp;(Exception&nbsp;ex)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.exit(<span>1);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;result;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li><li><span>import&nbsp;java.lang.reflect.InvocationHandler;&nbsp;&nbsp;</span></li><li><span>import&nbsp;java.lang.reflect.Method;&nbsp;&nbsp;</span></li><li><span>import&nbsp;java.lang.reflect.Proxy;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li><span>/**&nbsp;</span></li><li><span>&nbsp;*&nbsp;张三来到了婚介所(相亲现场)，开始相亲。&nbsp;</span></li><li><span>&nbsp;*&nbsp;&nbsp;</span></li><li><span>&nbsp;*&nbsp;@author&nbsp;zhengt&nbsp;</span></li><li><span>&nbsp;*&nbsp;@time&nbsp;Jun&nbsp;3,&nbsp;2095&nbsp;3:17:16&nbsp;PM&nbsp;</span></li><li><span>&nbsp;*/&nbsp;&nbsp;</span></li><li><span>public&nbsp;class&nbsp;HunJieSuo&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;static&nbsp;void&nbsp;main(String&nbsp;args[])&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//先将张三相亲这个相亲的实现类实例化，也就是得到XiangQinInterface接口的一个实例对象&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XiangQinInterface&nbsp;zhangSan&nbsp;=&nbsp;<span>new&nbsp;ZhangSanXiangQinInterfaceImpl();&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>/**&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;得到ZhangSanXiangQinInterfaceImpl这个类的一个代理类，同时为代理类绑定了一个处理类ReadyInvocationHandler。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;听着很绕口，其实就是每次调用ZhangSanXiangQinInterfaceImpl这个子类的xiangQin方法时，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;不是zhangSan这个ZhangSanXiangQinInterfaceImpl类的实例去调用，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;而是这个ZhangSanXiangQinInterfaceImpl的代理类ReadyInvocationHandler去调用它自己的invoke方法,&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;这个invoke方法里呢可以调用zhangSan这个实例的xiangQin方法&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>/**&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;在java种怎样实现动态代理呢&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第一步，我们要有一个接口，还要有一个接口的实现类，而这个实现类呢就是我们要代理的对象，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;所谓代理呢也就是在调用实现类的方法时，可以在方法执行前后做额外的工作，这个就是代理。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第二步，我们要自己写一个在要代理类的方法执行时，能够做额外工作的类，而这个类必须继承InvocationHandler接口，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;为什么要继承它呢？因为代理类的实例在调用实现类的方法的时候，不会调真正的实现类的这个方法，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;而是转而调用这个类的invoke方法（继承时必须实现的方法），在这个方法中你可以调用真正的实现类的这个方法。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第三步，在要用代理类的实例去调用实现类的方法的时候，写出下面两段代码。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XiangQinInterface&nbsp;proxy&nbsp;=&nbsp;(XiangQinInterface)&nbsp;Proxy.newProxyInstance(&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zhangSan.getClass().getClassLoader(),&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zhangSan.getClass().getInterfaces(),&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>new&nbsp;ReadyInvocationHandler(zhangSan));&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy.xiangQin();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>/**&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;这里要解释下中部那段长长的代码的意思，以及具体做了哪些工作？&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第一，根据zhangSan.getClass().getClassLoader()这个要代理类的类加载器和&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;zhangSan.getClass().getInterfaces()要代理类所实现的所有的接口&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;作为参数调用Proxy.getProxyClass(ClassLoader&nbsp;loader,&nbsp;Class&lt;?&gt;...&nbsp;interfaces)&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;的方法返回代理类的java.lang.Class对象，也就是得到了java动态生成的代理类$Proxy0的Class对象。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;同时，java还让这个动态生成的$Proxy0类实现了要代理类的实现的所有接口，并继承了Proxy接口。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第二，实例化这个动态生成的$Proxy0类的一个实例，实例化代理类的构造函数为Proxy(InvocationHandler&nbsp;h)，&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;也就是说要实例化这个动态生成的$Proxy0类，必须给它一个InvocationHandler参数，也就是我们自己实现的用来在代理类&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;方法执行前后做额外工作的类ReadyInvocationHandler。&nbsp;</span></li><li><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;这 段代码 Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new&nbsp;ReadyInvocationHandler(zhangSan))</span>&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;得到的其实是一个类名叫$Proxy0&nbsp;extends&nbsp;Proxy&nbsp;implements&nbsp;XiangQinInterface的类。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;第三，将这个$Proxy0类强制转型成XiangQinInterface类型，调用xiangQin方法。&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>}&nbsp; <br /></li></ol></div><div>网上看到一个牛人读过这个动态代理的源代码，现把网址留在这里，希望对网友们有帮助。 <br /><a target="_blank" href="http://hi.baidu.com/malecu/blog/item/45d4952b31bc0e27d52af17a.html">http://hi.baidu.com/malecu/blog/item/45d4952b31bc0e27d52af17a.html</a> </div><div><div><div>在目前的Java开发包中包含了对动态代理的支持，但是其实现只支持对接口的的实现。 <br /> <br />　　其实现主要通过是java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口。 <br /> <br />　　Proxy类主要用来获取动态代理对象，InvocationHandler接口用来约束调用者实现，如下，DiaoSi接口定义的 业务方法，DiaoSiNanImpl是DiaoSi接口的实现，<div>DiaoSiNanHandler是  InvocationHandler接口实现。代码如下：<br /><div>业务接口: </div></div></div><div>package proxy;<br /><br />public interface DiaoSi {<br />void luGuan();<br />}<br /></div><div><div>　业务接口实现： </div></div><div>public class DiaoSiNan implements DiaoSi {<br /><br />&nbsp;&nbsp; &nbsp;@Override<br />&nbsp;&nbsp; &nbsp;public void luGuan() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// TODO Auto-generated method stub<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("我是撸管王");<br />&nbsp;&nbsp; &nbsp;}<br /><br />}</div><div>　InvocationHandler实现，需要在接口方法调用前后加入一部份处理工作，这里仅仅在方法调用前后向后台输出两句字符串，其代码如下： </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 />&nbsp;&nbsp; &nbsp;//要代理的原始对象 <br />&nbsp;&nbsp; &nbsp;<br />private Object diaosinan; <br />/**<br /><br />* 构造函数。<br /><br />* @param obj 要代理的原始对象。<br /><br />*/ <br />public DiaoSiNanHander(Object diaosinan) {<br /><br />&nbsp;&nbsp; &nbsp;this.diaosinan = diaosinan;<br />}<br />&nbsp;&nbsp; &nbsp;@Override<br />&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;public Object invoke(Object proxy, Method method, Object[] args)<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;throws Throwable {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// TODO Auto-generated method stub<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;Object result ;<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;doBefore(); <br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//调用原始对象的方法 <br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;result = method.invoke(this.diaosinan ,args); <br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;//方法调用之后 <br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;doafter();<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;return result;<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;private void doafter() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// TODO Auto-generated method stub<br />System.out.println("after method invoke!"); <br />&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;private void doBefore() {<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;// TODO Auto-generated method stub<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;System.out.println("before method invoke!"); <br />&nbsp;&nbsp; &nbsp;}<br /><br /><br />}<br /></div><div>测试代码： </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 />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Class&lt;?&gt;[] interfaces,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InvocationHandler h)<br />throws IllegalArgumentException<br />{<br />if (h == null) {<br />throw new NullPointerException();<br />}*/<br />proxy.luGuan();<br /><br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br /><br />}<br />}<br /><div>&#216; 首先获取一个业务接口的实现对象; <br /> <br />　　&#216; 获取一个InvocationHandler实现，此处是<div>DiaoSiNanHanderHandler对象;</div> <br />　　&#216; 创建动态代理对象; <br /> <br />　　&#216; 通过动态代理对象调用luGuan()方法，此时会在原始对象DiaoSiNan.luGuan()方法前后输出两句字符串。 <br /> <br />　　运行测试类输出如下: <br /> <br />　　<div>before method invoke!<br />我试撸管王<br />after method invoke!<br /></div><br /> <br />　　此处Test类中的方法调用代码比较多，在我们的实际应用中可以通过配置文件来来简化客户端的调用实现。另外也可以通过动态代理来实现简单的AOP。 </div></div><br /><p><br /></p></div><br /></div><br /><p>&nbsp;</p></div><img src ="http://www.blogjava.net/qileilove/aggbug/392932.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-13 11:53 <a href="http://www.blogjava.net/qileilove/archive/2012/12/13/392932.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学习设计模式---代理模式</title><link>http://www.blogjava.net/qileilove/archive/2012/12/13/392930.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Thu, 13 Dec 2012 03:20:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2012/12/13/392930.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392930.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/13/392930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392930.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392930.html</trackback:ping><description><![CDATA[<div><a id="cb_post_title_url" href="http://www.cnblogs.com/hjzhang/archive/2010/06/15/2043568.html">Java 代理模式详解</a></div><div><p>代理模式是我们比较常用的设计模式之一。其中新思想是为了提供额外的处理或者不同的操作而在实际对象与调用者之间插入一个代理对象。这些额外的操作通常需要与实际对象进行通信，代理模式一般涉及到的角色有：&nbsp; </p> <p>抽象角色：声明真实对象和代理对象的共同接口；&nbsp;</p> <p>代理角色：代理对象角色内部含有对真实对象的引用，从而可以操作真实对象，同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时，代理对象可以在执行真实对象操作时，附加其他的操作，相当于对真实对象进行封装。&nbsp;</p> <p>真实角色：代理角色所代表的真实对象，是我们最终要引用的对象。 </p> <p>&nbsp;</p> <p>以下以发送消息为例来说明一个简单的代理模式的基本实现：</p> <p>首先明确目的：有一条消息，需要把这个消息发送出去，根据这个目的定义对应接口MessageHandler。需要的附加操作：假设需要验证消息的长度不能超过指定长度并且不能为空，并且我们需要统计相关信息发送到次数，超过指定的次数我们需要输出警报。我们通过代理模式来实现这个附加的操作。下面为对应的类关系图及示例代码。</p><p><img alt="" src="http://www.blogjava.net/images/blogjava_net/qileilove/2826853191106794995.jpg" height="252" width="405" /><br /></p><p><br /></p><p><br /></p></div><div>//接口定义<br />public interface MessageHandler {<br />public void sendMessage(String msg);<br />}<br />//通过Email方式发送消息的实现类<br />public class EmailMessage implements MessageHandler {<br />@Override<br />public void sendMessage(String msg) {<br />// TODO Auto-generated method stub<br />System.out.println(msg+" send!!");<br />}<br />}<br />//消息处理的代理类<br />public class MessageProxy implements MessageHandler {<br />private static int count;<br />private MessageHandler emailMsg;<br />@Override<br />public void sendMessage(String msg) {<br />// TODO Auto-generated method stub<br />if(checkMessage(msg))<br />{<br />if(emailMsg==null) emailMsg=new EmailMessage();<br />count++;<br />emailMsg.sendMessage(msg);<br />System.out.println("Message sent:"+count);<br />}<br />}<br />private boolean checkMessage(String msg) {<br />return msg != null &amp;&amp; msg.length() &gt; 10;<br />}<br />}<br />//调用类<br />public class MainClass {<br />private static void runProxy(MessageHandler handler)<br />{<br />handler.sendMessage("message for test");<br />}<br />/**<br />&nbsp;* @param args<br />&nbsp;*/<br />public static void main(String[] args) {<br />// TODO Auto-generated method stub<br />runProxy(new EmailMessage());<br />System.out.println("++++++++++++++++Pjroxy++++++++++++++++++");<br />runProxy(new MessageProxy());<br />}<br />}<br />输出<br />message for test send!!<br />++++++++++++++++Pjroxy++++++++++++++++++<br />message for test send!!<br />Message sent:1</div><div><p>在例子中我们可以方便的在消息发送过程中添加各种需要的附加处理方式，也能方便的替换消息的处理方式，如将通过Email发送消息替换为通过短信发送消息，而调用方不会有丝毫察觉！在任何你想要将一些额外操作分离到具体对象之外，特别是希望能够很容易做出修改，或者想在具体对象的方法执行前插入一些额外操作的时候，代理就显得十分有用！</p></div><div>　例如：假设有一组对象都实现同一个接口，实现同样的方法，但这组对象中有一部分对象需要有单独的方法，传统的笨办法是在每一个应用端都加上这个单独的方法，但是代码重用性低，耦合性高。 　　如果用代理的方法则很好的解决了这个问题</div><div>　假设有一个Italk接口，有空的方法talk（）（说话），所有的people对象都实现（implements）这个接口，实现talk（）方法， 前端有很多地方都将people实例化，执行talk方法，后来发现这些前端里有一些除了要说话以外还要唱歌（sing），那么我们既不能在Italk接 口里增加sing()方法，又不能在每个前端都增加sing方法，我们只有增加一个代理类talkProxy，这个代理类里实现talk和sing方法， 然后在需要sing方法的客户端调用代理类即可，代码如下：<h3>接口类Italk</h3>　　public interface Italk { <br />　　public void talk(String msg); <br />　　}<h3>实现类people</h3>　　public class People implements Italk<br />&nbsp;{ 　　public String username; 　<br />　public String age; 　<br />　public String getName() <br />{ 　　<br />return username; <br />　　} 　　<br />public void setName(String name) { <br />　　this.username= name; 　　<br />} 　<br />　public String getAge() { 　<br />　return age; 　　} 　　<br />public void setAge(String age) { <br />　　this.age = age; 　　} 　<br />　public People(String name1, String age1) { <br />　　this.username= name1; 　<br />　this.age = age1; 　<br />　} <br />　　public void talk(String msg) { <br />　　System.out.println(msg+"!你好,我是"+username+"，我年龄是"+age); <br />　　} 　　<br />}<h3>代理类talkProxy</h3>　　public class TalkProxy implements Italk<br />&nbsp;{ 　　Italk talker; 　<br />　public TalkProxy (Italk talker) <br />{ <br />　　//super(); 　　<br />this.talker=talker; 　<br />　} 　　<br />public void talk(String msg) <br />{ 　　<br />talker.talk(msg); 　<br />　} 　　<br />public void talk(String msg,String singname)<br />&nbsp;{ 　　<br />talker.talk(msg); <br />　　sing(singname); <br />　　} 　　<br />private void sing(String singname)<br />{ 　<br />　System.out.println("唱歌："+singname); <br />　　} 　<br />　} <br />　　}<h3>应用端myProxyTest</h3>　　public class MyProxyTest { 　<br />　/**代理模式 　　* @param args 　　*/ 　<br />　public static void main(String[] args)<br />&nbsp;{ 　　<br />//不需要执行额外方法的 　<br />　Italk people1=new People("<a target="_blank" href="http://baike.baidu.com/view/152104.htm">湖海散人</a>","18"); 　<br />　people1.talk("No ProXY Test"); 　<br />　System.out.println("-----------------------------"); 　<br />　//需要执行额外方法的 　　<br />TalkProxy talker=new TalkProxy(people1); 　　<br />talker.talk("ProXY Test","七里香"); <br />　　} 　<br />　}<br /><div>所谓代理，是指具有与代理元（被代理的对象）具有相同的接口的类，客户端必须通过代理与被代 理的目标类交互，而代理一般在交互的过程中（交互前后），进行某些特别的处理。Proxy模式是很常见的模式，在我们生活中处处可见，例如我们买火车票不 一定非要到火车站去买，可以到一些火车票的代售点去买。寄信不一定是自己去寄，可以把信委托给邮局，由邮局把信送到目的地。  <p style="text-indent: 2em;">代理结构如下图所示</p>  <p style="text-indent: 2em;"><img alt="Java 代理/动态代理模式(Proxy) - stevinzhu - stevinzhu的博客" src="http://img.blog.163.com/photo/_sb6nz7Sc3baQTA3t-OfQA==/2826853191106794995.jpg" border="0" /></p>  <p style="text-indent: 2em;">以通过代售点买火车票为例，代码实现如下：</p>  <p style="text-indent: 2em;">//提供买票的公共接口<br />interface Passenger {<br />public void buyTicket();<br />}</p>  <p style="text-indent: 2em;">//乘客实体<br />public class RealPassenger implements Passenger {<br />@Override<br />public void buyTicket() {<br />&nbsp;&nbsp; // TODO Auto-generated method stub<br />&nbsp;&nbsp; System.out.print("购买了火车票");<br />}<br />}</p>  <p style="text-indent: 2em;">//代售点<br />public class Proxy implements Passenger {<br />Passenger passenger;</p>  <p style="text-indent: 2em;">public Proxy(Passenger p) {<br />&nbsp;&nbsp; this.passenger = p;<br />}</p>  <p style="text-indent: 2em;">@Override<br />public void buyTicket() {<br />&nbsp;&nbsp; // TODO Auto-generated method stub<br />&nbsp;&nbsp; System.out.println("通过代售点");<br />&nbsp;&nbsp; passenger.buyTicket();<br />}<br />}</p>  <p style="text-indent: 2em;">//测试类<br />public class Client {<br />public static void main(String[] args) {<br />&nbsp;&nbsp; Passenger passenger = new RealPassenger();<br />&nbsp;&nbsp; Passenger proxy = new Proxy(passenger);<br />&nbsp;&nbsp; proxy.buyTicket();<br />}<br />}</p>  <p style="text-indent: 2em;">输出结果：<br />通过代售点<br />购买了火车票</p>  <p style="text-indent: 2em;">以 上的也可叫做静态代理，是为了区别代理模式在Java中的另一种实现&#8212;&#8212;动态代理。</p><p style="text-indent: 2em;">接下来会为大家带来动态代理<br /></p></div></div><img src ="http://www.blogjava.net/qileilove/aggbug/392930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-13 11:20 <a href="http://www.blogjava.net/qileilove/archive/2012/12/13/392930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥一起学习设计模式---中介者模式</title><link>http://www.blogjava.net/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://www.blogjava.net/qileilove/archive/2012/12/12/392858.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392858.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/12/392858.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392858.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392858.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 中介者模式（Mediator）：用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互。通用类图：举例：在一个公司里面，有很多部门、员工（我们统称他们互相为Colleague&#8220;同事&#8221;），为了完成一定的任务，&#8220;同事&#8221;之间肯定有许多需要互相配合、交流的过程。如果由各个&#8220;同事...&nbsp;&nbsp;<a href='http://www.blogjava.net/qileilove/archive/2012/12/12/392858.html'>阅读全文</a><img src ="http://www.blogjava.net/qileilove/aggbug/392858.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-12 13:23 <a href="http://www.blogjava.net/qileilove/archive/2012/12/12/392858.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学习设计模式---观察者模式</title><link>http://www.blogjava.net/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://www.blogjava.net/qileilove/archive/2012/12/11/392774.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392774.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/11/392774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392774.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392774.html</trackback:ping><description><![CDATA[<h2><a id="viewpost1_TitleUrl" href="http://www.blogjava.net/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;">简单地说，观察者模式定义了一个一对多的依赖关系，让一个或多个观察者对象监察一个主题对象。这样一个主题对象在状态上的变化能够通知所有的依赖于此对象的那些观察者对象，使这些观察者对象能够自动更新。<br />　<strong>观察者模式的结构</strong><br /><br />　　观察者（Observer）模式是对象的行为型模式，又叫做发表-订阅（Publish/Subscribe）模式、模型-视图（Model/View）模式、源-收听者（Source/Listener）模式或从属者（Dependents）模式。<br /><br />　本模式的类图结构如下：<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 />图1、观察者模式的静态结构可从类图中看清楚。</td></tr></tbody></table><p style="margin: 10px 0px;">　　在观察者模式里有如下的角色：<br />　.<strong>&nbsp;抽象主题（Subject）角色</strong>：主题角色把所有的观察者对象的引用保存在一个列表里；每个主题都可以有任何数量的观察者。主题提供一个接口可以加上或撤销观察者对象；主题角色又叫做抽象被观察者(Observable)角色；&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 />图2、抽象主题角色，有时又叫做抽象被观察者角色，可以用一个抽象类或者一个接口实现；在具体的情况下也不排除使用具体类实现。</td></tr></tbody></table></p><p style="margin: 10px 0px;">　　.<strong>&nbsp;抽象观察者（Observer）角色</strong>：为所有的具体观察者定义一个接口，在得到通知时更新自己；&nbsp;<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 />图3、抽象观察者角色，可以用一个抽象类或者一个接口实现；在具体的情况下也不排除使用具体类实现。</td></tr></tbody></table><p style="margin: 10px 0px;">　　.<strong>&nbsp;具体主题（ConcreteSubject）角色</strong>：保存对具体观察者对象有用的内部状态；在这种内部状态改变时给其观察者发出一个通知；具体主题角色又叫作具体被观察者角色；</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;">图4、具体主题角色，通常用一个具体子类实现。<br /><br /></span><p style="margin: 10px 0px;">．<strong>具体观察者（ConcreteObserver）角色</strong>：保存一个指向具体主题对象的引用；和一个与主题的状态相符的状态。具体观察者角色实现抽象观察者角色所要求的更新自己的接口，以便使本身的状态与主题的状态自恰。&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 />图5、具体观察者角色，通常用一个具体子类实现。</td></tr></tbody></table><span style="font-size: 12px; line-height: normal;"><br /></span><p style="margin: 10px 0px;">下面给出一个示意性实现的Java代码。首先在这个示意性的实现里，用一个Java接口实现抽象主题角色，这就是下面的Subject接口：<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 />　　这个抽象主题接口规定出三个子类必须实现的操作，即 attach() 用来增加一个观察者对象；detach() 用来删除一个观察者对象；和notifyObservers() 用来通知各个观察者刷新它们自己。抽象主题角色实际上要求子类保持一个以所有的观察者对象为元素的列表。<br /><br />　　具体主题则是实现了抽象主题Subject接口的一个具体类，它给出了以上的三个操作的具体实现。从下面的源代码可以看出，这里给出的Java实现使用了一个Java向量来保存所有的观察者对象，而 attach() 和 detach() 操作则是对此向量的元素增减操作。<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 (（Vector) observersVector.clone()).elements();<br />}<br />private Vector observersVector = new java.util.Vector();<br />}<br /></td></tr></tbody></table>代码清单2、ConcreteSubject类的源代码。&nbsp;<br />　　抽象观察者角色的实现实际上是最为简单的一个，它是一个Java接口，只声明了一个方法，即update()。这个方法被子类实现后，一被调用便刷新自己。<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()方法的实现。这个方法怎么实现与应用密切相关，因此本类只给出一个框架。<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、ConcreteObserver类的源代码。&nbsp;<br /><br />　　虽然观察者模式的实现方法可以有设计师自己确定，但是因为从AWT1.1开始视窗系统的事件模型采用观察者模式，因此观察者模式在Java语言里的地位较为重要。正因为这个原因，Java语言给出了它自己对观察者模式的支持。因此，本文建议读者在自己的系统中应用观察者模式时，不妨利用Java语言所提供的支持。<br />　　<strong>Java语言提供的对观察者模式的支持</strong><br /><br />　　在Java语言的java.util库里面，提供了一个Observable类以及一个Observer接口，构成Java语言对观察者模式的支持。<br /><br />　　<strong>Observer接口</strong><br /><br />　　这个接口只定义了一个方法，update()。当被观察者对象的状态发生变化时，这个方法就会被调用。这个方法的实现应当调用每一个被观察者对象的notifyObservers()方法，从而通知所有的观察对象。<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 />图6、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 />* 当被观察的对象发生变化时，这个方法会被调用。<br />*/<br />void update(Observable o, Object arg);<br />}<br /></td></tr></tbody></table>代码清单5、java.util.Observer接口的源代码。&nbsp;<br /><br />　　<strong>Observable类</strong><br /><br />　　被观察者类都是java.util.Observable类的子类。java.util.Observable提供公开的方法支持观察者对象，这些方法中有两个对Observable的子类非常重要：一个是setChanged()，另一个是notifyObservers()。第一个方法setChanged()被调用之后会设置一个内部标记变量，代表被观察者对象的状态发生了变化。第二个是notifyObservers()，这个方法被调用时，会调用所有登记过的观察者对象的update()方法，使这些观察者对象可以更新自己。<br /><br />　　java.util.Observable类还有其它的一些重要的方法。比如，观察者对象可以调用java.util.Observable类的addObserver()方法，将对象一个一个加入到一个列表上。当有变化时，这个列表可以告诉notifyObservers()方法那些观察者对象需要通知。由于这个列表是私有的，因此java.util.Observable的子对象并不知道观察者对象一直在观察着它们。<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 />图7、Java语言提供的被观察者的类图。</td></tr></tbody></table><br />　　被观察者类Observable的源代码：<br /><br /><span style="line-height: normal; color: #0000ff;">package</span><span style="line-height: normal;">&nbsp;java.util;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /></span><span style="line-height: normal; color: #0000ff;">public</span>&nbsp;<span style="line-height: normal; color: #0000ff;">class</span><span style="line-height: normal;">&nbsp;Observable<br /><img id="Codehighlighter1_44_1304_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /></span><span id="Codehighlighter1_44_1304_Open_Text" style="line-height: normal;">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">private</span>&nbsp;<span style="color: #0000ff;">boolean</span>&nbsp;changed&nbsp;=&nbsp;<span style="color: #0000ff;">false</span>;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">private</span>&nbsp;Vector&nbsp;obs;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_100_121_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_100_121_Open_Text"><span style="color: #008000;">/**</span><span style="color: #008000;">&nbsp;用0个观察者构造一个被观察者。*</span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;Observable()<br /><img id="Codehighlighter1_144_166_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_144_166_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;Vector();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_169_193_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;将一个观察者加到观察者列表上面。<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;addObserver(Observer&nbsp;o)<br /><img id="Codehighlighter1_244_291_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_244_291_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">if</span>&nbsp;(!obs.contains(o))<br /><img id="Codehighlighter1_268_289_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_268_289_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs.addElement(o);<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_294_320_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;将一个观察者对象从观察者列表上删除。<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;deleteObserver(Observer&nbsp;o)<br /><img id="Codehighlighter1_374_398_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_374_398_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs.removeElement(o);<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_401_434_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;相当于&nbsp;notifyObservers(null)<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;notifyObservers()<br /><img id="Codehighlighter1_466_491_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_466_491_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />notifyObservers(<span style="color: #0000ff;">null</span>);<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_494_590_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;如果本对象有变化（那时hasChanged&nbsp;方法会返回true）<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;调用本方法通知所有登记在案的观察者，即调用它们的update()方法，<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;传入this和arg作为参量。<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;notifyObservers(Object&nbsp;arg)<br /><img id="Codehighlighter1_632_861_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_632_861_Open_Text">{<br /><img id="Codehighlighter1_634_664_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;临时存放当前的观察者的状态。参见备忘录模式。<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />Object[]&nbsp;arrLocal;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">synchronized</span>&nbsp;(<span style="color: #0000ff;">this</span>)<br /><img id="Codehighlighter1_706_772_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_706_772_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">if</span>&nbsp;(!changed)&nbsp;<span style="color: #0000ff;">return</span>;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />arrLocal&nbsp;=&nbsp;obs.toArray();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />clearChanged();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">for</span>&nbsp;(<span style="color: #0000ff;">int</span>&nbsp;i&nbsp;=&nbsp;arrLocal.length-1;&nbsp;i&gt;=0;&nbsp;i--)<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />((Observer)arrLocal[i]).update(<span style="color: #0000ff;">this</span>,&nbsp;arg);<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_864_880_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;将观察者列表清空<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;deleteObservers()<br /><img id="Codehighlighter1_925_952_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_925_952_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />obs.removeAllElements();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_955_975_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;将&#8220;已变化&#8221;设为true<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">protected</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;setChanged()<br /><img id="Codehighlighter1_1018_1036_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1018_1036_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />changed&nbsp;=&nbsp;<span style="color: #0000ff;">true</span>;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_1039_1061_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;将&#8220;已变化&#8221;重置为false<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">protected</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;clearChanged()<br /><img id="Codehighlighter1_1106_1125_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1106_1125_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />changed&nbsp;=&nbsp;<span style="color: #0000ff;">false</span>;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_1128_1146_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;探测本对象是否已变化<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">boolean</span>&nbsp;hasChanged()<br /><img id="Codehighlighter1_1189_1207_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1189_1207_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">return</span>&nbsp;changed;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img id="Codehighlighter1_1210_1238_Open_Image" src="http://www.blogjava.net/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://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />*&nbsp;返还被观察对象（即此对象）的观察者总数。<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" /></span><span style="color: #008000;">*/</span></span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">synchronized</span>&nbsp;<span style="color: #0000ff;">int</span>&nbsp;countObservers()<br /><img id="Codehighlighter1_1281_1302_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_1281_1302_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">return</span>&nbsp;obs.size();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span><span style="line-height: normal;"><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /></span>代码清单6、java.util.Observer接口的源代码。&nbsp;<br /><br />　　这个Observable类代表一个被观察者对象。一个被观察者对象可以有数个观察者对象，一个观察者可以是一个实现Observer接口的对象。在被观察者对象发生变化时，它会调用Observable的notifyObservers方法，此方法调用所有的具体观察者的update()方法，从而使所有的观察者都被通知更新自己。见下面的类图：<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 />图8、使用Java语言提供的对观察者模式的支持。</td></tr></tbody></table><br />　　发通知的次序在这里没有指明。Observerable类所提供的缺省实现会按照Observers对象被登记的次序通知它们，但是Observerable类的子类可以改掉这一次序。子类并可以在单独的线程里通知观察者对象；或者在一个公用的线程里按照次序执行。&nbsp;<br /><br />　　当一个可观察者对象刚刚创立时，它的观察者集合是空的。两个观察者对象在它们的equals()方法返回true时，被认为是两个相等的对象。&nbsp;<br />　　<strong>怎样使用Java对观察者模式的支持</strong><br /><br />　　为了说明怎样使用Java所提供的对观察者模式的支持，本节给出一个非常简单的例子。在这个例子里，被观察对象叫做Watched，也就是被监视者；而观察者对象叫做Watcher。Watched对象继承自java.util.Obsevable类；而Watcher对象实现了java.util.Observer接口。另外有一个对象Tester，扮演客户端的角色。&nbsp;<br /><br />　　这个简单的系统的结构如下图所示。&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 />图9、一个使用Observer接口和Observable类的例子。</td></tr></tbody></table><br />　　在客户端改变Watched对象的内部状态时，Watched就会通知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://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">package</span>&nbsp;com.javapatterns.observer.watching;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">import</span>&nbsp;java.util.Observer;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span>&nbsp;Tester<br /><img id="Codehighlighter1_93_466_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_93_466_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">private</span>&nbsp;Watched&nbsp;watched;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">private</span>&nbsp;Observer&nbsp;watcher;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">static</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;main(String[]&nbsp;args)<br /><img id="Codehighlighter1_200_464_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_200_464_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;Watched();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watcher&nbsp;=&nbsp;<span style="color: #0000ff;">new</span>&nbsp;Watcher(watched);<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In&nbsp;C,&nbsp;we&nbsp;create&nbsp;bugs.");<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In&nbsp;Java,&nbsp;we&nbsp;inherit&nbsp;bugs.");<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In&nbsp;Java,&nbsp;we&nbsp;inherit&nbsp;bugs.");<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />watched.changeData("In&nbsp;Visual&nbsp;Basic,&nbsp;we&nbsp;visualize&nbsp;bugs.");&nbsp;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /></div></td></tr></tbody></table><br />　　代码清单7、Tester类的源代码。&nbsp;<br /><span style="line-height: normal;"><br /><br /></span>　代码清单7、Tester类的源代码。&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://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">package</span>&nbsp;com.javapatterns.observer.watching;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">import</span>&nbsp;java.util.Observable;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">class</span>&nbsp;Watched&nbsp;<span style="color: #0000ff;">extends</span>&nbsp;Observable<br /><img id="Codehighlighter1_115_319_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_115_319_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">private</span>&nbsp;String&nbsp;data&nbsp;=&nbsp;"";<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;String&nbsp;retrieveData()<br /><img id="Codehighlighter1_173_188_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_173_188_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">return</span>&nbsp;data;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">public</span>&nbsp;<span style="color: #0000ff;">void</span>&nbsp;changeData(String&nbsp;data)<br /><img id="Codehighlighter1_227_317_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_227_317_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">if</span>&nbsp;(&nbsp;!<span style="color: #0000ff;">this</span>.data.equals(&nbsp;data)&nbsp;)<br /><img id="Codehighlighter1_261_295_Open_Image" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" alt="" /><span id="Codehighlighter1_261_295_Open_Text">{<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><span style="color: #0000ff;">this</span>.data&nbsp;=&nbsp;data;<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />setChanged();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align="top" alt="" />notifyObservers();<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" alt="" />}</span><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" alt="" />}</span></div></td></tr></tbody></table><br /><br />代码清单9、Watcher类的源代码。&nbsp;<br /><br />　　可以看出，虽然客户端将Watched对象的内部状态赋值了四次，但是值的改变只有三次：<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://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In&nbsp;C,&nbsp;we&nbsp;create&nbsp;bugs.");<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In&nbsp;Java,&nbsp;we&nbsp;inherit&nbsp;bugs.");<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In&nbsp;Java,&nbsp;we&nbsp;inherit&nbsp;bugs.");<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />watched.changeData("In&nbsp;Visual&nbsp;Basic,&nbsp;we&nbsp;visualize&nbsp;bugs.");&nbsp;</div></td></tr></tbody></table><br />　　代码清单10、被观察者的内部状态发生了改变。&nbsp;<br /><br />　　对应地，Watcher对象汇报了三次改变，下面就是运行时间程序打印出的信息：<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://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />Data&nbsp;has&nbsp;been&nbsp;changed&nbsp;to:&nbsp;'In&nbsp;C,&nbsp;we&nbsp;create&nbsp;bugs.'<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />Data&nbsp;has&nbsp;been&nbsp;changed&nbsp;to:&nbsp;'In&nbsp;Java,&nbsp;we&nbsp;inherit&nbsp;bugs.'<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /><br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" />Data&nbsp;has&nbsp;been&nbsp;changed&nbsp;to:&nbsp;'In&nbsp;Visual&nbsp;Basic,&nbsp;we&nbsp;visualize&nbsp;bugs.'<br /><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align="top" alt="" /></div></td></tr></tbody></table><br />　　代码清单11、运行的结果。&nbsp;<br /><br />　<strong>菩萨的守瓶龟</strong><br /><br />　　想当年齐天大圣为解救师傅唐僧，前往南海普陀山请菩萨降伏妖怪红孩儿：&#8220;菩萨听说...恨了一声，将手中宝珠净瓶往海心里扑的一掼...只见那海当中，翻波跳浪，钻出个瓶来，原来是一个怪物驮着出来...要知此怪名和姓，兴风作浪恶乌龟。&#8221;&nbsp;<br /><br />　　使用面向对象的语言描述，乌龟便是一个观察者对象，它观察的主题是菩萨。一旦菩萨将净瓶掼到海里，就象征着菩萨作为主题调用了notifyObservers()方法。在西游记中，观察者对象有两个，一个是乌龟，另一个是悟空。悟空的反应在这里暂时不考虑，而乌龟的反应便是将瓶子驮回海岸。&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 />图10、菩萨和菩萨的守瓶乌龟。</td></tr></tbody></table><strong>Java中的DEM事件机制</strong><br /><br />　　<strong>AWT中的DEM机制</strong><br /><br />　　责任链模式一章中曾谈到，AWT1.0的事件处理的模型是基于责任链的。这种模型不适用于复杂的系统，因此在AWT1.1版本及以后的各个版本中，事件处理模型均为基于观察者模式的委派事件模型（Delegation Event Model或DEM）。&nbsp;<br /><br />　　在DEM模型里面，主题（Subject）角色负责发布（publish）事件，而观察者角色向特定的主题订阅（subscribe）它所感兴趣的事件。当一个具体主题产生一个事件时，它就会通知所有感兴趣的订阅者。&nbsp;<br /><br />　　使用这种发布-订阅机制的基本设计目标，是提供一种将发布者与订阅者松散地耦合在一起的联系形式，以及一种能够动态地登记、取消向一个发布者的订阅请求的办法。显然，实现这一构思的技巧，是设计抽象接口，并把抽象层和具体层分开。这在观察者模式里可以清楚地看到。&nbsp;<br /><br />　　使用DEM的用词，发布者叫做事件源（event source），而订阅者叫做事件聆听者（event listener）。在Java里面，事件由类代表，事件的发布是通过同步地调用成员方法做到的。&nbsp;<br /><br />　　<strong>Servlet技术中的的DEM机制</strong><br /><br />　　AWT中所使用的DEM事件模型实际上被应用到了所有的Java事件机制上。Servlet技术中的事件处理机制同样也是使用的DEM模型。&nbsp;<br /><br />　　<strong>SAX2技术中的DEM机制</strong><br /><br />　　DEM事件模型也被应用到了SAX2的事件处理机制上。&nbsp;<br /><br />　　<strong>观察者模式的效果</strong><br /><br />　　观察者模式的效果有以下的<strong>优点</strong>：&nbsp;<br /><br />　　第一、观察者模式在被观察者和观察者之间建立一个抽象的耦合。被观察者角色所知道的只是一个具体观察者列表，每一个具体观察者都符合一个抽象观察者的接口。被观察者并不认识任何一个具体观察者，它只知道它们都有一个共同的接口。&nbsp;<br /><br />　　由于被观察者和观察者没有紧密地耦合在一起，因此它们可以属于不同的抽象化层次。如果被观察者和观察者都被扔到一起，那么这个对象必然跨越抽象化和具体化层次。&nbsp;<br /><br />　　第二、观察者模式支持广播通讯。被观察者会向所有的登记过的观察者发出通知，&nbsp;<br /><br />　　观察者模式有下面的<strong>缺点</strong>：&nbsp;<br /><br />　　第一、如果一个被观察者对象有很多的直接和间接的观察者的话，将所有的观察者都通知到会花费很多时间。&nbsp;<br /><br />　　第二、如果在被观察者之间有循环依赖的话，被观察者会触发它们之间进行循环调用，导致系统崩溃。在使用观察者模式是要特别注意这一点。&nbsp;<br /><br />　　第三、如果对观察者的通知是通过另外的线程进行异步投递的话，系统必须保证投递是以自恰的方式进行的。&nbsp;<br /><br />　　第四、虽然观察者模式可以随时使观察者知道所观察的对象发生了变化，但是观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。&nbsp;<br /><br />　　<strong>观察者模式与其它模式的关系</strong><br /><br />　　观察者模式使用了备忘录模式(Memento Pattern)暂时将观察者对象存储在被观察者对象里面。<br /><br />　　<strong>问答题</strong><br /><br />　　第一题、我和妹妹跟妈妈说：&#8220;妈妈，我和妹妹在院子里玩；饭做好了叫我们一声。&#8221;请问这是什么模式？能否给出类图说明？<br /><br />　　<strong>问答题答案</strong><br /><br />　　第一题答案、这是观察者模式。我和妹妹让妈妈告诉我们饭做好了，这样我们就可以来吃饭了。换用较为技术化的语言来说，当系统的主题（饭）发生变化时，就告诉系统的其它部份（观察者们，也就是妈妈、我和妹妹），使其可以调整内部状态（有开始吃饭的准备），并采取相应的行动（吃饭）。<br /><br />　　系统的类图说明如下。<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 />图11、系统的类图。</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;">网上商店中的商品在名称、价格发生变化时，必须自动通知会员，Java的API为我们提供了Observer接口和Observable类来实现所谓观察者模式。<br />Observable(可观察者）类允许在自身发生改变时，通知其它对象（实现接口Observer，观察者）。</p><p style="margin: 0px 0px 10px; padding: 0px;">下面是一个可观察者（产品类）：<br />import java.util.*;<br />public class product extends Observable{&nbsp;<br />　　 private String name;////产品名<br />　　 private float price;////价格</p><p style="margin: 0px 0px 10px; padding: 0px;">　　 public String getName(){ return name;}<br />　　 public void setName(String name){<br />　　&nbsp; this.name=name;<br />　　 ////设置变化点&nbsp;<br />　　&nbsp; setChanged();<br />　　&nbsp; 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 />　　&nbsp; this.price=price;<br />　　 ////设置变化点<br />　　&nbsp; setChanged();<br />　　&nbsp; notifyObservers(new Float(price));</p><p style="margin: 0px 0px 10px; padding: 0px;">　　 }</p><p style="margin: 0px 0px 10px; padding: 0px;">　　 ////以下可以是数据库更新 插入命令.<br />　　 public void saveToDb(){<br />　　 System.out.println("saveToDb");<br />&nbsp;&nbsp;&nbsp; }</p><p style="margin: 0px 0px 10px; padding: 0px;">}</p><p style="margin: 0px 0px 10px; padding: 0px;">下面是两个观察者：<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 />　　　　&nbsp; name=(String)arg;<br />　　　　&nbsp; ////产品名称改变值在name中<br />　　　　&nbsp; 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;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<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;">　　　　&nbsp; price=((Float)arg).floatValue();<br />　　<br />　　　　&nbsp; 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 />下面是测试类：<br />public class Test {</p><p style="margin: 0px 0px 10px; padding: 0px;">　　 public static void main(String args[]){<br />&nbsp;&nbsp;&nbsp; Product product=new Product();<br />&nbsp;&nbsp;&nbsp; NameObserver nameobs=new NameObserver();<br />&nbsp;&nbsp;&nbsp; PriceObserver priceobs=new PriceObserver();</p><p style="margin: 0px 0px 10px; padding: 0px;">&nbsp;&nbsp;&nbsp; ////加入观察者<br />&nbsp;&nbsp;&nbsp; product.addObserver(nameobs);<br />&nbsp;&nbsp;&nbsp; product.addObserver(priceobs);</p><p style="margin: 0px 0px 10px; padding: 0px;">&nbsp;&nbsp;&nbsp; product.setName("applet");<br />&nbsp;&nbsp;&nbsp; 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>&nbsp;</p></div><img src ="http://www.blogjava.net/qileilove/aggbug/392774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-11 11:51 <a href="http://www.blogjava.net/qileilove/archive/2012/12/11/392774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝大哥学设计模式-单例模式</title><link>http://www.blogjava.net/qileilove/archive/2012/12/07/392604.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Fri, 07 Dec 2012 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2012/12/07/392604.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392604.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/07/392604.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392604.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392604.html</trackback:ping><description><![CDATA[<span style="color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;">概念：</span><span style="margin: 0px; padding: 0px; color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;"><br style="margin: 0px; padding: 0px;" /></span><span style="color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;">　　</span><span style="margin: 0px; padding: 0px; color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;">java</span><span style="color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;">中单例模式是一种常见的设计模式，</span><span style="margin: 0px; padding: 0px; font-family: 宋体; line-height: 25px; background-color: #ffffff; color: #800000;">单例模式分三种：懒汉式单例、饿汉式单例、登记式单例三种。<br /><span style="margin: 0px; padding: 0px;">哈哈 我们可以这样分 屌丝单例模式：懒汉式屌丝单例，饿汉式屌丝单例，登记式屌丝单例。<br /><br style="margin: 0px; padding: 0px;" /></span></span><span style="color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;">　　</span><span style="margin: 0px; padding: 0px; font-family: 宋体; line-height: 25px; background-color: #ffffff; color: #ff6600;">单例模式有一下特点：<span style="margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /></span></span><span style="color: #333333; font-family: 宋体; line-height: 25px; background-color: #ffffff;">　　</span><span style="margin: 0px; padding: 0px; font-family: 宋体; line-height: 25px; background-color: #ffffff; color: #008000;"><span style="margin: 0px; padding: 0px;">1</span>、单例类只能有一个实例。<span style="margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /></span>　　<span style="margin: 0px; padding: 0px;">2</span>、单例类必须自己自己创建自己的唯一实例。<span style="margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /></span>　　<span style="margin: 0px; padding: 0px;">3</span>、单例类必须给所有其他对象提供这一实例。<br /></span><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif;"><span style="margin: 0px; padding: 0px; font-family: 宋体;"><span style="margin: 0px; padding: 0px; color: #008000;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: black;"><span size="3" style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #800000;">单例模式确保某个类只有一个实例，而且自行实例化并向整个系统提供这个实例。</span><span style="margin: 0px; padding: 0px;">在计算机系统中，线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机，但只能有一个</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif;">Printer Spooler</span><span style="margin: 0px; padding: 0px;">，以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口，系统应当集中管理这些通信端口，以避免一个通信端口同时被两个请求同时调用。总之，选择单例模式就是为了避免不一致状态，避免政出多头。</span><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #008000;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: black;"><span size="3" style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #008000;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: black;"><span size="3" style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; color: #008000;"></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif;"></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif;"></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif;"></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif;"></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; text-indent: 21pt; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 15.05pt;"><span style="margin: 0px; padding: 0px; font-family: 宋体;">首先看一个经典的单例实现。<br /><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">public</span></strong>&nbsp;<strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">class</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;Singleton {</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">private</span></strong>&nbsp;<strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">static</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;Singleton&nbsp;</span><em style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #0000c0; font-size: 10pt;">uniqueInstance</span></em><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;=&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">null</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">;</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">private</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;Singleton() {</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #3f7f5f; font-size: 10pt;">// Exists only to defeat instantiation.</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp; }</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;">&nbsp;</p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">public</span></strong>&nbsp;<strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">static</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;Singleton getInstance() {</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">if</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;(</span><em style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #0000c0; font-size: 10pt;">uniqueInstance</span></em><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;==&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">null</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">) {</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><em style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #0000c0; font-size: 10pt;">uniqueInstance</span></em><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;=&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">new</span></strong><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;Singleton();</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #7f0055; font-size: 10pt;">return</span></strong>&nbsp;<em style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #0000c0; font-size: 10pt;">uniqueInstance</span></em><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">;</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp; }</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: #3f7f5f; font-size: 10pt;">// Other methods...</span></p><p align="left" style="margin: 0cm 0cm 0pt 21pt; padding: 0px; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff;"><span style="margin: 0px; padding: 0px; font-family: 'Courier New'; color: black; font-size: 10pt;">}<br /><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; text-indent: 21pt; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 15.05pt;"><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif; color: black;">Singleton</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">通过将构造方法限定为</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif; color: black;">private</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">避免了类在外部被实例化，在同一个虚拟机范围内，</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif; color: black;">Singleton</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">的唯一实例只能通过</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif; color: black;">getInstance()</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">方法访问。（事实上，<span style="margin: 0px; padding: 0px; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">通过</strong></span></span><span style="margin: 0px; padding: 0px; color: #0000ff;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif;">Java</span><span style="margin: 0px; padding: 0px; font-family: 宋体;">反射机制是能够实例化构造方法为</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif;">private</span><span style="margin: 0px; padding: 0px; font-family: 宋体;">的类的，那基本上会使所有的</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif;">Java</span></strong></span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;"><span style="margin: 0px; padding: 0px; color: #0000ff;"><strong style="margin: 0px; padding: 0px;">单例实现失效。</strong></span>此问题在此处不做讨论，姑且掩耳盗铃地认为反射机制不存在。）</span></p><p align="left" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; text-indent: 21pt; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; font-size: 14px; line-height: 15.05pt;"><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">但是以上实现没有考虑线程安全问题。所谓线程安全是指：如果你的代码所在的进程中有多个线程在同时运行，而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的，而且其他的变量的值也和预期的是一样的，就是线程安全的。或者说：一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif; color: black;">,</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求，在并发环境下很可能出现多个</span><span style="margin: 0px; padding: 0px; font-family: Arial, sans-serif; color: black;">Singleton</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: black;">实例。<br /><div></div><div>public class TestDiaoSiStream {</div><div>&nbsp; &nbsp; &nbsp;private String DiaoSiname;</div><div>&nbsp; &nbsp; &nbsp;public String getDiaoSiname() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return DiaoSiname;</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp;public void setDiaoSiname(String DiaoSiname) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.DiaoSiname = DiaoSiname;</div><div>&nbsp; &nbsp; &nbsp;}&nbsp;</div><div>&nbsp; &nbsp; &nbsp;//该类只能有一个实例</div><div>&nbsp; &nbsp; &nbsp;private TestDiaoSiStream(){} &nbsp; &nbsp;//私有无参构造方法</div><div>&nbsp; &nbsp; &nbsp;//该类必须自行创建</div><div>&nbsp; &nbsp; &nbsp;//有2种方式</div><div>&nbsp; &nbsp; &nbsp;/*private static final TestDiaoSiStream ds=new TestDiaoSiStream();*/</div><div>&nbsp; &nbsp; &nbsp;private static TestDiaoSiStream ds1=null;</div><div>&nbsp; &nbsp; &nbsp;//这个类必须自动向整个系统提供这个实例对象</div><div>&nbsp; &nbsp; &nbsp;public static TestDiaoSiStream getTestDiaoSiTest(){</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(ds1==null){</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ds1=new TestDiaoSiStream();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return ds1;</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp;public void getInfo(){</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println("output message "+DiaoSiname);</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp;}<br /><br /><div></div><div>public class TestMain {</div><div>&nbsp; &nbsp; &nbsp;public static void main(String [] args){</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TestDiaoSiStream &nbsp;ds=TestDiaoSiStream.getTestDiaoSiTest();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ds.setDiaoSiname("奶娃");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println(ds.getDiaoSiname());</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TestDiaoSiStream ds1=TestDiaoSiStream.getTestDiaoSiTest();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ds1.setDiaoSiname("奶娃");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println(ds1.getDiaoSiname());</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ds.getInfo();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ds1.getInfo();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(ds==ds1){</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println("创建的是同一个屌丝实例");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}else if(ds!=ds1){</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println("创建的不是同一个屌丝实例");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}else{</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println("application error");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp;}<br /><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px;">运行结果：<br style="margin: 0px; padding: 0px;" />　　<span style="color: #000000; font-family: 宋体; line-height: 20.066667556762695px; text-indent: 28px;">奶娃</span><br />　　<span style="color: #000000; font-family: 宋体; line-height: 20.066667556762695px; text-indent: 28px;">奶娃</span><br />　　output message&nbsp;<span style="color: #000000; font-family: 宋体; line-height: 20.066667556762695px; text-indent: 28px;">奶娃</span><br />　　output message&nbsp;<span style="color: #000000; font-family: 宋体; line-height: 20.066667556762695px; text-indent: 28px;">奶娃</span><br />　　创建的是同一个<span style="color: #000000; font-family: 宋体; line-height: 20.066667556762695px; text-indent: 28px;">屌丝</span><br />实例</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px;">结论：由结果可以得知<span style="margin: 0px; padding: 0px; font-family: 宋体;">单例模式为一个面向对象的应用程序提供了对象惟一的访问点，不管它实现何种功能，<span style="margin: 0px; padding: 0px; color: #800000;">整个应用程序都会同享一个实例对象</span>。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px;"><span style="margin: 0px; padding: 0px; font-family: Tahoma; color: #4d4d4d; font-size: 11pt;">1.</span><span style="margin: 0px; padding: 0px; font-family: 宋体; color: #4d4d4d; font-size: 11pt;">饿汉式单例类<br /><br /><div>//饿汉式单例类.在类初始化时，已经自行实例化&nbsp;</div><div>&nbsp;public class Singleton1 {</div><div>&nbsp; &nbsp; &nbsp;//私有的默认构造子</div><div>&nbsp; &nbsp; &nbsp;private Singleton1() {}</div><div>&nbsp; &nbsp; &nbsp;//已经自行实例化&nbsp;</div><div>&nbsp; &nbsp; &nbsp;private static final Singleton1 single = new Singleton1();</div><div>&nbsp; &nbsp; &nbsp;//静态工厂方法&nbsp;</div><div>&nbsp; &nbsp; &nbsp;public static Singleton1 getInstance() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return single;</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp;}<br /><br /><span style="margin: 0px; padding: 0px; font-family: Tahoma; font-size: 11pt;">2.</span><span style="margin: 0px; padding: 0px; font-size: 11pt;">懒汉式单例类</span><br /><div>//懒汉式单例类.在第一次调用的时候实例化&nbsp;</div><div>&nbsp;public class Singleton2 {</div><div>&nbsp; &nbsp; &nbsp;//私有的默认构造子</div><div>&nbsp; &nbsp; &nbsp;private Singleton2() {}</div><div>&nbsp; &nbsp; &nbsp;//注意，这里没有final &nbsp; &nbsp;</div><div>&nbsp; &nbsp; &nbsp;private static Singleton2 single=null;</div><div>&nbsp; &nbsp; &nbsp;//静态工厂方法&nbsp;</div><div>&nbsp; &nbsp; &nbsp;public synchronized &nbsp;static Singleton2 getInstance() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (single == null) { &nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; single = new Singleton2();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return single;</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp;}<br /><span style="margin: 0px; padding: 0px; font-size: 11pt; line-height: 26px; font-family: Tahoma;">3.</span><span style="margin: 0px; padding: 0px; font-size: 11pt; line-height: 26px;">登记式单例类<br /><br /></span><div>import java.util.HashMap;</div><div>&nbsp;import java.util.Map;</div><div>&nbsp;//登记式单例类.</div><div>&nbsp;//类似Spring里面的方法，将类名注册，下次从里面直接获取。</div><div>&nbsp;public class Singleton3 {</div><div>&nbsp; &nbsp; &nbsp;private static Map&lt;String,Singleton3&gt; map = new HashMap&lt;String,Singleton3&gt;();</div><div>&nbsp; &nbsp; &nbsp;static{</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Singleton3 single = new Singleton3();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;map.put(single.getClass().getName(), single);</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp;//保护的默认构造子</div><div>&nbsp; &nbsp; &nbsp;protected Singleton3(){}</div><div>&nbsp; &nbsp; &nbsp;//静态工厂方法,返还此类惟一的实例</div><div>&nbsp; &nbsp; &nbsp;public static Singleton3 getInstance(String name) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(name == null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;name = Singleton3.class.getName();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println("name == null"+"---&gt;name="+name);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(map.get(name) == null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;map.put(name, (Singleton3) Class.forName(name).newInstance());</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} catch (InstantiationException e) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;e.printStackTrace();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} catch (IllegalAccessException e) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;e.printStackTrace();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} catch (ClassNotFoundException e) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;e.printStackTrace();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return map.get(name);</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp; &nbsp; &nbsp;//一个示意性的商业方法</div><div>&nbsp; &nbsp; &nbsp;public String about() { &nbsp; &nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return "Hello, I am RegSingleton."; &nbsp; &nbsp;</div><div>&nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;</div><div>&nbsp; &nbsp; &nbsp;public static void main(String[] args) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Singleton3 single3 = Singleton3.getInstance(null);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.println(single3.about());</div><div>&nbsp; &nbsp; &nbsp;}</div><div>&nbsp;}<br /><br /></div></div></div></span></p></div><div></div></div><div></div></span></p></span></p></span></p><img src ="http://www.blogjava.net/qileilove/aggbug/392604.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-07 14:55 <a href="http://www.blogjava.net/qileilove/archive/2012/12/07/392604.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>跟屌丝学设计模式之责任链模式</title><link>http://www.blogjava.net/qileilove/archive/2012/12/06/392531.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Thu, 06 Dec 2012 03:19:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2012/12/06/392531.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392531.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/06/392531.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392531.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392531.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JAVA之责任链模式原文地址：http://itzyx.com/index.php/java_zrl/在阎宏博士的《JAVA与模式》一书中开头是这样描述责任链（Chain&nbsp;of&nbsp;Responsibility）模式的：&nbsp;　　责任链模式是一种对象的行为模式。在责任链模式里，很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递，直到链上的某一个对象决定...&nbsp;&nbsp;<a href='http://www.blogjava.net/qileilove/archive/2012/12/06/392531.html'>阅读全文</a><img src ="http://www.blogjava.net/qileilove/aggbug/392531.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-06 11:19 <a href="http://www.blogjava.net/qileilove/archive/2012/12/06/392531.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java设计模式-桥接模式（屌丝男学设计模式）</title><link>http://www.blogjava.net/qileilove/archive/2012/12/05/392498.html</link><dc:creator>顺其自然EVO</dc:creator><author>顺其自然EVO</author><pubDate>Wed, 05 Dec 2012 08:21:00 GMT</pubDate><guid>http://www.blogjava.net/qileilove/archive/2012/12/05/392498.html</guid><wfw:comment>http://www.blogjava.net/qileilove/comments/392498.html</wfw:comment><comments>http://www.blogjava.net/qileilove/archive/2012/12/05/392498.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/qileilove/comments/commentRss/392498.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/qileilove/services/trackbacks/392498.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana;">本文介绍设计模式中的桥接（<a href="http://space.itpub.net/?uid-9399028-action-viewspace-itemid-687882" target="_self" style="color: #336699; text-decoration: initial;"><span style="text-decoration: underline;"><strong>Bridge</strong></span></a>）模式的概念，用法，以及实际应用中怎么样使用<a href="http://space.itpub.net/?uid-9399028-action-viewspace-itemid-687882" target="_self" style="color: #336699; text-decoration: initial;"><span style="text-decoration: underline;"><strong>桥接模式</strong></span></a>进行开发。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana;"><strong>Bridge模式的概念</strong></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: Verdana;">Bridge 模式是构造型的设计模式之一。Bridge模式基于类的最小设计原则，通过使用封装，聚合以及继承等行为来让不同的类承担不同的责任。它的主要特点是把抽象（abstraction）与行为实现（implementation）分离开来，从而可以保持各部分的独立性以及应对它们的功能扩展。<br /><br /></span></p><p><strong>Bridge模式的应用场景</strong></p><p>面向对象的程序设计（OOP）里有类继承（子类继承父类）的概念，如果一个类或接口有多个具体实现子类，如果这些子类具有以下特性：<br />- 存在相对并列的子类属性。<br />- 存在概念上的交叉。<br />- 可变性。<br />我们就可以用Bridge模式来对其进行抽象与具体，对相关类进行重构。<br /><br /></p><p>为了容易理解，我们举例说明一下，比如屌丝（DiaoSi），假设有2个子类，男屌丝类（ManDiaoSi）与女屌丝类（WomanDiao），它们有[穷挫矮]这个动作行为，通过不同穷挫矮特征的设置，可以将它们设置为比如为<span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">拥有</span>黑木耳男屌丝或（拥有撸管王的女屌丝），和拥有紫木耳男屌丝或（拥有撸神的女屌丝）的各种屌丝。<br />这样，不管是黑木耳男屌丝还是紫木耳男屌丝，又或是有撸管王的女屌丝还是有撸神的女屌丝，它们都可以是屌丝类的子类，而且：<br />- 存在相对并列的子类属性。屌丝的种类，与屌丝穷挫矮的规格是屌丝的2个并列的属性，没有概念上的重复。<br />- 存在概念上的交叉。不管是男屌丝还是女屌丝，都是穷挫矮，黑穷丑的屌丝。<br />- 可变性。除了男屌丝，女屌丝之外，可能还有人妖屌丝；除了有黑木耳（撸管王）与紫木耳（撸神）特征的屌丝之外，还可能有紫黑木耳（撸圣）的屌丝等等。</p><p>这样一来，我们怎么来设计屌丝类呢？<br /><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>方法一</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">通过继承设计所有可能存在的子类。可能我们会想到下面的这种继承关系：<br />屌丝总类：DiaoSi<br />屌丝子类 - 按种类分类：<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">ManDiaoSi</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao</span><br />屌丝子类 - 按特征分类：拥有<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">黑木耳男屌丝</span>，拥有<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的女屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳男屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有撸神的女屌丝</span><br />这样设置特征这个动作就由各个子类加以实现。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">但如果以后需要增加一种<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">人妖屌丝</span>（GuyDiaoSi），以及增加一个特征规格紫黑木耳，需要实现的子类将会有：<br /><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有黑木耳男屌丝</span>，拥有<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的女屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳男屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有撸神的女屌丝 &nbsp;</span><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫黑木耳男屌丝&nbsp;</span>拥有<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的人妖屌丝&nbsp;</span><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫黑木耳人妖屌丝&nbsp;</span><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳人妖屌丝</span><br />&nbsp;等等。<br />也就是说，这种设计方法，子类数目将随几何级数增长。<br />而且，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有黑木耳男屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳人妖屌丝</span>的特征规格相同，它们的特征设置动作应该是一样的，但现在把它们分成不同的子类，难以避免执行重复的动作行为。</p><p>&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>方法二</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">分别为男屌丝以及女屌丝实现设置不同特征的方法<br />屌丝总类：DiaoSi<br />屌丝子类：<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">ManDiaoSi</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">然后在男屌丝类里分别提供黑木耳（撸管王）以及紫木耳（撸神）特征的设置方法：<br /><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">ManDiaoSi&nbsp;</span>extends&nbsp;DiaoSi<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp; public set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>黑木耳();<br />&nbsp;&nbsp;&nbsp; public&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>紫木耳();<br />}</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">在女屌丝类里也分别提供撸管王以及撸神特征的设置方法：<br /><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao&nbsp;</span>extends&nbsp;DiaoSi<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp; public&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>撸管王();<br />&nbsp;&nbsp;&nbsp; public&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>撸神();<br />}<br /><br />这种情况，子类的数量是被控制了。但一方面，如果每增加一种特征规格，需要修改所有的屌丝子类；另一方面，即使特征的设置行为一样，但是不同的屌丝子类却需要提供完全一样的方法。<br /></p><p>在实际的应用开发中，以上2种方法都会造成迁一发而动全身，而且会存在大量的重复代码。</p><p>Bridge模式可以很好的解决这类问题。<br />Client<br />&nbsp;&nbsp;&nbsp; Bridge模式的使用者<br />Abstraction<br />&nbsp;&nbsp;&nbsp; 抽象类接口（接口或抽象类）<br />&nbsp;&nbsp;&nbsp; 维护对行为实现（Implementor）的引用<br />Refined Abstraction<br />&nbsp;&nbsp;&nbsp; Abstraction子类<br />Implementor<br />&nbsp;&nbsp;&nbsp; 行为实现类接口 (Abstraction接口定义了基于Implementor接口的更高层次的操作)<br />ConcreteImplementor<br />&nbsp;&nbsp;&nbsp; Implementor子类<br /></p><p>&nbsp;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><strong>Bridge模式的应用范例</strong></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">我们来看看怎么应用Bridge模式来设计汽车类。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">抽象 - Abstraction类：屌丝类及其子类：<br />屌丝总类：DiaoSi<br />屌丝子类 - 按种类分类：<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">ManDiaoSi</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao</span><br />屌丝子类 - 按特征分类：拥有<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">黑木耳男屌丝</span>，拥有<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">撸管王的女屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有紫木耳男屌丝</span>，<span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">拥有撸神的女屌丝</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">行为实现 - Implementor：屌丝特征设置的行为类及子类<br />&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>：屌丝特征的设置接口<br />&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>黑木耳();<br />set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>紫木耳();</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">代码：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">//测试</p><p style="background-color: #ffffff;"><span style="color: #333333; font-family: Arial; line-height: 26px;">public class Client<br />{<br />&nbsp;&nbsp;&nbsp; public static void main( String[] argv )<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span>黑木耳= new &nbsp;男屌丝特征();<br /><br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span><span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">紫</span>木耳= new &nbsp;</span><font face="arial, 宋体" size="3"><span style="line-height: 20px; white-space: pre-wrap;">女屌丝特征</span></font><font color="#333333" face="Arial"><span style="line-height: 26px;">();</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span></font><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">DiaoSi&nbsp;</span><font color="#333333" face="Arial"><span style="line-height: 26px;">拥有黑木耳的男屌丝= new &nbsp;ManDiaoSi(&nbsp;黑木耳&nbsp;);</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;</span></font><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">DiaoSi&nbsp;</span><font color="#333333" face="Arial"><span style="line-height: 26px;">拥有紫木耳的男屌丝= new &nbsp;ManDiaoSi(&nbsp;紫木耳&nbsp;);</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;拥有黑木耳的男屌丝.set</span></font><span style="color: #000000; font-family: arial, 宋体; line-height: 20px; font-size: 16px; white-space: pre-wrap; background-color: #ffff00;">Features</span><font color="#333333" face="Arial"><span style="line-height: 26px;">();</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;拥有紫木耳的男屌丝.set</span></font><span style="color: #000000; font-family: arial, 宋体; line-height: 20px; font-size: 16px; white-space: pre-wrap; background-color: #ffff00;">Features</span><font color="#333333" face="Arial"><span style="line-height: 26px;">();</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;DiaoSi&nbsp;拥有黑木耳的女屌丝= new&nbsp;</span></font><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao</span><font color="#333333" face="Arial"><span style="line-height: 26px;">( 黑木耳 );</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Vehicle&nbsp;拥有紫木耳的女屌丝= new&nbsp;</span></font><span style="color: #000000; font-family: verdana, 'courier new'; line-height: 21px;">WomanDiao</span><font color="#333333" face="Arial"><span style="line-height: 26px;">( 紫木耳 );</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp;&nbsp;拥有黑木耳的女屌丝.set</span></font><span style="color: #000000; font-family: arial, 宋体; line-height: 20px; font-size: 16px; white-space: pre-wrap; background-color: #ffff00;">Features</span><font color="#333333" face="Arial"><span style="line-height: 26px;">();</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;拥有紫木耳的女屌丝.set</span></font><span style="color: #000000; font-family: arial, 宋体; line-height: 20px; font-size: 16px; white-space: pre-wrap; background-color: #ffff00;">Features</span><font color="#333333" face="Arial"><span style="line-height: 26px;">();</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; &nbsp; &nbsp;</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">&nbsp; &nbsp; }</span></font><br /><font color="#333333" face="Arial"><span style="line-height: 26px;">}</span></font></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br />&nbsp;*<br />&nbsp;* @author<br />&nbsp;* @since 2012/12/05<br />&nbsp;*/<br />public abstract class DiaoSi<br />{<br />&nbsp;&nbsp;&nbsp; private&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span><span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; Vehicle(&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span><span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span>(&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; public abstract void&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>();</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; public void&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>(&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span><span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>=&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>;<br />&nbsp;&nbsp;&nbsp; }</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; public&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span>get<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span>;<br />&nbsp;&nbsp;&nbsp; }<br />}</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">//Abstraction子类：这里为屌丝抽象类的子类</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">public class ManDiaoSi extends DiaoSi<br />{<br />&nbsp;&nbsp;&nbsp; public&nbsp;ManDiaoSi&nbsp;(<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span><span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span><br />)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super( <span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span><br />&nbsp;);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; public void&nbsp;set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>()<br />&nbsp; &nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.print("男屌丝的特征: ");<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;get<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>.set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>();<br />&nbsp; &nbsp; }<br />}</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">//Abstraction子类：这里为屌丝抽象类的子类</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">public class WomanDiaoSi extends DiaoSi<br />{<br />&nbsp;&nbsp;&nbsp; public&nbsp;WomanDiaoSi&nbsp;(&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features </span><span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span><br />&nbsp;)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">features</span><br />);<br />&nbsp;&nbsp;&nbsp; }</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; public void&nbsp; set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>()<br />&nbsp; &nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.print("女屌丝的特征: ");<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;get<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>().se<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>();<br />&nbsp;&nbsp;&nbsp; }</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">}</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">//屌丝类的行为接口</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">public interface&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span><br />{<br />&nbsp;&nbsp;&nbsp; public void set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>();<br />}</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package&nbsp;ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">/** ConcreteImplementor */<br />//行为实现子类</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">public class 男屌丝特征 implements&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span><br />{</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; public void set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("黑木耳 或者 撸管王");<br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />}</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">package ITfarmer.designpatterns.study.bridge;</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">/** ConcreteImplementor */<br />//行为实现子类</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">public class &nbsp;女屌丝特征&nbsp;implements&nbsp;<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span><br />{</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp; public void set<span style="color: #000000; font-family: arial, 宋体; font-size: 16px; line-height: 20px; white-space: pre-wrap; background-color: #ffff00;">Features</span>()<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("黑木耳 或者 撸管王");<br />&nbsp; &nbsp; }&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />}</p><span style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">小结：Bridge模式是一种抽象与其实现相分离的模式。它主要应用于：当事物是一组变化量，和对这些事物的操作方法(实现)也是一组变化量的情况，也就是说它们都是多变的。</span><br /><p>&nbsp;</p><img src ="http://www.blogjava.net/qileilove/aggbug/392498.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/qileilove/" target="_blank">顺其自然EVO</a> 2012-12-05 16:21 <a href="http://www.blogjava.net/qileilove/archive/2012/12/05/392498.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>