﻿<?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-xhchc</title><link>http://www.blogjava.net/xhchc/</link><description>危波帆墙,笑谈只在桃花上;与谁共尚,风吹万里浪;
相依相偎,不做黄泉想;莫惆怅,碧波潮生,一萧自狂放……</description><language>zh-cn</language><lastBuildDate>Mon, 18 May 2026 16:04:45 GMT</lastBuildDate><pubDate>Mon, 18 May 2026 16:04:45 GMT</pubDate><ttl>60</ttl><item><title>Struts2.0 文件上传与下载全解析（转）</title><link>http://www.blogjava.net/xhchc/archive/2009/05/26/278000.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Tue, 26 May 2009 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/05/26/278000.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/278000.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/05/26/278000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/278000.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/278000.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: struts的上传封装的已经非常完美了，首先我们来看一下页面&nbsp;&nbsp;&nbsp;&nbsp;&lt;s:form&nbsp;action="saveDocument.action"&nbsp;method="post"&nbsp;enctype&nbsp;="multipart/form-data"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.blogjava.net/xhchc/archive/2009/05/26/278000.html'>阅读全文</a><img src ="http://www.blogjava.net/xhchc/aggbug/278000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-05-26 14:21 <a href="http://www.blogjava.net/xhchc/archive/2009/05/26/278000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts 2中的OGNL (转)</title><link>http://www.blogjava.net/xhchc/archive/2009/04/16/265995.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Thu, 16 Apr 2009 08:32:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/04/16/265995.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/265995.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/04/16/265995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/265995.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/265995.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本人是一个EL（Expression Language，以下译为表达式语言）的支持者。因为我对&lt;% %&gt;写法极为反感，忘记了在那本书上看到的一句话——&#8220;使用标志（Tag）的一个目的就是避免在JSP页面中出现过多的&lt;%%&gt;的语句，使页面与后台代码分离。&#8221;表达式语言主要有以下几大好处：    避免(MyType) request.getAtt...&nbsp;&nbsp;<a href='http://www.blogjava.net/xhchc/archive/2009/04/16/265995.html'>阅读全文</a><img src ="http://www.blogjava.net/xhchc/aggbug/265995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-04-16 16:32 <a href="http://www.blogjava.net/xhchc/archive/2009/04/16/265995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring ibatis struts2的基本配置和使用(连接)</title><link>http://www.blogjava.net/xhchc/archive/2009/04/03/263817.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Fri, 03 Apr 2009 12:50:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/04/03/263817.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/263817.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/04/03/263817.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/263817.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/263817.html</trackback:ping><description><![CDATA[<br />
http://blog.csdn.net/peihexian/archive/2008/12/09/3486042.aspx<br />
<br />
<br />
http://www.wwoon.com/www/15/2008-12/8031.html<br />
<br />
<br />
http://www.busfly.cn/post/dolphin-struts-spring-javabus.html<br />
<br />
<br />
http://www.blogjava.net/seeckt/archive/2008/05/12/114809.html 
<img src ="http://www.blogjava.net/xhchc/aggbug/263817.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-04-03 20:50 <a href="http://www.blogjava.net/xhchc/archive/2009/04/03/263817.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>给Spring初学者的学习建议(转)</title><link>http://www.blogjava.net/xhchc/archive/2009/03/13/259500.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Fri, 13 Mar 2009 03:57:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/03/13/259500.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/259500.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/03/13/259500.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/259500.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/259500.html</trackback:ping><description><![CDATA[<span onmouseup="NewHighlight(event)" class="wenzhang_con" id="articlecontent" style="width: 780px"><br />
原文出自：http://www.360doc.com/content/050912/19/1330_12098.html<br />
&nbsp;
<p style="text-indent: 15.75pt"><span style="font-family: 宋体">最近有人问我学习</span><span lang="EN-US">Spring</span><span style="font-family: 宋体"><clk>的<nobr oncontextmenu="return false" onmousemove="kwM(1)" id="clickeyekey1" onmouseover="kwE(event,1, this)" style="color: #6600ff; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline" onclick='kwC(event,1,"")' onmouseout="kwL(event,this)">经验</nobr>。心中不免有些惭愧，本来以为自己对</clk></span><span lang="EN-US">Spring</span><span style="font-family: 宋体">算比较精通啦，但最近看</span><span lang="EN-US">Professional Java development with SpringFramework</span><span style="font-family: 宋体">，发现其实自己还有好多东西不知道。不过既然有人问起，就大概谈一下体会吧，由于我自己的途径与下面所列的步骤还是有些差距的（主要是当时关于</span><span lang="EN-US">Spring</span><span style="font-family: 宋体"><clk>的书和参考资料太少了），而且每个人的<nobr oncontextmenu="return false" onmousemove="kwM(2)" id="clickeyekey2" onmouseover="kwE(event,2, this)" style="color: #6600ff; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline" onclick='kwC(event,2,"")' onmouseout="kwL(event,this)">学习</nobr>方式也会不同，所以只能作为参考了。</clk></span></p>
<br />
<p style="text-indent: -21pt"><span style="font-family: 宋体"><font face="Times New Roman"></font></span></p>
<p style="text-indent: -21pt"><span style="font-family: 宋体"><font face="Times New Roman">一 一、</font>首先</span><span lang="EN-US">Java</span><span style="font-family: 宋体">的基础、面向对象的基础和设计模式的基础知识是必不可少的。</span></p>
<p><span style="font-family: 宋体">如果连这些基础知道都不够扎实的话，我建议还是先去补补课。关于设计模式我觉得不用学太多，但以下三个模式是学习</span><span lang="EN-US">Spring</span><span style="font-family: 宋体">必不可少的：</span><span lang="EN-US">factory</span><span style="font-family: 宋体">模式（包括简单工厂和抽象工厂），</span><span lang="EN-US">Strategy</span><span style="font-family: 宋体">模式，</span><span lang="EN-US">Template method</span><span style="font-family: 宋体">模式。如果不掌握这些你就根本没法领悟</span><span lang="EN-US">Spring</span><span style="font-family: 宋体">的精髓，只能依样画葫芦地照搬，这是很可怕的事。</span></p>
<p><span style="font-family: 宋体">关于这方面的书的建议已经够多的，我就不说了。我这里强烈建议的书可能让人有点意外，那就是</span><span lang="EN-US">Expert one on one J2EE design and development</span><span style="font-family: 宋体">的第四章，这一章不仅仅是</span><span lang="EN-US">Spring</span><span style="font-family: 宋体">初学者，而是任何搞</span><span lang="EN-US">Java</span><span style="font-family: 宋体">开发的人必读的一章。经典！</span></p>
<p>
<p><span style="font-family: 宋体">二、接下可以看一些</span><span lang="DA">Spring</span><span style="font-family: 宋体">的入门书籍</span></p>
<p><span style="font-family: 宋体">其实我自己没怎么看过这方面的书，我当时只看过</span><span lang="DA">Spring</span><span style="font-family: 宋体">的</span><span lang="DA">reference</span><span style="font-family: 宋体">，不过现在这方面的书好象多的是，而</span><span lang="DA">Spring reference</span><span style="font-family: 宋体">看起来还是有些吃力的。</span><span lang="DA">JavaEye</span><span style="font-family: 宋体">上很多人建议</span><span lang="DA"><a href="http://www.xiaxin.net/Spring_Dev_Guide.rar"><span lang="EN-US" style="font-family: 宋体"><span lang="EN-US">夏昕的</span></span>Spring<span lang="EN-US" style="font-family: 宋体"><span lang="EN-US">开发指南</span></span></a></span><span style="font-family: 宋体">，据说入门很容易。另外的入门书应该是</span><span lang="DA">Spring live</span><span style="font-family: 宋体">或</span><span lang="DA">Spring in action</span><span style="font-family: 宋体">。我大概扫了一下，</span><span lang="DA">Spring live</span><span style="font-family: 宋体">是一本只讲怎么做而不讲为什么的书，我不太喜欢（偶尔参考一下倒不错），不过有些人特别喜欢这样的书，看自己的个人爱好吧。</span></p>
<p>
<p><span style="font-family: 宋体">三、研究几个用</span><span lang="DA">Spring</span><span style="font-family: 宋体">做的开源项目</span></p>
<p><span style="font-family: 宋体"><clk>理论还是要与实际结合，所以看完书后是要看实际的<nobr oncontextmenu="return false" onmousemove="kwM(0)" id="clickeyekey0" onmouseover="kwE(event,0, this)" style="color: #6600ff; border-bottom: #6600ff 1px dotted; background-color: transparent; text-decoration: underline" onclick='kwC(event,0,"")' onmouseout="kwL(event,this)">项目</nobr>的。很多人喜欢</clk></span><span lang="DA">appfuse</span><span style="font-family: 宋体">，我觉得</span><span lang="DA">appfuse</span><span style="font-family: 宋体">花的东西太多，真正实质性的内容又太少。我更喜欢</span><span lang="DA">Spring</span><span style="font-family: 宋体">自带的</span><span lang="DA">jpetstore</span><span style="font-family: 宋体">，这是一个非常完整的例子，看完后</span><span lang="DA">Spring</span><span style="font-family: 宋体">的基本用法应该都能掌握。</span></p>
<p>
<p><span style="font-family: 宋体">四、开始做实际的项目</span></p>
<p><span style="font-family: 宋体">在上述这些都完备以后，我觉得应该要去实际项目中锻炼了。当然并不是每人都有这样的机会的，这时只能自己做个玩具项目啦。项目的锻炼是非常关键的，其实每个人都清楚，我就不重复了。</span></p>
<p>
<p><span style="font-family: 宋体">五、继续深入学习</span></p>
<p><span style="font-family: 宋体">经过项目的锤炼，对</span><span lang="DA">Spring</span><span style="font-family: 宋体">的用法和原理有了一定的了解的时候，才有可能真正掌握</span><span lang="DA">Spring</span><span style="font-family: 宋体">的精髓。这时要读的书才是</span><span lang="DA">Rod Johnson</span><span style="font-family: 宋体">的三本经典名著，分别是：</span></p>
<p><span lang="DA">Expert one on one J2ee design and development</span></p>
<p><span lang="EN-US">Expert one on one J2ee without EJB</span></p>
<p><span lang="EN-US">Professional Java Development with SpringFramework</span></p>
<p><span style="font-family: 宋体">前两本书的经典程度我就不说了，只有读了它们，才能真正了解</span><span lang="EN-US">Spring</span><span style="font-family: 宋体">的设计意图，掌握</span><span lang="EN-US">Spring</span><span style="font-family: 宋体">的精髓。</span></p>
<p><span style="font-family: 宋体">第三本书是我强烈不建议初学者读的书。里面的东西深入而全，但是原理讲解得又不够深，很容易让初学者犯迷糊。但是却是</span><span lang="EN-US">Spring</span><span style="font-family: 宋体">的高级用户必读的一本书（还有一本</span><span lang="EN-US">pro Spring</span><span style="font-family: 宋体">据说也不错，不过我没读过）。我过几天会写一下这本书的书评。</span></p>
<p><span style="font-family: 宋体">当然这个阶段与第四阶段是交错的，边读书边做项目学到的东西才会更多的。</span></p>
<p>
<p><span style="font-family: 宋体">六、分析源代码，扩展</span><span lang="DA">Spring</span></p>
<p><span style="font-family: 宋体">有人认为没有必要分析</span><span lang="DA">Spring</span><span style="font-family: 宋体">的源代码，因为这是很累人又不计好的事。但是要想成为</span><span lang="DA">Spring</span><span style="font-family: 宋体">的高级用户，这是必经的阶段。在学习的过程中，我们学到的不仅是</span><span lang="DA">Spring</span><span style="font-family: 宋体">，更重要的是他的设计思想。不管怎样，看牛人的源代码是绝对有好处的。不过这是一个很累人的过程，要有思考准备哦！</span></p>
<p>
<p><span style="font-family: 宋体">七、等我到这个阶段的时候再告诉你吧，哈哈</span></span></p>
<img src ="http://www.blogjava.net/xhchc/aggbug/259500.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-03-13 11:57 <a href="http://www.blogjava.net/xhchc/archive/2009/03/13/259500.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring总结</title><link>http://www.blogjava.net/xhchc/archive/2009/03/11/259151.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Wed, 11 Mar 2009 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/03/11/259151.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/259151.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/03/11/259151.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/259151.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/259151.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: spring 7大组成模块：&nbsp;1:spring core：提供了spring 的核心功能，BeanFactory是spring核心容器的主要组件，&nbsp;&nbsp;&nbsp;&nbsp;它通过Ioc把程序的配置和依赖性与实际的代码分开，是整个spring的基础&nbsp;2:spring context：通过配置文件向spring提供上下文信息，&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/xhchc/archive/2009/03/11/259151.html'>阅读全文</a><img src ="http://www.blogjava.net/xhchc/aggbug/259151.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-03-11 16:38 <a href="http://www.blogjava.net/xhchc/archive/2009/03/11/259151.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2实现的6位数字的验证码程序</title><link>http://www.blogjava.net/xhchc/archive/2009/03/04/257844.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Wed, 04 Mar 2009 09:50:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/03/04/257844.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/257844.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/03/04/257844.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/257844.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/257844.html</trackback:ping><description><![CDATA[<strong><span style="color: red">1、login.jsp页面程序</span></strong> <br />
<br />
<div class="dp-highlighter">
<div class="tools">Java代码 </div>
<p class="bar"></span></p>
<div class="tools"><a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"></a>&nbsp;</div>
<ol class="dp-j">
    <li><span><span>&lt;script&nbsp;type=</span><span class="string">"text/javascript"</span><span>&gt;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>function&nbsp;changeValidateCode(obj)&nbsp;{&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">//获取当前的时间作为参数，无具体意义&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>var&nbsp;timenow&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Date().getTime();&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//每次请求需要一个不同的参数，否则可能会返回同样的验证码&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//这和浏览器的缓存机制有关系，也可以把页面设置为不缓存，这样就不用这个参数了。&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>obj.src=</span><span class="string">"rand.action?d="</span><span>+timenow;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/script&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>在表单中添加下面这句话： &nbsp;&nbsp;</span></li>
    <li><span>&lt;s:text&nbsp;name=</span><span class="string">"random"</span><span>&gt;&lt;/s:text&gt;：&lt;s:textfield&nbsp;name=</span><span class="string">"rand"</span><span>&nbsp;size=</span><span class="string">"5"</span><span>&gt;&lt;/s:textfield&gt;&lt;img&nbsp;src=</span><span class="string">"rand.action"</span><span>&nbsp;title=</span><span class="string">"点击图片刷新验证码"</span><span>/&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
<span style="color: red"><strong>2、RandomNumUtil.java 生成验证码的类文件</strong></span> <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">import</span><span>&nbsp;java.awt.Color; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.awt.Font; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.awt.Graphics; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.awt.image.BufferedImage; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.ByteArrayInputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.ByteArrayOutputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.util.Random; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;javax.imageio.ImageIO; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;javax.imageio.stream.ImageOutputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;RandomNumUtil&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">private</span><span>&nbsp;ByteArrayInputStream&nbsp;image;</span><span class="comment">//图像&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">private</span><span>&nbsp;String&nbsp;str;</span><span class="comment">//验证码&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">private</span><span>&nbsp;RandomNumUtil(){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>init();</span><span class="comment">//初始化属性&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">/*&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*&nbsp;取得RandomNumUtil实例&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*/</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;RandomNumUtil&nbsp;Instance(){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;RandomNumUtil();&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">/*&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*&nbsp;取得验证码图片&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*/</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;ByteArrayInputStream&nbsp;getImage(){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.image;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">/*&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*&nbsp;取得图片的验证码&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*/</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;String&nbsp;getString(){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.str;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;init()&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//&nbsp;在内存中创建图象&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;width=</span><span class="number">85</span><span>,&nbsp;height=</span><span class="number">20</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>BufferedImage&nbsp;image&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;BufferedImage(width,&nbsp;height,&nbsp;BufferedImage.TYPE_INT_RGB);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//&nbsp;获取图形上下文&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>Graphics&nbsp;g&nbsp;=&nbsp;image.getGraphics();&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">//&nbsp;生成随机类&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>Random&nbsp;random&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Random();&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//&nbsp;设定背景色&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>g.setColor(getRandColor(</span><span class="number">200</span><span>,</span><span class="number">250</span><span>));&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>g.fillRect(</span><span class="number">0</span><span>,&nbsp;</span><span class="number">0</span><span>,&nbsp;width,&nbsp;height);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//&nbsp;设定字体&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>g.setFont(</span><span class="keyword">new</span><span>&nbsp;Font(</span><span class="string">"Times&nbsp;New&nbsp;Roman"</span><span>,Font.PLAIN,</span><span class="number">18</span><span>));&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//&nbsp;随机产生155条干扰线，使图象中的认证码不易被其它程序探测到&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>g.setColor(getRandColor(</span><span class="number">160</span><span>,</span><span class="number">200</span><span>));&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i=</span><span class="number">0</span><span>;i&lt;</span><span class="number">155</span><span>;i++)&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>{&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="keyword">int</span><span>&nbsp;x&nbsp;=&nbsp;random.nextInt(width);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;y&nbsp;=&nbsp;random.nextInt(height);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;xl&nbsp;=&nbsp;random.nextInt(</span><span class="number">12</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;yl&nbsp;=&nbsp;random.nextInt(</span><span class="number">12</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>g.drawLine(x,y,x+xl,y+yl);&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">//&nbsp;取随机产生的认证码(6位数字)&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>String&nbsp;sRand=</span><span class="string">""</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i=</span><span class="number">0</span><span>;i&lt;</span><span class="number">6</span><span>;i++){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>String&nbsp;rand=String.valueOf(random.nextInt(</span><span class="number">10</span><span>));&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>sRand+=rand;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">//&nbsp;将认证码显示到图象中&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>g.setColor(</span><span class="keyword">new</span><span>&nbsp;Color(</span><span class="number">20</span><span>+random.nextInt(</span><span class="number">110</span><span>),</span><span class="number">20</span><span>+random.nextInt(</span><span class="number">110</span><span>),</span><span class="number">20</span><span>+random.nextInt(</span><span class="number">110</span><span>)));&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="comment">//&nbsp;调用函数出来的颜色相同，可能是因为种子太接近，所以只能直接生成&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>g.drawString(rand,</span><span class="number">13</span><span>*i+</span><span class="number">6</span><span>,</span><span class="number">16</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>} &nbsp;&nbsp;</span></li>
    <li><span class="comment">//赋值验证码 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">this</span><span>.str=sRand;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="comment">//图象生效&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>g.dispose();&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>ByteArrayInputStream&nbsp;input=</span><span class="keyword">null</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>ByteArrayOutputStream&nbsp;output&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;ByteArrayOutputStream();&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">try</span><span>{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>ImageOutputStream&nbsp;imageOut&nbsp;=&nbsp;ImageIO.createImageOutputStream(output);&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>ImageIO.write(image,&nbsp;</span><span class="string">"JPEG"</span><span>,&nbsp;imageOut);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>imageOut.close();&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>input&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;ByteArrayInputStream(output.toByteArray());&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}</span><span class="keyword">catch</span><span>(Exception&nbsp;e){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>System.out.println(</span><span class="string">"验证码图片产生出现错误："</span><span>+e.toString());&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">this</span><span>.image=input;</span><span class="comment">/*&nbsp;赋值图像&nbsp;*/</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="comment">/*&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*&nbsp;给定范围获得随机颜色&nbsp; </span>&nbsp;</span></li>
    <li><span><span class="comment">*/</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">private</span><span>&nbsp;Color&nbsp;getRandColor(</span><span class="keyword">int</span><span>&nbsp;fc,</span><span class="keyword">int</span><span>&nbsp;bc){&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>Random&nbsp;random&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Random();&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">if</span><span>(fc&gt;</span><span class="number">255</span><span>)&nbsp;fc=</span><span class="number">255</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">if</span><span>(bc&gt;</span><span class="number">255</span><span>)&nbsp;bc=</span><span class="number">255</span><span>;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;r=fc+random.nextInt(bc-fc);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;g=fc+random.nextInt(bc-fc);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">int</span><span>&nbsp;b=fc+random.nextInt(bc-fc);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">new</span><span>&nbsp;Color(r,g,b);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>} &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&nbsp;</pre>
<br />
<br />
<span style="color: red"><strong>3、RandomAction.java&nbsp; 生成验证码的action程序</strong></span> <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">import</span><span>&nbsp;java.io.ByteArrayInputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;com.mxl.util.RandomNumUtil; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;com.opensymphony.xwork2.ActionContext; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;com.opensymphony.xwork2.ActionSupport; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;RandomAction&nbsp;</span><span class="keyword">extends</span><span>&nbsp;ActionSupport{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">private</span><span>&nbsp;ByteArrayInputStream&nbsp;inputStream;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;String&nbsp;execute()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;Exception{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>RandomNumUtil&nbsp;rdnu=RandomNumUtil.Instance();&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="keyword">this</span><span>.setInputStream(rdnu.getImage());</span><span class="comment">//取得带有随机字符串的图片&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>ActionContext.getContext().getSession().put(</span><span class="string">"random"</span><span>,&nbsp;rdnu.getString());</span><span class="comment">//取得随机字符串放入HttpSession&nbsp; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;SUCCESS;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setInputStream(ByteArrayInputStream&nbsp;inputStream)&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">this</span><span>.inputStream&nbsp;=&nbsp;inputStream;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp; &nbsp;&nbsp;</span></li>
    <li><span class="keyword">public</span><span>&nbsp;ByteArrayInputStream&nbsp;getInputStream()&nbsp;{&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;inputStream;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>} &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&nbsp;</pre>
<br />
<br />
<span style="color: red"><strong>4、LoginAction.java 验证验证码的action</strong></span> <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">private</span><span>&nbsp;String&nbsp;rand;&nbsp;</span><span class="comment">//表单中的rand </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;String&nbsp;getRand()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;rand; &nbsp;&nbsp;</span></span></li>
    <li><span>} &nbsp;&nbsp;</span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setRand(String&nbsp;rand)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">this</span><span>.rand&nbsp;=&nbsp;rand; &nbsp;&nbsp;</span></span></li>
    <li><span>} &nbsp;&nbsp;</span></li>
    <li><span class="comment">//从session中取出RandomAction.java&nbsp;中生成的验证码random </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>String&nbsp;arandom=(String)(ActionContext.getContext().getSession().get(</span><span class="string">"random"</span><span>)); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="comment">//下面就是将session中保存验证码字符串与客户输入的验证码字符串对比了 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">if</span><span>(arandom.equals(</span><span class="keyword">this</span><span>.getRand()))&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>ActionContext.getContext().getSession().put(</span><span class="string">"user"</span><span>,&nbsp;</span><span class="keyword">this</span><span>.getUsername()); &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;SUCCESS; &nbsp;&nbsp;</span></span></li>
    <li><span>} &nbsp;&nbsp;</span></li>
    <li><span class="keyword">else</span><span>&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">return</span><span>&nbsp;ERROR; &nbsp;&nbsp;</span></span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
<span style="color: red"><strong>5、配置struts.xml文件</strong></span> <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!--&nbsp;Random验证码&nbsp;--&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;action&nbsp;name=</span><span class="string">"rand"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"com.mxl.rand.RandomAction"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;result&nbsp;type=</span><span class="string">"stream"</span><span>&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=</span><span class="string">"contentType"</span><span>&gt;image/jpeg&lt;/param&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=</span><span class="string">"inputName"</span><span>&gt;inputStream&lt;/param&gt;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/result&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&lt;/action&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
<span style="color: red"><strong>6、生成的验证码图片演示（实现的6位数字的验证码）</strong></span> <br />
<br />
<br />
<br />
<span style="color: blue"><strong>说明：</strong></span> <br />
<br />
<strong><span style="color: red">如果想修改验证码生成的个数，需要修改以下几个地方：</span></strong> <br />
<br />
<span style="color: violet">第一点：</span> <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">int</span><span>&nbsp;width=</span><span class="number">85</span><span>,&nbsp;height=</span><span class="number">20</span><span>;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&nbsp;</pre>
<br />
<br />
<span style="color: violet">第二点：</span> <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://www.javaeye.com/topic/300128#"><img alt="复制代码" src="http://www.javaeye.com/images/icon_copy.gif" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i=</span><span class="number">0</span><span>;i&lt;</span><span class="number">6</span><span>;i++)&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre class="java" style="display: none" name="code">&nbsp;</pre>
<br />
<br />
<span style="color: red">数字6，修改成你想生成的位数就可以了～</span> 
<img src ="http://www.blogjava.net/xhchc/aggbug/257844.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-03-04 17:50 <a href="http://www.blogjava.net/xhchc/archive/2009/03/04/257844.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式解读之一： 策略模式(转)</title><link>http://www.blogjava.net/xhchc/archive/2009/03/04/257836.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Wed, 04 Mar 2009 09:27:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/03/04/257836.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/257836.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/03/04/257836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/257836.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/257836.html</trackback:ping><description><![CDATA[<p>原文出自：http://www.javaeye.com/topic/328262<br />
<br />
当我们掌握了Java的语法，当我们了解了面向对象的封装、继承、多态等特性，当我们可以用Swing、Servlet、JSP技术构建桌面以及Web应用，不意味着我们可以写出面向对象的程序，不意味着我们可以很好的实现代码复用，弹性维护，不意味着我们可以实现在维护、扩展基础上的代码复用。一把刀，可以使你制敌于无形而于江湖扬名，也可以只是一把利刃而使你切菜平静。Java，就是这把刀，它的威力取决于你使用的方式。当我们陷入无尽无止重复代码的泥沼，当我们面临牵一发而动全身的维护恶梦, 你应该想起&#8220;设计模式&#8221;这个行动秘笈。面向对象的精义，看似平淡，其实要经过艰苦实践才能成功。而构造OO系统的隐含经验于是被前人搜集而成并冠以&#8220;设计模式&#8221;之名。我们应该在编码行动初始就携带以它。接下来，让我们步&#8220;四人组&#8221;先行者之后，用中国文字、用实际案例领略模式于我们代码焕然一新的改变：</p>
<p>&nbsp;</p>
<p>设计模式解读之一： 策略模式</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; 1. 模式定义<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把会变化的内容取出并封装起来，以便以后可以轻易地改动或扩充部分，而不影响不需要变化的其他部分；<br />
<br />
&nbsp;&nbsp;&nbsp; 2. 问题缘起<br />
<br />
&nbsp;&nbsp;&nbsp; 当涉及至代码维护时，为了复用目的而使用继承，结局并不完美。对父类的修改，会影响到子类型。在超类中增加的方法，会导致子类型有该方法，甚至连那些不该具备该方法的子类型也无法免除。示例，一个鸭子类型：<br />
<br />
&nbsp;&nbsp;&nbsp; public abstract class Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //所有的鸭子均会叫以及游泳，所以父类中处理这部分代码<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Quack");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void swim() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("All ducks float, even decoys.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //因为每种鸭子的外观是不同的，所以父类中该方法是抽象的，由子类型自己完成。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public abstract void display();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public class MallardDuck extends Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //野鸭外观显示为绿头<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Green head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public class RedHeadDuck extends Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //红头鸭显示为红头<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Red head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public class RubberDuck extends Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //橡皮鸭叫声为吱吱叫，所以重写父类以改写行为<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Squeak");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //橡皮鸭显示为黄头<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Yellow head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; 上述代码，初始实现得非常好。现在我们如果给Duck.java中加入fly()方法的话，那么在子类型中均有了该方法，于是我们看到了 会飞的橡皮鸭子，你看过吗？当然，我们可以在子类中通过空实现重写该方法以解决该方法对于子类型的影响。但是父类中再增加其它的方法呢？<br />
<br />
&nbsp;&nbsp;&nbsp; 通过继承在父类中提供行为，会导致以下缺点：<br />
<br />
&nbsp;&nbsp;&nbsp; a. 代码在多个子类中重复;<br />
&nbsp;&nbsp;&nbsp; b. 运行时的行为不容易改变；<br />
&nbsp;&nbsp;&nbsp; c. 改变会牵一发动全身，造成部分子类型不想要的改变；<br />
<br />
&nbsp;&nbsp;&nbsp; 好啦，还是刚才鸭子的例子，你也许想到使用接口，将飞的行为、叫的行为定义为接口，然后让Duck的各种子类型实现这些接口。这时侯代码类似于：<br />
<br />
&nbsp;&nbsp;&nbsp; public abstract class Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //将变化的行为 fly() 以及quake()从Duck类中分离出去定义形成接口，有需求的子类中自行去实现<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void swim() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("All ducks float, even decoys.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public abstract void display();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; //变化的 fly() 行为定义形成的接口<br />
&nbsp;&nbsp;&nbsp; public interface FlyBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void fly();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; //变化的 quack() 行为定义形成的接口<br />
&nbsp;&nbsp;&nbsp; public interface QuackBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void quack();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; //野鸭子会飞以及叫，所以实现接口&nbsp; FlyBehavior, QuackBehavior<br />
&nbsp;&nbsp;&nbsp; public class MallardDuck extends Duck implements FlyBehavior, QuackBehavior{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Green head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void fly() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Fly.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Quack.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; //红头鸭子会飞以及叫，所以也实现接口&nbsp; FlyBehavior, QuackBehavior<br />
&nbsp;&nbsp;&nbsp; public class RedHeadDuck extends Duck implements FlyBehavior, QuackBehavior{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Red head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void fly() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Fly.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Quack.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; //橡皮鸭不会飞，但会吱吱叫，所以只实现接口QuackBehavior<br />
&nbsp;&nbsp;&nbsp; public class RubberDuck extends Duck implements QuackBehavior{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //橡皮鸭叫声为吱吱叫<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Squeak");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //橡皮鸭显示为黄头<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Yellow head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; 上述代码虽然解决了一部分问题，让子类型可以有选择地提供一些行为(例如 fly() 方法将不会出现在橡皮鸭中).但我们也看到，野鸭子MallardDuck.java和红头鸭子RedHeadDuck.java的一些相同行为代码不能得到重复使用。很大程度上这是从一个火坑跳到另一个火坑。<br />
<br />
&nbsp;&nbsp;&nbsp; 在一段程序之后，让我们从细节中跳出来，关注一些共性问题。不管使用什么语言，构建什么应用，在软件开发上，一直伴随着的不变的真理是：需要一直在变化。不管当初软件设计得多好，一段时间之后，总是需要成长与改变，否则软件就会死亡。<br />
<br />
&nbsp;&nbsp;&nbsp; 我们知道，继承在某种程度上可以实现代码重用，但是父类(例如鸭子类Duck)的行为在子类型中是不断变化的，让所有子类型都有这些行为是不恰当的。我们可以将这些行为定义为接口，让Duck的各种子类型去实现，但接口不具有实现代码，所以实现接口无法达到代码复用。这意味着，当我们需要修改某个行为，必须往下追踪并在每一个定义此行为的类中修改它，一不小心，会造成新的错误。<br />
<br />
&nbsp;&nbsp;&nbsp; 设计原则：把应用中变化的地方独立出来，不要和那些不需要变化的代码混在一起。这样代码变化引起的不经意后果变少，系统变得更有弹性。<br />
<br />
&nbsp;&nbsp;&nbsp; 按照上述设计原则，我们重新审视之前的Duck代码。<br />
<br />
&nbsp;&nbsp;&nbsp; 1) 分开变化的内容和不变的内容<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Duck类中的行为 fly(), quack(), 每个子类型可能有自己特有的表现，这就是所谓的变化的内容。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Duck类中的行为 swim() 每个子类型的表现均相同，这就是所谓不变的内容。<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 我们将变化的内容从Duck()类中剥离出来单独定义形成接口以及一系列的实现类型。将变化的内容定义形成接口可实现变化内容和不变内容的剥离。其实现类型可实现变化内容的重用。这些实现类并非Duck.java的子类型，而是专门的一组实现类，称之为"行为类"。由行为类而不是Duck.java的子类型来实现接口。这样，才能保证变化的行为独立于不变的内容。于是我们有：<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 变化的内容：<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 fly() 行为定义形成的接口<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public interface FlyBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void fly();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 fly() 行为的实现类之一<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class FlyWithWings implements FlyBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void fly() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("I'm flying.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 fly() 行为的实现类之二<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class FlyNoWay implements FlyBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void fly() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("I can't fly.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -----------------------------------------------------------------<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 quack() 行为定义形成的接口<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public interface QuackBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; void quack();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 quack() 行为实现类之一<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class Quack implements QuackBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Quack");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 quack() 行为实现类之二<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class Squeak implements QuackBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Squeak.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; //变化的 quack() 行为实现类之三<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class MuteQuack implements QuackBehavior {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void quack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("&lt;&lt; Slience &gt;&gt;");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 通过以上设计，fly()行为以及quack()行为已经和Duck.java没有什么关系，可以充分得到复用。而且我们很容易增加新的行为, 既不影响现有的行为，也不影响Duck.java。但是，大家可能有个疑问，就是在面向对象中行为不是体现为方法吗？为什么现在被定义形成类(例如Squeak.java)？在OO中，类代表的"东西"一般是既有状态(实例变量）又有方法。只是在本例中碰巧"东西"是个行为。既使是行为，也有属性及方法，例如飞行行为，也需要一些属性记录飞行的状态，如飞行高度、速度等。<br />
<br />
&nbsp;&nbsp;&nbsp; 2) 整合变化的内容和不变的内容<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Duck.java将 fly()以及quack()的行为委拖给行为类处理。<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 不变的内容：<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public abstract class Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //将行为类声明为接口类型，降低对行为实现类型的依赖<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; FlyBehavior flyBehavior;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; QuackBehavior quackBehavior;<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void performFly() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //不自行处理fly()行为，而是委拖给引用flyBehavior所指向的行为对象<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; flyBehavior.fly();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void performQuack() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; quackBehavior.quack();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void swim() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("All ducks float, even decoys.");&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public abstract void display();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Duck.java不关心如何进行 fly()以及quack(), 这些细节交由具体的行为类完成。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class MallardDuck extends Duck{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public MallardDuck() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; flyBehavior=new FlyWithWings();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; quackBehavior=new Quack();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("Green head.");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 测试类：<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class DuckTest {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Duck duck=new MallardDuck();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; duck.performFly();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; duck.performQuack();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 在Duck.java子类型MallardDuck.java的构造方法中，直接实例化行为类型，在编译的时侯便指定具体行为类型。当然，我们可以：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 1) 我们可以通过工厂模式或其它模式进一步解藕(可参考后续模式讲解);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 2) 或做到在运行时动态地改变行为。<br />
<br />
&nbsp;&nbsp;&nbsp; 3) 动态设定行为<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 在父类Duck.java中增加设定行为类型的setter方法，接受行为类型对象的参数传入。为了降藕，行为参数被声明为接口类型。这样，既便在运行时，也可以通过调用这二个方法以改变行为。<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public abstract class Duck {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //在刚才Duck.java中加入以下二个方法。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void setFlyBehavior(FlyBehavior flyBehavior) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.flyBehavior=flyBehavior;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public void setQuackBehavior(QuackBehavior quackBehavior) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.quackBehavior=quackBehavior;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //其它方法同，省略...<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 测试类：<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public class DuckTest {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Duck duck=new MallardDuck();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; duck.performFly();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; duck.performQuack();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; duck.setFlyBehavior(new FlyNoWay());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; duck.performFly();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 如果，我们要加上火箭助力的飞行行为，只需再新建FlyBehavior.java接口的实现类型。而子类型可通过调用setQuackBehavior(...)方法动态改变。至此，在Duck.java增加新的行为给我们代码所带来的困绕已不复存在。<br />
<br />
&nbsp;&nbsp;&nbsp; 该是总结的时侯了，让我们从代码的水中浮出来，做一只在水面上自由游动的鸭子吧:<br />
<br />
&nbsp;&nbsp;&nbsp; 3.&nbsp; 解决方案<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MallardDuck 继承&nbsp; Duck抽象类；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt; 不变的内容<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FlyWithWings 实现 FlyBehavior接口；&nbsp;&nbsp;&nbsp;&nbsp; -&gt; 变化的内容,行为或算法<br />
&nbsp;&nbsp;&nbsp; 在Duck.java提供setter方法以装配关系；&nbsp;&nbsp;&nbsp; -&gt; 动态设定行为<br />
<br />
&nbsp;&nbsp;&nbsp; 以上就是策略模式的实现三步曲。接下来，让我们透过步骤看本质:<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 1) 初始，我们通过继承实现行为的重用，导致了代码的维护问题。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -&gt; 继承, is a<br />
&nbsp;&nbsp;&nbsp; 2) 接着，我们将行为剥离成单独的类型并声明为不变内容的实例变量并通过&nbsp; -&gt; 组合, has a<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; setter方法以装配关系；<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 继承，可以实现静态代码的复用；组合，可以实现代码的弹性维护；使用组合代替继承，可以使代码更好地适应软件开发完后的需求变化。<br />
<br />
&nbsp;&nbsp;&nbsp; 策略模式的本质：少用继承，多用组合</p>
<img src ="http://www.blogjava.net/xhchc/aggbug/257836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-03-04 17:27 <a href="http://www.blogjava.net/xhchc/archive/2009/03/04/257836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jQuery中文入门指南，翻译加实例，jQuery的起点教程(转)</title><link>http://www.blogjava.net/xhchc/archive/2009/03/02/257364.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Mon, 02 Mar 2009 08:55:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/03/02/257364.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/257364.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/03/02/257364.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/257364.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/257364.html</trackback:ping><description><![CDATA[<div>
<h3>中文版译者：<a href="http://keelsike.blogspot.com/">Keel</a></h3>
<p>此文以实例为基础一步步说明了jQuery的工作方式。现以中文翻译（添加我的补充说明）如下。如有相关意见或建议请麻烦到我的 <a href="http://keelsike.blogspot.com/">BLOG</a> 写个回复或者 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#107;&#101;&#101;&#108;&#46;&#115;&#105;&#107;&#101;&#40;&#97;&#116;&#41;&#103;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">EMAIL</a> 告知。</p>
<p>英文原版：<a href="http://jquery.bassistance.de/jquery-getting-started.html">http://jquery.bassistance.de/jquery-getting-started.html</a> ，感谢原文作者 <a href="http://bassistance.de/">J&#246;rn Zaefferer</a></p>
<p><strong>本文发布已征求原作者同意。</strong> </p>
<p>另外我认为在学习过程中,有两个API文档你要打开随时查看:</p>
<ul>
    <li><a href="http://jquery.com/api/">http://jquery.com/api/</a>
    <li><a href="http://visualjquery.com/">http://visualjquery.com/</a> </li>
</ul>
</div>
<h4>以下部分为原文翻译:</h4>
<hr />
<div>
<h2>jQuery入门指南教程</h2>
<p>这个指南是一个对jQuery库的说明，要求读者了解HTML(DOM)和CSS的一些常识。它包括了一个简单的Hello World的例子，选择器和事件基础，AJAX、FX的用法，以及如何制作jQuery的插件。 这个指南包括了很多代码，你可以copy它们，并试着修改它们，看看产生的效果。 </p>
<h2>内容提要</h2>
<ol>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#setup">安装</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#hello">Hello jQuery</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#find">Find me:使用选择器和事件</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#rate">Rate me:使用AJAX</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#">Animate me(让我生动起来):使用FX</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#sort">Sort me(将我有序化):使用tablesorter插件(表格排序)</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#plug">Plug me:制作您自己的插件</a>
    <li><a href="http://www.k99k.com/jQuery_getting_started.html#next">Next steps(下一步)</a> </li>
</ol>
</div>
<div>
<h2 id="setup">安装</h2>
<p>一开始,我们需要一个jQuery的库,最新的下载可以到<a href="http://jquery.com/src/">这里</a>找到。这个指南提供一个基本包含实例的包供下载.</p>
<p>下载：<a class="download" href="http://www.k99k.com/jquery-starterkit.zip">jQuery Starterkit</a></p>
<p class="log">(译者Keel注:一定要下载这个包，光看文章不实践肯定是不行的。) </p>
<p class="instruction">下载后解压缩，然后用你最喜欢的文本编辑器打开starterkit.html和custom.js这两个文件。<span class="log">(译者Keel注:这两个就是例子文件,所有的例子都用这两个例子作出,custom.js写jQuery代码,starterkit.html观察效果.建议用editPlus打开) </span></p>
<p>现在,我们就已经做好了一切准备来进行这个著名的"Hello world"例子.</p>
<h4>本章的相关链接:</h4>
<ul>
    <li><a href="http://www.k99k.com/jquery-starterkit.zip">Starterkit</a>
    <li><a href="http://jquery.com/src/">jQuery Downloads</a> </li>
</ul>
</div>
<div>
<h2 id="hello">Hello jQuery</h2>
<p>在做所有事情之前,我们要让jQuery读取和处理文档的DOM,必须尽可能快地在DOM载入后开始执行事件,所以,我们用一个ready事件作为处理HTML文档的开始.看看我们打开的custom.js这个文件,里面已经准备好了:</p>
<pre>$(document).ready(function() {
// do stuff when DOM is ready
});</pre>
<p>放一个简单的alert事件在需要等DOM完成载入,所以我们把任务稍稍变复杂一点:在点击任何一个链接时显示一个alert.</p>
<pre>$(document).ready(function() {
$("a").click(function() {
alert("Hello world!");
});
});</pre>
<p>这样在你点击页面的一个链接时都会触发这个"Hello world"的提示。</p>
<p class="log">(译者Keel注:请照此代码修改custom.js并保存,然后用浏览器打开starterkit.html观察效果。)</p>
<p>让我们看一下这些修改是什么含义。$("a") 是一个jQuery选择器(selector),在这里，它选择所有的a标签<span class="log">（译者Keel注：即&lt;a&gt;&lt;/a&gt;）</span>，$号是 jQuery &#8220;类&#8221;(jQuery "class")的一个别称，因此$()构造了一个新的jQuery 对象(jQuery object)。函数 click() 是这个jQuery对象的一个方法，它绑定了一个单击事件到所有选中的标签(这里是所有的a标签),并在事件触发时执行了它所提供的alert方法.</p>
<p>这里有一个拟行相似功能的代码:</p>
<pre>&lt;a href="#" onclick="alert('Hello world')"&gt;Link&lt;/a&gt;</pre>
<p>不同之处很明显,用jQuery不需要在每个a标签上写onclick事件,所以我们拥有了一个整洁的结构文档(HTML)和一个行为文档(JS),达到了将结构与行为分开的目的,就像我们使用CSS追求的一样.</p>
<p>下面我们会更多地了解到选择器与事件.</p>
<h4>本章的相关链接:</h4>
<ul>
    <li><a href="http://jquery.com/docs/Base/">jQuery Base</a>
    <li><a href="http://jquery.com/docs/Base/Expression/">jQuery Expressions</a>
    <li><a href="http://jquery.com/docs/Base/Events/">jQuery Basic Events</a> </li>
</ul>
</div>
<div>
<h2 id="find">Find me:使用选择器和事件</h2>
<p>jQuery提供两种方式来选择html的elements，第一种是用CSS和Xpath选择器联合起来形成一个字符串来传送到jQuery的构造器（如：$("div &gt; ul a")）；第二种是用jQuery对象的几个methods(方法)。这两种方式还可以联合起来混合使用。</p>
<p>为了测试一下这些选择器，我们来试着在我们starterkit.html中选择并修改第一个ordered list.</p>
<p>一开始，我们需要选择这个list本身，这个list有一个ID叫&#8220;orderedlist&#8221;，通常的javascript写法是document.getElementById("orderedlist").在jQuery中，我们这样做：</p>
<pre>$(document).ready(function() {
$("#orderedlist").addClass("red");
});</pre>
<p>这里将starterkit中的一个CSS样式red附加到了orderedlist上<span class="log">(译者Keel注：参考测试包中的css目录下的core.css，其中定义了red样式)</span>。因此，在你刷新了starterkit.html后，你将会看到第一个有序列表(ordered list )背景色变成了红色，而第二个有序列表没有变化.</p>
<p>现在，让我们添加一些新的样式到list的子节点.</p>
<pre>$(document).ready(function() {
$("#orderedlist &gt; li").addClass("blue");
});</pre>
<p>这样，所有orderedlist中的li都附加了样式"blue"。</p>
<p>现在我们再做个复杂一点的，当把鼠标放在li对象上面和移开时进行样式切换，但只在list的最后一个element上生效。</p>
<pre>$(document).ready(function() {
$("#orderedlist li:last").hover(function() {
$(this).addClass("green");
}, function() {
$(this).removeClass("green");
});
});</pre>
<p>还有大量的类似的<a class="doc" title="Documentation for CSS selectors" href="http://jquery.com/docs/Base/Expression/CSS/">CSS</a>和<a class="doc" title="Documentation for XPath selectors" href="http://jquery.com/docs/Base/Expression/XPath/">XPath</a>例子，更多的例子和列表可以在<a class="doc" title="Documentation for base selectors" href="http://jquery.com/docs/Base/Expression/">这里</a>找到。<span class="log">（译者Keel注：入门看此文，修行在个人，要想在入门之后懂更多，所以这段话的几个链接迟早是要必看的！不会又要翻译吧...^_^!）</span></p>
<p>每一个onXXX事件都有效，如onclick,onchange,onsubmit等，都有jQuery等价表示方法<span class="log">（译者Keel注：jQuery不喜欢onXXX，所以都改成了XXX，去掉了on）</span>。<a class="doc" title="Documentation for advanced events" href="http://jquery.com/docs/EventModule/">其他的一些事件</a>，如ready和hover,也提供了相应的方法。</p>
<p>你可以在<a href="http://visualjquery.com/">Visual jQuery</a>找到全部的事件列表，在Events栏目下.</p>
<p>用这些选择器和事件你已经可以做很多的事情了，但这里有一个更强的好东东！</p>
<pre>$(document).ready(function() {
$("#orderedlist").find("li").each(function(i) {
$(this).html( $(this).html() + " BAM! " + i );
});
});</pre>
<p>find() 让你在已经选择的element中作条件查找,因此 $("#orderedlist).find("li") 就像 $("#orderedlist li")一样。each()方法迭代了所有的li，并可以在此基础上作更多的处理。 大部分的方法,如addClass(), 都可以用它们自己的 each() 。在这个例子中, html()用来获取每个li的html文本, 追加一些文字，并将之设置为li的html文本。<span class="log">（译者Keel注：从这个例子可以看到.html()方法是获取对象的html代码，而.html('xxx')是设置'xxx'为对象的html代码）</span></p>
<p>另一个经常碰到的任务是在没有被jQuery覆盖的DOM元素上call一些方法，想像一个在你用AJAX方式成功提交后的reset：</p>
<pre>$(document).ready(function() {
// use this to reset a single form
$("#reset").click(function() {
$("#form")[0].reset();
});
});</pre>
<p class="log">（译者Keel注：这里作者将form的id也写成了form，源文件有&lt;form id="form"&gt;，这是非常不好的写法，你可以将这个ID改成form1或者testForm，然后用$("#form1")或者$("#testForm")来表示它，再进行测试。）</p>
<p>这个代码选择了所有ID为"form"的元素，并在其第一个上call了一个reset()。如果你有一个以上的form，你可以这样做：</p>
<pre>$(document).ready(function() {
// use this to reset several forms at once
$("#reset").click(function() {
$("form").each(function() {
this.reset();
});
});
});</pre>
<p class="log">（译者Keel注：请注意一定要亲自将这些代码写在custom.js中并在starterkit.html上测试效果才能有所体会！必要时要观察starterkit.html的html代码）</p>
<p>这样你在点击Reset链接后，就选择了文档中所有的form元素，并对它们都执行了一次reset()。</p>
<p>还有一个你可能要面对的问题是不希望某些特定的元素被选择。jQuery 提供了filter() 和not() 方法来解决这个问题。 filter()以过滤表达式来减少不符合的被选择项, not()则用来取消所有符合过滤表达式的被选择项. 考虑一个无序的list，你想要选择所有的没有ul子元素的li元素。</p>
<pre>$(document).ready(function() {
$("li").not("[ul]").css("border", "1px solid black");
});</pre>
<p>这个代码选择了所有的li元素，然后去除了没有ul子元素的li元素。刷新浏览器后，所有的li元素都有了一个边框，只有ul子元素的那个li元素例外。</p>
<p class="log">（译者Keel注：请注意体会方便之极的css()方法，并再次提醒请务必实际测试观察效果，比方说换个CSS样式呢？再加一个CSS样式呢？像这样：$("li").not("[ul]").css("border", "1px solid black").css("color","red");）</p>
<p>上面代码中的[expression] 语法是从XPath而来，可以在子元素和属性(elements and attributes)上用作过滤器，比如你可能想选择所有的带有name属性的链接:</p>
<pre>$(document).ready(function() {
$("a[@name]").background("#eee");
});</pre>
<p>这个代码给所有带有name属性的链接加了一个背景色。<span class="log">（译者Keel注：这个颜色太不明显了，建议写成$("a[@name]").background("red");）</span></p>
<p>更常见的情况是以name来选择链接，你可能需要选择一个有特点href属性的链接，这在不同的浏览器下对href的理解可能会不一致，所以我们的部分匹配("*=")的方式来代替完全匹配("=")：</p>
<pre>$(document).ready(function() {
$("a[@href*=/content/gallery]").click(function() {
// do something with all links that point somewhere to /content/gallery
});
});</pre>
<p>到现在为止，选择器都用来选择子元素或者是过滤元素。另外还有一种情况是选择上一个或者下一个元素，比如一个FAQ的页面，答案首先会隐藏，当问题点击时，答案显示出来，jQuery代码如下：</p>
<pre>$(document).ready(function() {
$('#faq').find('dd').hide().end().find('dt').click(function() {
var answer = $(this).next();
if (answer.is(':visible')) {
answer.slideUp();
} else {
answer.slideDown();
}
});
});</pre>
<p>这里我们用了一些链式表达法来减少代码量，而且看上去更直观更容易理解。像'#faq' 只选择了一次，利用end()方法，第一次find()方法会结束(undone)，所以我们可以接着在后面继续find('dt')，而不需要再写$('#faq').find('dt')。</p>
<p>在点击事件中的，我们用 $(this).next() 来找到dt下面紧接的一个dd元素，这让我们可以快速地选择在被点击问题下面的答案。</p>
<p class="log">（译者Keel注：这个例子真是太酷了，FAQ中的答案可以收缩！从利用next()的思路到实现这些效果都有很多地方需要我们消化，注意 if (answer.is(':visible'))用法，注意answer.slideUp();不懂的地方赶紧查我在最开始提到的两个必看API文档）</p>
<p>除了选择同级别的元素外，你也可以选择父级的元素。可能你想在用户鼠标移到文章某段的某个链接时，它的父级元素--也就是文章的这一段突出显示，试试这个：</p>
<pre>$(document).ready(function() {
$("a").hover(function() {
$(this).parents("p").addClass("highlight");
}, function() {
$(this).parents("p").removeClass("highlight");
});
});</pre>
<p>测试效果可以看到，移到文章某段的链接时，它所在的段全用上highlight样式，移走之后又恢复原样。</p>
<span class="log">（译者Keel注：highlight是core.css中定义的样式，你也可以改变它，注意这里有第二个function()这是hover方法的特点，请在API文档中查阅hover，上面也有例子说明）</span>
<p>在我们继续之前我们先来看看这一步： jQuery会让代码变得更短从而更容易理解和维护，下面是$(document).ready(callback)的缩写法：</p>
<pre>$(function() {
// code to execute when the DOM is ready
});</pre>
<p>应用到我们的Hello world例子中，可以这样:</p>
<pre>$(function() {
$("a").click(function() {
alert("Hello world!");
});
});</pre>
<p>现在，我们手上有了这些基础的知识，我们可以更进一步的探索其它方面的东西，就从AJAX开始！</p>
<h4>本章的相关链接:</h4>
<ul>
    <li><a href="http://jquery.com/api/">jQuery API documentation</a>
    <li><a href="http://visualjquery.com/">Visual jQuery - A categorized browsable API documentation</a>
    <li><a href="http://jquery.com/docs/Base/Expression/CSS/">jQuery Expressions: CSS</a>
    <li><a href="http://jquery.com/docs/Base/Expression/XPath/">jQuery Expressions: XPath</a>
    <li><a href="http://jquery.com/docs/Base/Expression/Custom/">jQuery Expressions: Custom</a>
    <li><a href="http://jquery.com/docs/EventModule/">jQuery Special Events</a>
    <li><a href="http://jquery.com/docs/Base/Traverse/">jQuery DOM Traversing</a> </li>
</ul>
</div>
<div>
<h2 id="rate">Rate me:使用AJAX</h2>
<p>在这一部分我们写了一个小小的AJAX应用，它能够rate一些东西<span class="log">（译Keel注：就是对某些东西投票）</span>，就像在youtube.com上面看到的一样。</p>
<p>首先我们需要一些服务器端代码，这个例子中用到了一个PHP文件，读取rating参数然后返回rating总数和平均数。看一下<a href="http://www.k99k.com/rate.phps">rate.php</a>代码.</p>
<p>虽然这些例子也可以不使用AJAX来实现，但显示我们不会那么做，我们用jQuery生成一个DIV容器，ID是"rating".</p>
<pre>$(document).ready(function() {
// generate markup
var ratingMarkup = ["Please rate: "];
for(var i=1; i &lt;= 5; i++) {
ratingMarkup[ratingMarkup.length] = "&lt;a href='#'&gt;" + i + "&lt;/a&gt;&nbsp;";
}
// add markup to container and applier click handlers to anchors
$("#rating").append( ratingMarkup.join('') ).find("a").click(function(e) {
e.preventDefault();
// send requests
$.post("rate.php", {rating: $(this).html()}, function(xml) {
// format result
var result = [
"Thanks for rating, current average: ",
$("average", xml).text(),
", number of votes: ",
$("count", xml).text()
];
// output result
$("#rating").html(result.join(''));
} );
});
});</pre>
<p>这段代码生成了5个链接，并将它们追加到id为"rating"容器中，当其中一个链接被点击时，该链接标明的分数就会以rating参数形式发送到rate.php，然后，结果将以XML形式会从服务器端传回来，添加到容器中，替代这些链接。</p>
<p>如果你没有一个安装过PHP的webserver，你可以看看这个<a href="http://www.k99k.com/example-rateme.html">在线的例子</a>.</p>
<p>不使用javascript实现的例子可以访问 <a href="http://www.softonic.de/ie/51494">softonic.de</a> 点击 "Kurz bewerten!"</p>
<p>更多的AJAX方法可以从<a class="doc" title="Documentation for AJAX methods" href="http://jquery.com/docs/AJAXModule/">这里</a> 找到，或者看看<a href="http://visualjquery.com/">API文档</a> 下面的AJAX filed under AJAX.</p>
<p class="log">（译者Keel注：这个在线实例从国内访问还是比较慢的，点击后要等一会儿才能看到结果，可以考虑对它进行修改，比如加上loading，投票后加上再投票的返回链接等。此外，这个例子中还是有很多需要进一步消化的地方，看不懂的地方请参考API文档。）</p>
<p>一个在使用AJAX载入内容时经常发生的问题是：当载入一个事件句柄到一个HTML文档时，还需要在载入内容上应用这些事件，你不得不在内容加载完成后应用这些事件句柄，为了防止代码重复执行，你可能用到如下一个function:</p>
<pre>// lets use the shortcut
$(function() {
var addClickHandlers = function() {
$("a.clickMeToLoadContent").click(function() {
$("#target").load(this.href, addClickHandlers);
});
};
addClickHandlers();
});</pre>
<p>现在，addClickHandlers只在DOM载入完成后执行一次，这是在用户每次点击具有clickMeToLoadContent 这个样式的链接并且内容加载完成后.</p>
<p>请注意addClickHandlers函数是作为一个局部变量定义的，而不是全局变量(如：function addClickHandlers() {...})，这样做是为了防止与其他的全局变量或者函数相冲突.</p>
<p>另一个常见的问题是关于回调(callback)的参数。你可以通过一个额外的参数指定回调的方法，简单的办法是将这个回调方法包含在一个其它的function中:</p>
<pre>// get some data
var foobar = ...;
// specify handler, it needs data as a paramter
var handler = function(data) {
...
};
// add click handler and pass foobar!
$('a').click( function(event) { handler(foobar); } );
// if you need the context of the original handler, use apply:
$('a').click( function(event) { handler.apply(this, [foobar]); } );</pre>
<p>用到简单的AJAX后，我们可以认为已经非常之&#8220;web2.0&#8221;了，但是到现在为止，我们还缺少一些酷炫的效果。下一节将会谈到这些效果.</p>
<h4>本章的相关链接:</h4>
<ul>
    <li><a href="http://jquery.com/docs/AJAXModule/">jQuery AJAX Module</a>
    <li><a href="http://jquery.com/api/">jQuery API: Contains description and examples for append and all other jQuery methods</a>
    <li><a href="http://jquery.com/demo/thickbox/">ThickBox: A jQuery plugin that uses jQuery to enhance the famous lightbox</a> </li>
</ul>
</div>
<div>
<h2 id="animate">Animate me(让我生动起来):使用FX</h2>
<p>一些动态的效果可以使用 <code>show()</code> 和 <code>hide()</code>来表现:</p>
<pre>$(document).ready(function() {
$("a").toggle(function() {
$(".stuff").hide('slow');
}, function() {
$(".stuff").show('fast');
});
});</pre>
<p>你可以与 <code>animate()</code>联合起来创建一些效果,如一个带渐显的滑动效果:</p>
<pre>$(document).ready(function() {
$("a").toggle(function() {
$(".stuff").animate({
height: 'hide',
opacity: 'hide'
}, 'slow');
}, function() {
$(".stuff").animate({
height: 'show',
opacity: 'show'
}, 'slow');
});
});</pre>
<p>很多不错的效果可以访问<a href="http://interface.eyecon.ro/">interface plugin collection</a>. 这个站点提供了很多demos和文档</p>
<p>这些效果插件是位于jQuery插件列表的前面的，当然也有很多其他的插件，比如我们下一章讲到的表格排序插件。</p>
<h4>本章的相关链接:</h4>
<ul>
    <li><a href="http://jquery.com/docs/FxModule/">jQuery FX Module</a>
    <li><a href="http://interface.eyecon.ro/">Interface plugin</a> </li>
</ul>
</div>
<div>
<h2 id="sort">Sort me(将我有序化):使用tablesorter插件(表格排序)</h2>
<p>这个表格排序插件能让我们在客户端按某一列进行排序，引入jQuery和这个插件的js文件，然后告诉插件你想要哪个表格拥有排序功能。</p>
<p>要测试这个例子，先在starterkit.html中加上像下面这一行的代码：</p>
<pre>&lt;script src="lib/jquery.tablesorter.js" type="text/javascript"&gt;&lt;/script&gt;</pre>
<p>然后可以这样调用不着:</p>
<pre>$(document).ready(function() {
$("#large").tableSorter();
});</pre>
<p>现在点击表格的第一行head区域，你可以看到排序的效果，再次点击会按倒过来的顺序进行排列。</p>
<p>这个表格还可以加一些突出显示的效果，我们可以做这样一个隔行背景色（斑马线）效果:</p>
<pre>$(document).ready(function() {
$("#large").tableSorter({
stripingRowClass: ['odd','even'],	// Class names for striping supplyed as a array.
stripRowsOnStartUp: true		// Strip rows on tableSorter init.
});
});</pre>
<p>关于这个插件的更多例子和文档可以在 <a href="http://motherrussia.polyester.se/jquery-plugins/tablesorter/">tablesorter首页</a>找到.</p>
<p>几乎所有的特件都是这样用的:先include插件的js文件,然后在某些元素上使用插件定义的方法,当然也有一些参数选项是可以配置的</p>
<p>经常更新的插件列表可以从jQuery官方站 <a title="Plugins for jQuery" href="http://jquery.com/plugins/">on the jQuery site</a>找到.</p>
<p>当你更经常地使用jQuery时,你会发现将你自己的代码打包成插件是很有用处的,它能方便地让你的公司或者其他人进行重用.下一章我们将谈到如何构建一个自己的插件.</p>
<h4>本章的相关链接:</h4>
<ul>
    <li><a href="http://jquery.com/plugins/">Plugins for jQuery</a>
    <li><a href="http://motherrussia.polyester.se/jquery-plugins/tablesorter/">Tablesorter Plugin</a> </li>
</ul>
</div>
<div>
<h2 id="plug">Plug me:制作自己的插件</h2>
<p>写一个自己的jQuery插件是非常容易的,如果你按照下面的原则来做,可以让其他人也容易地结合使用你的插件.</p>
<ol>
    <li>为你的插件取一个名字,在这个例子里面我们叫它"foobar".
    <li>创建一个像这样的文件:jquery.[yourpluginname].js,比如我们创建一个jquery.foobar.js
    <li>创建一个或更多的插件方法,使用继承jQuery对象的方式,如:
    <pre>jQuery.fn.foobar = function() {
    // do something
    };</pre>
    <li>可选的:创建一个用于帮助说明的函数,如:
    <pre>jQuery.fooBar = {
    height: 5,
    calculateBar = function() { ... },
    checkDependencies = function() { ... }
    };</pre>
    <p>你现在可以在你的插件中使用这些帮助函数了:</p>
    <pre>jQuery.fn.foobar = function() {
    // do something
    jQuery.foobar.checkDependencies(value);
    // do something else
    };</pre>
    <li>可选的l:创建一个默认的初始参数配置,这些配置也可以由用户自行设定,如:
    <pre>jQuery.fn.foobar = function(options) {
    var settings = {
    value: 5,
    name: "pete",
    bar: 655
    };
    if(options) {
    jQuery.extend(settings, options);
    }
    };</pre>
    <p>现在可以无需做任何配置地使用插件了,默认的参数在此时生效:</p>
    <pre>$("...").foobar();</pre>
    <p>或者加入这些参数定义:</p>
    <pre>$("...").foobar({
    value: 123,
    bar: 9
    });</pre>
    </li>
</ol>
<p>如果你release你的插件, 你还应该提供一些例子和文档,大部分的插件都具备这些良好的参考文档.</p>
<p>现在你应该有了写一个插件的基础,让我们试着用这些知识写一个自己的插件.</p>
<p>很多人试着控制所有的radio或者checkbox是否被选中,比如:</p>
<pre>$("input[@type='checkbox']").each(function() {
this.checked = true;
// or, to uncheck
this.checked = false;
// or, to toggle
this.checked = !this.checked;
});</pre>
<p>无论何时候，当你的代码出现each时，你应该重写上面的代码来构造一个插件,很直接地:</p>
<pre>$.fn.check = function() {
return this.each(function() {
this.checked = true;
});
};</pre>
<p>这个插件现在可以这样用:</p>
<pre>$("input[@type='checkbox']").check();</pre>
<p>现在你应该还可以写出uncheck()和toggleCheck()了.但是先停一下,让我们的插件接收一些参数.</p>
<pre>$.fn.check = function(mode) {
var mode = mode || 'on'; // if mode is undefined, use 'on' as default
return this.each(function() {
switch(mode) {
case 'on':
this.checked = true;
break;
case 'off':
this.checked = false;
break;
case 'toggle':
this.checked = !this.checked;
break;
}
});
};</pre>
<p>这里我们设置了默认的参数,所以将"on"参数省略也是可以的,当然也可以加上"on","off", 或 "toggle",如:</p>
<pre>$("input[@type='checkbox']").check();
$("input[@type='checkbox']").check('on');
$("input[@type='checkbox']").check('off');
$("input[@type='checkbox']").check('toggle');</pre>
<p>如果有多于一个的参数设置会稍稍有点复杂,在使用时如果只想设置第二个参数,则要在第一个参数位置写入null.</p>
<p>从上一章的tablesorter插件用法我们可以看到,既可以省略所有参数来使用或者通过一个 key/value 对来重新设置每个参数.</p>
<p>作为一个练习,你可以试着将 <a href="http://www.k99k.com/jQuery_getting_started.html#rate">第四章</a> 的功能重写为一个插件.这个插件的骨架应该是像这样的:</p>
<pre>$.fn.rateMe = function(options) {
var container = this; // instead of selecting a static container with $("#rating"), we now use the jQuery context
var settings = {
url: "rate.php"
// put more defaults here
// remember to put a comma (",") after each pair, but not after the last one!
};
if(options) { // check if options are present before extending the settings
$.extend(settings, options);
}
// ...
// rest of the code
// ...
return this; // if possible, return "this" to not break the chain
});</pre>
</div>
<div>
<h2 id="next">Next steps(下一步)</h2>
<p>如果你想做更好的javascript开发,建议你使用一个叫 <a href="http://www.joehewitt.com/software/firebug/">FireBug</a>的firefox插件. 它提供了断点调试(比alert强多了)、观察DOM变化等很多漂亮的功能</p>
<p>如果你还有未解决的问题，或者新的想法与建议，你可以使用jQuery的邮件列表 <a href="http://jquery.com/discuss">jQuery mailing list</a>.</p>
</div>
<img src ="http://www.blogjava.net/xhchc/aggbug/257364.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-03-02 16:55 <a href="http://www.blogjava.net/xhchc/archive/2009/03/02/257364.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编程爱好者论坛</title><link>http://www.blogjava.net/xhchc/archive/2009/02/06/253605.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Fri, 06 Feb 2009 09:14:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/02/06/253605.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/253605.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/02/06/253605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/253605.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/253605.html</trackback:ping><description><![CDATA[http://bbs.pfan.cn/main.asp
<img src ="http://www.blogjava.net/xhchc/aggbug/253605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-02-06 17:14 <a href="http://www.blogjava.net/xhchc/archive/2009/02/06/253605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EXT技术</title><link>http://www.blogjava.net/xhchc/archive/2009/02/06/253596.html</link><dc:creator>chu</dc:creator><author>chu</author><pubDate>Fri, 06 Feb 2009 08:42:00 GMT</pubDate><guid>http://www.blogjava.net/xhchc/archive/2009/02/06/253596.html</guid><wfw:comment>http://www.blogjava.net/xhchc/comments/253596.html</wfw:comment><comments>http://www.blogjava.net/xhchc/archive/2009/02/06/253596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xhchc/comments/commentRss/253596.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xhchc/services/trackbacks/253596.html</trackback:ping><description><![CDATA[http://www.ajaxjs.com/ajaxjs/index/
<img src ="http://www.blogjava.net/xhchc/aggbug/253596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xhchc/" target="_blank">chu</a> 2009-02-06 16:42 <a href="http://www.blogjava.net/xhchc/archive/2009/02/06/253596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>