﻿<?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-DANCE WITH JAVA-随笔分类-设计模式</title><link>http://www.blogjava.net/dreamstone/category/24599.html</link><description>开发出高质量的系统</description><language>zh-cn</language><lastBuildDate>Mon, 20 Aug 2007 03:41:36 GMT</lastBuildDate><pubDate>Mon, 20 Aug 2007 03:41:36 GMT</pubDate><ttl>60</ttl><item><title>终于可以在Java中使用lazy loading的单态了</title><link>http://www.blogjava.net/dreamstone/archive/2007/02/27/101000.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Tue, 27 Feb 2007 12:10:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/02/27/101000.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/101000.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/02/27/101000.html#Feedback</comments><slash:comments>12</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/101000.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/101000.html</trackback:ping><description><![CDATA[<p><a href="http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html">在我的这篇文章http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html中写了为什么不要使用Java的lazy loading</a> ,即使是double-check也解决不了问题，但是有人解决了这个问题。<br>佩服啊。实在是巧妙，如此简单<br>注意：在多个虚拟机的情况下这个方法还是不能用的，但是一般情况下是可以的。<br>实现方式：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_23_224_Open_Image onclick="this.style.display='none'; Codehighlighter1_23_224_Open_Text.style.display='none'; Codehighlighter1_23_224_Closed_Image.style.display='inline'; Codehighlighter1_23_224_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_23_224_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_23_224_Closed_Text.style.display='none'; Codehighlighter1_23_224_Open_Image.style.display='inline'; Codehighlighter1_23_224_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">class</span> <span style="COLOR: #000000">&nbsp;Singleton&nbsp;</span> <span id=Codehighlighter1_23_224_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_23_224_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br><img id=Codehighlighter1_62_121_Open_Image onclick="this.style.display='none'; Codehighlighter1_62_121_Open_Text.style.display='none'; Codehighlighter1_62_121_Closed_Image.style.display='inline'; Codehighlighter1_62_121_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_62_121_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_62_121_Closed_Text.style.display='none'; Codehighlighter1_62_121_Open_Image.style.display='inline'; Codehighlighter1_62_121_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">class</span> <span style="COLOR: #000000">&nbsp;SingletonHolder&nbsp;</span> <span id=Codehighlighter1_62_121_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_62_121_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #000000">&nbsp;Singleton&nbsp;instance&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">new</span> <span style="COLOR: #000000">&nbsp;Singleton();&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br><img id=Codehighlighter1_169_216_Open_Image onclick="this.style.display='none'; Codehighlighter1_169_216_Open_Text.style.display='none'; Codehighlighter1_169_216_Closed_Image.style.display='inline'; Codehighlighter1_169_216_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_169_216_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_169_216_Closed_Text.style.display='none'; Codehighlighter1_169_216_Open_Image.style.display='inline'; Codehighlighter1_169_216_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">static</span> <span style="COLOR: #000000">&nbsp;Singleton&nbsp;getInstance()&nbsp;</span> <span id=Codehighlighter1_169_216_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_169_216_Open_Text><span style="COLOR: #000000">{&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">return</span> <span style="COLOR: #000000">&nbsp;SingletonHolder.instance;&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000">&nbsp;&nbsp;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span> </div>
<p>这个写法的发明者是Google公司的Bob lee。<br>他还写了个轻量级IoC容器，据说不要配制文件，性能比spring快100倍。感觉100倍有些夸张，不过可以看看。<br><br></p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/101000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-02-27 20:10 <a href="http://www.blogjava.net/dreamstone/archive/2007/02/27/101000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>推荐给大家一个很有趣的话题： Javaeye上的"奇技淫巧"</title><link>http://www.blogjava.net/dreamstone/archive/2007/02/27/100950.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Tue, 27 Feb 2007 08:34:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/02/27/100950.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/100950.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/02/27/100950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/100950.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/100950.html</trackback:ping><description><![CDATA[从javaeye上看到一篇很有趣的文章&lt;&lt;奇技淫巧&gt;&gt;，链接在这里<br><a href="http://www.javaeye.com/topic/39694?page=1">http://www.javaeye.com/topic/39694?page=1</a><br>文中就一个问题提出了各种各样的思路，很多人给出了自己的观点，是个对人有启发的话题。<br>下边是我想出的一个思路，就是利用jdk1.6的script支持，也算一个办法吧。建议看完了上边的讨论再看<br>我下边的内容，要不可能不知道是什么意思。<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_55_466_Open_Image onclick="this.style.display='none'; Codehighlighter1_55_466_Open_Text.style.display='none'; Codehighlighter1_55_466_Closed_Image.style.display='inline'; Codehighlighter1_55_466_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_55_466_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_55_466_Closed_Text.style.display='none'; Codehighlighter1_55_466_Open_Image.style.display='inline'; Codehighlighter1_55_466_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;getOverall(Details[]&nbsp;arr&nbsp;,String&nbsp;method)</span><span id=Codehighlighter1_55_466_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_55_466_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;sum&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br><img id=Codehighlighter1_80_402_Open_Image onclick="this.style.display='none'; Codehighlighter1_80_402_Open_Text.style.display='none'; Codehighlighter1_80_402_Closed_Image.style.display='inline'; Codehighlighter1_80_402_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_80_402_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_80_402_Closed_Text.style.display='none'; Codehighlighter1_80_402_Open_Image.style.display='inline'; Codehighlighter1_80_402_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">try</span><span id=Codehighlighter1_80_402_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_80_402_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScriptEngineManager&nbsp;factory&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ScriptEngineManager();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ScriptEngine&nbsp;engine&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;factory.getEngineByName(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">JavaScript</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img id=Codehighlighter1_238_398_Open_Image onclick="this.style.display='none'; Codehighlighter1_238_398_Open_Text.style.display='none'; Codehighlighter1_238_398_Closed_Image.style.display='inline'; Codehighlighter1_238_398_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_238_398_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_238_398_Closed_Text.style.display='none'; Codehighlighter1_238_398_Open_Image.style.display='inline'; Codehighlighter1_238_398_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">arr.length;i</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)</span><span id=Codehighlighter1_238_398_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_238_398_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;engine.put(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">obj</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,&nbsp;arr[i]);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;engine.eval(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">obj.</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">method);<br><img id=Codehighlighter1_346_393_Open_Image onclick="this.style.display='none'; Codehighlighter1_346_393_Open_Text.style.display='none'; Codehighlighter1_346_393_Closed_Image.style.display='inline'; Codehighlighter1_346_393_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_346_393_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_346_393_Closed_Text.style.display='none'; Codehighlighter1_346_393_Open_Image.style.display='inline'; Codehighlighter1_346_393_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">&nbsp;(obj&nbsp;</span><span style="COLOR: #0000ff">instanceof</span><span style="COLOR: #000000">&nbsp;Double)</span><span id=Codehighlighter1_346_393_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_346_393_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum&nbsp;</span><span style="COLOR: #000000">+=</span><span style="COLOR: #000000">&nbsp;((Double)obj).doubleValue();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_421_449_Open_Image onclick="this.style.display='none'; Codehighlighter1_421_449_Open_Text.style.display='none'; Codehighlighter1_421_449_Closed_Image.style.display='inline'; Codehighlighter1_421_449_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_421_449_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_421_449_Closed_Text.style.display='none'; Codehighlighter1_421_449_Open_Image.style.display='inline'; Codehighlighter1_421_449_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000">(Exception&nbsp;e)</span><span id=Codehighlighter1_421_449_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_421_449_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;sum;<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br><img id=Codehighlighter1_518_562_Open_Image onclick="this.style.display='none'; Codehighlighter1_518_562_Open_Text.style.display='none'; Codehighlighter1_518_562_Closed_Image.style.display='inline'; Codehighlighter1_518_562_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_518_562_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_518_562_Closed_Text.style.display='none'; Codehighlighter1_518_562_Open_Image.style.display='inline'; Codehighlighter1_518_562_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;getOverallBalance(Details[]&nbsp;arr)&nbsp;</span><span id=Codehighlighter1_518_562_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_518_562_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;getOverall(arr,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">getBalance()</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_611_653_Open_Image onclick="this.style.display='none'; Codehighlighter1_611_653_Open_Text.style.display='none'; Codehighlighter1_611_653_Closed_Image.style.display='inline'; Codehighlighter1_611_653_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_611_653_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_611_653_Closed_Text.style.display='none'; Codehighlighter1_611_653_Open_Image.style.display='inline'; Codehighlighter1_611_653_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">double</span><span style="COLOR: #000000">&nbsp;getOverallFixed(Details[]&nbsp;arr)&nbsp;</span><span id=Codehighlighter1_611_653_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_611_653_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;getOverall(arr,</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">getFixed()</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.blogjava.net/Images/dot.gif">..&nbsp;&nbsp;&nbsp;&nbsp;</span></div>
最终的实现就是上边的样子，利用script我们能实现通过函数名来调用函数，其实内部和动态代理，反射<br>&nbsp;的效果是一样的。不过就是写起来简单，学习成本低。因为用java的人大部分是了解javascript的。 
<img src ="http://www.blogjava.net/dreamstone/aggbug/100950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-02-27 16:34 <a href="http://www.blogjava.net/dreamstone/archive/2007/02/27/100950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式相关文章 -- 目录</title><link>http://www.blogjava.net/dreamstone/archive/2007/01/08/92491.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 08 Jan 2007 15:42:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/01/08/92491.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/92491.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/01/08/92491.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/92491.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/92491.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 设计模式&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2007/01/08/92491.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/92491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-01-08 23:42 <a href="http://www.blogjava.net/dreamstone/archive/2007/01/08/92491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>更详细的 Bridge Adapter Facade模式之间的比较</title><link>http://www.blogjava.net/dreamstone/archive/2007/01/08/92482.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 08 Jan 2007 15:21:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/01/08/92482.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/92482.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/01/08/92482.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/92482.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/92482.html</trackback:ping><description><![CDATA[<a href="http://www.blogjava.net/dreamstone/archive/2007/01/07/92268.html">在这篇文章中</a>，我写了Bridge和adapter模式的区别.但是 maninred说<br>Bridge和adapter是没有关系的，而和Facade比较象，但在我的经验中更多的时候<br>是会混淆Bridge和adapter而不是Facade，这里详细的列出三个模式的比较 .<br>一,定义:<br>1.Facade模式是为一个复杂系统提供一个简单的接口。<br>比如你要去博物馆参观，很多东西，你一个个到处去问每个东西的管理员很麻烦，所以你找一个导游，让他给你一个个介绍，你只要找到导游就好了。导游就是门面。<br>2，适配器模式，引用一下GOF95中的话:<br>适配器模式是把一个类的接口变换成客户端所期待的另一种接口，从而使原本因接口不匹配而无法工作的两个类能够工作到一起。<br>举个例子，例如变压器<br>3，Bridge模式:<br>GOF95中的桥梁模式的描述：桥梁模式的用意是"将抽象化与实现化脱耦，使的二者可以独立变化。<br>例如AWT的实现<br>二,目的:<br>1,Facade模式使用在给一个复杂的系统提供统一的门面(接口),目的是简化客户端的操作,但并没有改变接口.<br>2,Adapter模式使用在两个部分有不同的接口的情况,目的是改变接口,使两个部分协同工作<br>3,桥梁模式是为了分离抽象和实现<br>二,使用场合<br>1,Facade模式出现较多的情况是这样的情况,你有一个复杂的系统,对应了各种情况,<br>客户看了说功能不错,但是使用太麻烦.你说没问题,我给你提供一个统一的门面.<br>所以Facade使用的场合多是对系统的"优化".<br>2,Adapter模式出现的情况是这样,你有一个类提供接口A,但是你的客户需要一个实现接口B的类,<br>这个时候你可以写一个Adapter让把A接口变成B接口,所以Adapter使用的场合是<br>指鹿为马.就是你受夹板气的时候,一边告诉你我只能提供给你A(鹿),一边告诉你说<br>我只要B(马),他长了四条腿,你没办法了,把鹿牵过去说,这是马,你看他有四条腿.<br>(当然实现指鹿为马也有两种方法,一个方法是你只露出鹿的四条腿,说你看这是马,这种方式就是<br>封装方式的Adapter实现,另一种方式是你把鹿牵过去,但是首先介绍给他说这是马,因为他长了四条腿<br>这种是继承的方式.)<br>3,Bridge模式在一般的开发中出现的情况并不多,AWT是一个,SWT也算部分是,<br>如果你的客户要求你开发一个系统,这个系统在Windows下运行界面的样子是Windows的样子.<br>在Linux下运行是Linux下的样子.在Macintosh下运行要是Mac Os的样子.<br>怎么办? 定义一系列的控件Button,Text,radio,checkBox等等.供上层开发者<br>使用,他们使用这些控件的方法,利用这些控件构造一个系统的GUI,然后你为这些控件<br>写好Linux的实现,让它在Linux上调用Linux本地的对应控件,<br>在Windows上调用Windows本地的对应控件,在Macintosh上调用Macintosh本地的对应控件<br>ok,你的任务完成了.<br>三,需求程度<br>1,Facade的需求程度是"中等",因为你不提供Facade程序照样能工作,只是不够好.<br>2,Adapter的需求程度是"必须",因为你不这么做就不能工作,除非你自己从头实现一个.<br>3,Bridge的需求程度是"一般",适合精益求精的人,因为你可以写三个程序给客户.<br>四,出现时期<br>1,Facade出现在项目中期,再优化<br>2,Adapter出现在项目后期,大部分都有了,差的仅仅是接口不同<br>3,Bridge出现在项目前期,你想让你的系统更灵活,更cool<br>五,在写文章的时候想到的<br>1,Facade很多时候是1:m的关系<br>2,Adapter很多是候是1:1的关系<br>3,Bridge很多时候是m:n的关系<br>呵呵.<br>六,最后<br>另外:回应一下maninred<br>1,我并没有把模式看的很独立,其实很多模式是配合使用的,而且在一定情况下可以<br>用一个替换另一个.同一个需求,有可能当你思考的角度不同时,使用的模式就不同了.<br>2,设计模式并不是"用OO的封装来封装所有的东西",模式其实可以应用于所有的设计上<br>和OO没有直接的关系,只是因为计算机的设计模式大部分是GOF收集总结的,<br>他们讲解设计模式是用的C++,而在Java中得到了大量应用,所以我们谈到设计模式<br>的时候多提到OO.其实模式更早应用于建筑学,Alexander的《建筑的永恒之道》讲的<br>就是设计模式。所以说设计模式应该是设计过程中积累下来的一些成型的东西。<br>更深入一点，《Java与模式》的作者认为模式起源于中国的道教思想，讲的是哲学。呵呵。<br>3，对于模式的使用，个人感觉，模式很大程度上是为了对应这类需求的所有情况，也就<br>是最复杂情况，最灵活情况，当我们实际的开发中并没有遇到这么多这样的情况。<br>所以在需要的时候使用，根据需求简化使用，而不是照搬。<br>4,虽然模式是相关的，但是只有知道了每个模式的区别点，才能更好的根据需求选择使用哪个模式。 
<img src ="http://www.blogjava.net/dreamstone/aggbug/92482.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-01-08 23:21 <a href="http://www.blogjava.net/dreamstone/archive/2007/01/08/92482.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>桥接模式和适配器模式的区别</title><link>http://www.blogjava.net/dreamstone/archive/2007/01/07/92268.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sun, 07 Jan 2007 13:53:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/01/07/92268.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/92268.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/01/07/92268.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/92268.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/92268.html</trackback:ping><description><![CDATA[很多时候经常容易把桥接模式和适配器模式弄混。那什么时候用桥接，什么时候用适配器呢 ？<br><br>共同点：桥接和适配器都是让两个东西配合工作<br>不同点：出发点不同。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;适配器：改变已有的两个接口，让他们相容。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;桥接模式：分离抽象化和实现，使两者的接口可以不同，目的是分离。<br><br>所以说，如果你拿到两个已有模块，想让他们同时工作，那么你使用的适配器。<br>如果你还什么都没有，但是想分开实现，那么桥接是一个选择。<br><br>桥接是先有桥，才有两端的东西<br>适配是先有两边的东西，才有适配器<br><br>桥接是在桥好了之后，两边的东西还可以变化。<br><br>例如游戏手柄，就象个桥，它把你的任何操作转化成指令。<br>（虽然，你可以任何操作组合，但是你的操作脱不开山下左右，a,b，选择 ，确定）<br>JRE本身就是一个就是一个很好的桥，先写好在linux上执行的Jre，再写好可以在windows下执行的JRE，<br>这样无论什么样的Java程序，只要配和相应的Jre就能在Linux或者Windows上运行.<br>两个Jre并没有限定你写什么样的程序，但要求你必须用Java来写。 
<img src ="http://www.blogjava.net/dreamstone/aggbug/92268.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-01-07 21:53 <a href="http://www.blogjava.net/dreamstone/archive/2007/01/07/92268.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java与模式 --- 适配器模式</title><link>http://www.blogjava.net/dreamstone/archive/2007/01/07/92229.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sun, 07 Jan 2007 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/01/07/92229.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/92229.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/01/07/92229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/92229.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/92229.html</trackback:ping><description><![CDATA[适配器模式：<br>如果你有两个编译好的(无源代码)类，类A有某些功能，但是需要一个xml读取模块才能工作，<br>这个模块要实现这个接口:<br>public interface XmlReader{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public InputStream xmlReader();<br>}<br>你的另一个类B恰好有这个功能，但是B实现的是这个接口:<br>public interface ReaderXml{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public InputStream readerXml();<br>}<br>这个时候我们的做法是写个适配器<br>public class Adapter implements XmlReader extends B{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;public InputStream xmlReader(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;return readerXml();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}<br>这个就是适配器模式了。<br>适配器模式还有另外一种实现方式<br>public class Adapter implements XmlReader<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReaderXml b = new B();<br>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; public InputStream xmlReader(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;return b.readerXml();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;}<br>} 
<img src ="http://www.blogjava.net/dreamstone/aggbug/92229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-01-07 16:07 <a href="http://www.blogjava.net/dreamstone/archive/2007/01/07/92229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的模式 －－－ 构造者模式</title><link>http://www.blogjava.net/dreamstone/archive/2007/01/07/92222.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sun, 07 Jan 2007 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2007/01/07/92222.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/92222.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2007/01/07/92222.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/92222.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/92222.html</trackback:ping><description><![CDATA[一，一般来说你要做一件复杂的事情的时候，把它分成多个小的部分来做是比较好的方法，<br>把每个小部分做完，然后结合成一个完整的事情。例如生产一辆汽车，你是一个个零件<br>生产完了，才组装成一辆辆汽车。这个就是建造模式的工作。<br>二，建造模式的角色<br>1、抽象建造者<br>2、具体构造者<br>3、导演者<br>4、产品角色<br>三、实现代码 ：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #000000">抽象构造者:<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img id=Codehighlighter1_28_171_Open_Image onclick="this.style.display='none'; Codehighlighter1_28_171_Open_Text.style.display='none'; Codehighlighter1_28_171_Closed_Image.style.display='inline'; Codehighlighter1_28_171_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_28_171_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_28_171_Closed_Text.style.display='none'; Codehighlighter1_28_171_Open_Image.style.display='inline'; Codehighlighter1_28_171_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span id=Codehighlighter1_28_171_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_28_171_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">构造零件</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;buildPart1();<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">构造零件</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;buildPart2();<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返还商品</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">abstract</span><span style="COLOR: #000000">&nbsp;Product&nbsp;retrieveResult();<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>具体构造者:<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img id=Codehighlighter1_224_568_Open_Image onclick="this.style.display='none'; Codehighlighter1_224_568_Open_Text.style.display='none'; Codehighlighter1_224_568_Closed_Image.style.display='inline'; Codehighlighter1_224_568_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_224_568_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_224_568_Closed_Text.style.display='none'; Codehighlighter1_224_568_Open_Image.style.display='inline'; Codehighlighter1_224_568_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ConcreteBuilder&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;Builder</span><span id=Codehighlighter1_224_568_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_224_568_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;Product&nbsp;product&nbsp;;<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img id=Codehighlighter1_287_402_Open_Image onclick="this.style.display='none'; Codehighlighter1_287_402_Open_Text.style.display='none'; Codehighlighter1_287_402_Closed_Image.style.display='inline'; Codehighlighter1_287_402_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_287_402_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_287_402_Closed_Text.style.display='none'; Codehighlighter1_287_402_Open_Image.style.display='inline'; Codehighlighter1_287_402_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Product&nbsp;retrieveResult()</span><span id=Codehighlighter1_287_402_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_287_402_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;product</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Product();<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;product.setPart1(buildPart1());<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;product.setPart2(buildPart2());<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;product;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img id=Codehighlighter1_431_484_Open_Image onclick="this.style.display='none'; Codehighlighter1_431_484_Open_Text.style.display='none'; Codehighlighter1_431_484_Closed_Image.style.display='inline'; Codehighlighter1_431_484_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_431_484_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_431_484_Closed_Text.style.display='none'; Codehighlighter1_431_484_Open_Image.style.display='inline'; Codehighlighter1_431_484_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Object&nbsp;buildPart1()</span><span id=Codehighlighter1_431_484_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_431_484_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">构造part1</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">23</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;part1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif">;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;part1;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img id=Codehighlighter1_513_566_Open_Image onclick="this.style.display='none'; Codehighlighter1_513_566_Open_Text.style.display='none'; Codehighlighter1_513_566_Closed_Image.style.display='inline'; Codehighlighter1_513_566_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_513_566_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_513_566_Closed_Text.style.display='none'; Codehighlighter1_513_566_Open_Image.style.display='inline'; Codehighlighter1_513_566_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Object&nbsp;buildPart2()</span><span id=Codehighlighter1_513_566_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_513_566_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">构造part2</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">28</span><span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;part2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;<img src="http://www.blogjava.net/Images/dot.gif">;<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;part2;<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img id=Codehighlighter1_590_746_Open_Image onclick="this.style.display='none'; Codehighlighter1_590_746_Open_Text.style.display='none'; Codehighlighter1_590_746_Closed_Image.style.display='inline'; Codehighlighter1_590_746_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_590_746_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_590_746_Closed_Text.style.display='none'; Codehighlighter1_590_746_Open_Image.style.display='inline'; Codehighlighter1_590_746_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Product</span><span id=Codehighlighter1_590_746_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_590_746_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;Part1;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;Part2;<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img id=Codehighlighter1_657_682_Open_Image onclick="this.style.display='none'; Codehighlighter1_657_682_Open_Text.style.display='none'; Codehighlighter1_657_682_Closed_Image.style.display='inline'; Codehighlighter1_657_682_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_657_682_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_657_682_Closed_Text.style.display='none'; Codehighlighter1_657_682_Open_Image.style.display='inline'; Codehighlighter1_657_682_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setPart1(Object&nbsp;Part1)</span><span id=Codehighlighter1_657_682_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_657_682_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.part1&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;part1;<br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img id=Codehighlighter1_719_744_Open_Image onclick="this.style.display='none'; Codehighlighter1_719_744_Open_Text.style.display='none'; Codehighlighter1_719_744_Closed_Image.style.display='inline'; Codehighlighter1_719_744_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_719_744_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_719_744_Closed_Text.style.display='none'; Codehighlighter1_719_744_Open_Image.style.display='inline'; Codehighlighter1_719_744_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setPart2(Object&nbsp;Part2)</span><span id=Codehighlighter1_719_744_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_719_744_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.part2&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;part2;<br></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">42</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">导演者</span><span style="COLOR: #008000"><br></span><span style="COLOR: #008080">43</span><span style="COLOR: #008000"><img id=Codehighlighter1_775_943_Open_Image onclick="this.style.display='none'; Codehighlighter1_775_943_Open_Text.style.display='none'; Codehighlighter1_775_943_Closed_Image.style.display='inline'; Codehighlighter1_775_943_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_775_943_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_775_943_Closed_Text.style.display='none'; Codehighlighter1_775_943_Open_Image.style.display='inline'; Codehighlighter1_775_943_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Director</span><span id=Codehighlighter1_775_943_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_775_943_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;Builder&nbsp;builder;<br></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img id=Codehighlighter1_827_941_Open_Image onclick="this.style.display='none'; Codehighlighter1_827_941_Open_Text.style.display='none'; Codehighlighter1_827_941_Closed_Image.style.display='inline'; Codehighlighter1_827_941_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_827_941_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_827_941_Closed_Text.style.display='none'; Codehighlighter1_827_941_Open_Image.style.display='inline'; Codehighlighter1_827_941_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;construct()</span><span id=Codehighlighter1_827_941_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_827_941_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;builder&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;ConcreteBuilder();<br></span><span style="COLOR: #008080">47</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;builder.retrieveResult();<br></span><span style="COLOR: #008080">58</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">49</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>
<img src ="http://www.blogjava.net/dreamstone/aggbug/92222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2007-01-07 15:19 <a href="http://www.blogjava.net/dreamstone/archive/2007/01/07/92222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>visitor模式概念-------------－-----   visitor模式进一步</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/20/88948.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Tue, 19 Dec 2006 17:26:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/20/88948.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/88948.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/20/88948.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/88948.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/88948.html</trackback:ping><description><![CDATA[<p>visitor模式理论及学术概念-------------－-----&nbsp;&nbsp; visitor模式进一步<br>一，访问者模式的角色：<br>抽象访问者：声明一个或者多个访问操作，形成所有的具体元素都要实现的接口<br>具体访问者：实现抽象访问者所声明的接口<br>抽象节点：声明一个接受操作，接受一个访问者对象作为参量<br>具体节点：实现了抽象元素所规定的接受操作<br>结构对象：遍历结构中的所有元素，类似List Set等<br>二，在什么情况下应当使用访问者模式<br>访问者模式应该用在被访问类结构比较稳定的时候，换言之系统很少出现增加新节点的<br>情况。因为访问者模式对开－闭原则的支持并不好，访问者模式允许在节点中加入方法，<br>是倾斜的开闭原则，类似抽象工厂。<br>三，访问者模式的缺点：<br>1，增加节点困难<br>2，破坏了封装<br>因为访问者模式的缺点和复杂性，很多设计师反对使用访问者模式。个人感觉应该在了解的<br>情况下考虑衡量选择。</p>
<p>最后的部分： <br>看完本文，如果你对visitor模式有更多的兴趣，想了解更多请看如下几篇文章。<br>1,<a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html"><font color=#7297ce>静态分派，动态分派，多分派，单分派 --------------&nbsp;&nbsp; visitor模式准备</font></a><br>2<a href="http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html"><font color=#7297ce>,访问差异类型的集合类 ------------------------&nbsp;&nbsp; visitor模式入门</font></a><br>3,visitor模式理论及学术概念-------------－-----&nbsp;&nbsp; visitor模式进一步<font color=#7297ce>(<font color=#000000>本文）</font></font><br>4，<a href="http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html"><font color=#7297ce>重载overloading和覆写overriding哪个更早执行--&nbsp;&nbsp; visitor帮助篇</font></a><br>虽然排列顺序是1,2,3,4 但是我个人建议的学习方式是2,1,3,4因为这个顺序更方便一般人理解</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/88948.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-20 01:26 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88948.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>静态分派，动态分派，多分派，单分派 --------------   visitor模式准备</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Tue, 19 Dec 2006 17:08:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/88947.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/88947.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/88947.html</trackback:ping><description><![CDATA[一，静态分派:<br>1，定义：发生在编译时期，分派根据静态类型信息发生，重载就是静态分派<br>2，什么是静态类型：变量被声明时的类型是静态类型<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;什么是动态类型：变量所引用的对象的真实类型<br>3，有两个类,BlackCat ,WhiteCat都继承自Cat<br>如下调用<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_9_10_Open_Image onclick="this.style.display='none'; Codehighlighter1_9_10_Open_Text.style.display='none'; Codehighlighter1_9_10_Closed_Image.style.display='inline'; Codehighlighter1_9_10_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_9_10_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_9_10_Closed_Text.style.display='none'; Codehighlighter1_9_10_Open_Image.style.display='inline'; Codehighlighter1_9_10_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Cat</span><span id=Codehighlighter1_9_10_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_9_10_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_38_39_Open_Image onclick="this.style.display='none'; Codehighlighter1_38_39_Open_Text.style.display='none'; Codehighlighter1_38_39_Closed_Image.style.display='inline'; Codehighlighter1_38_39_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_38_39_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_38_39_Closed_Text.style.display='none'; Codehighlighter1_38_39_Open_Image.style.display='inline'; Codehighlighter1_38_39_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;WhiteCat&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;Cat</span><span id=Codehighlighter1_38_39_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_38_39_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_67_68_Open_Image onclick="this.style.display='none'; Codehighlighter1_67_68_Open_Text.style.display='none'; Codehighlighter1_67_68_Closed_Image.style.display='inline'; Codehighlighter1_67_68_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_67_68_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_67_68_Closed_Text.style.display='none'; Codehighlighter1_67_68_Open_Image.style.display='inline'; Codehighlighter1_67_68_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BlackCat&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;Cat</span><span id=Codehighlighter1_67_68_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_67_68_Open_Text><span style="COLOR: #000000">{}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_90_462_Open_Image onclick="this.style.display='none'; Codehighlighter1_90_462_Open_Text.style.display='none'; Codehighlighter1_90_462_Closed_Image.style.display='inline'; Codehighlighter1_90_462_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_90_462_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_90_462_Closed_Text.style.display='none'; Codehighlighter1_90_462_Open_Image.style.display='inline'; Codehighlighter1_90_462_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Person&nbsp;</span><span id=Codehighlighter1_90_462_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_90_462_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_118_155_Open_Image onclick="this.style.display='none'; Codehighlighter1_118_155_Open_Text.style.display='none'; Codehighlighter1_118_155_Closed_Image.style.display='inline'; Codehighlighter1_118_155_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_118_155_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_118_155_Closed_Text.style.display='none'; Codehighlighter1_118_155_Open_Image.style.display='inline'; Codehighlighter1_118_155_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;feed(Cat&nbsp;cat)</span><span id=Codehighlighter1_118_155_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_118_155_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">feed&nbsp;cat</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_188_230_Open_Image onclick="this.style.display='none'; Codehighlighter1_188_230_Open_Text.style.display='none'; Codehighlighter1_188_230_Closed_Image.style.display='inline'; Codehighlighter1_188_230_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_188_230_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_188_230_Closed_Text.style.display='none'; Codehighlighter1_188_230_Open_Image.style.display='inline'; Codehighlighter1_188_230_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;feed(WhiteCat&nbsp;cat)</span><span id=Codehighlighter1_188_230_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_188_230_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">feed&nbsp;WhiteCat</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_263_305_Open_Image onclick="this.style.display='none'; Codehighlighter1_263_305_Open_Text.style.display='none'; Codehighlighter1_263_305_Closed_Image.style.display='inline'; Codehighlighter1_263_305_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_263_305_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_263_305_Closed_Text.style.display='none'; Codehighlighter1_263_305_Open_Image.style.display='inline'; Codehighlighter1_263_305_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;feed(BlackCat&nbsp;cat)</span><span id=Codehighlighter1_263_305_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_263_305_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">feed&nbsp;BlackCat</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_347_459_Open_Image onclick="this.style.display='none'; Codehighlighter1_347_459_Open_Text.style.display='none'; Codehighlighter1_347_459_Closed_Image.style.display='inline'; Codehighlighter1_347_459_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_347_459_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_347_459_Closed_Text.style.display='none'; Codehighlighter1_347_459_Open_Image.style.display='inline'; Codehighlighter1_347_459_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)&nbsp;</span><span id=Codehighlighter1_347_459_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_347_459_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;wc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;WhiteCat();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;bc&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;BlackCat();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Person&nbsp;p&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Person();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.feed(wc);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.feed(bc);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top></span></div>
运行结果是:<br>feed cat<br>feed cat<br>这样的结果是因为重载是静态分派，在编译器执行的，取决于变量的声明类型，因为wc ,bc都是Cat所以调用的都是feed(Cat cat)的函数.<br>二，动态分派<br>1，定义：发生在运行期，动态分派，动态的置换掉某个方法。<br>还是上边类似的例子：<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img id=Codehighlighter1_9_67_Open_Image onclick="this.style.display='none'; Codehighlighter1_9_67_Open_Text.style.display='none'; Codehighlighter1_9_67_Closed_Image.style.display='inline'; Codehighlighter1_9_67_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_9_67_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_9_67_Closed_Text.style.display='none'; Codehighlighter1_9_67_Open_Image.style.display='inline'; Codehighlighter1_9_67_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Cat</span><span id=Codehighlighter1_9_67_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_9_67_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_29_65_Open_Image onclick="this.style.display='none'; Codehighlighter1_29_65_Open_Text.style.display='none'; Codehighlighter1_29_65_Closed_Image.style.display='inline'; Codehighlighter1_29_65_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_29_65_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_29_65_Closed_Text.style.display='none'; Codehighlighter1_29_65_Open_Image.style.display='inline'; Codehighlighter1_29_65_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;eat()</span><span id=Codehighlighter1_29_65_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_29_65_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">cat&nbsp;eat</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_102_251_Open_Image onclick="this.style.display='none'; Codehighlighter1_102_251_Open_Text.style.display='none'; Codehighlighter1_102_251_Closed_Image.style.display='inline'; Codehighlighter1_102_251_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_102_251_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_102_251_Closed_Text.style.display='none'; Codehighlighter1_102_251_Open_Image.style.display='inline'; Codehighlighter1_102_251_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;BlackCat&nbsp;</span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000">&nbsp;Cat</span><span id=Codehighlighter1_102_251_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_102_251_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_122_164_Open_Image onclick="this.style.display='none'; Codehighlighter1_122_164_Open_Text.style.display='none'; Codehighlighter1_122_164_Closed_Image.style.display='inline'; Codehighlighter1_122_164_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_122_164_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_122_164_Closed_Text.style.display='none'; Codehighlighter1_122_164_Open_Image.style.display='inline'; Codehighlighter1_122_164_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;eat()</span><span id=Codehighlighter1_122_164_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_122_164_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">black&nbsp;cat&nbsp;eat</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">);<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img id=Codehighlighter1_205_249_Open_Image onclick="this.style.display='none'; Codehighlighter1_205_249_Open_Text.style.display='none'; Codehighlighter1_205_249_Closed_Image.style.display='inline'; Codehighlighter1_205_249_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_205_249_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_205_249_Closed_Text.style.display='none'; Codehighlighter1_205_249_Open_Image.style.display='inline'; Codehighlighter1_205_249_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;main(String[]&nbsp;args)</span><span id=Codehighlighter1_205_249_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_205_249_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;cat&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;BlackCat();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cat.eat();<br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
这个时候的结果是:<br>black cat eat<br>这样的结果是因为在执行期发生了向下转型，就是动态分派了。<br><br>三，单分派：<br>1，定义：根据一个宗量的类型进行方法的选择<br>四,多分派：<br>1，定义：根据多于一个宗量的类型对方法的选择<br>2，说明：多分派其实是一系列的单分派组成的，区别的地方就是这些但分派不能分割。<br>3,C++ ,Java都是动态单分派，静态多分派语言<br>多分派的语言有：CLOS&nbsp; Cecil<br><br>最后的部分：
<p>看完本文，如果你对visitor模式有更多的兴趣，想了解更多请看如下几篇文章。<br>1,<a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html"><font color=#7297ce>静态分派，动态分派，多分派，单分派 --------------&nbsp;&nbsp; visitor模式准备</font></a><a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html"><font color=#7297ce>(<font color=#000000>本文）</font><br></font></a>2<a href="http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html"><font color=#7297ce>,访问差异类型的集合类 ------------------------&nbsp;&nbsp; visitor模式入门</font></a><br>3,<a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88948.html">visitor模式理论及学术概念-------------－-----&nbsp;&nbsp; visitor模式进一步<br></a>4，<a href="http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html">重载overloading和覆写overriding哪个更早执行--&nbsp;&nbsp; visitor帮助篇</a><br>虽然排列顺序是1,2,3,4但是我个人建议的学习方式是2,1,3,4因为这个顺序更方便一般人理解</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/88947.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-20 01:08 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>访问差异类型的集合类--visitor模式入门</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 18 Dec 2006 12:18:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/88623.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html#Feedback</comments><slash:comments>13</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/88623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/88623.html</trackback:ping><description><![CDATA[<p>访问差异类型的集合类--visitor模式入门<br>本文对应代码下载<a href="http://www.blogjava.net/Files/dreamstone/visitor.rar">这里</a><br>一，问题提出<br>访问同一类型的集合类是我们最常见的事情了，我们工作中这样的代码太常见了。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #000000">Iterator&nbsp;ie&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;list.iterator();<br></span><span style="COLOR: #008080">2</span> <span style="COLOR: #000000"><img id=Codehighlighter1_50_96_Open_Image onclick="this.style.display='none'; Codehighlighter1_50_96_Open_Text.style.display='none'; Codehighlighter1_50_96_Closed_Image.style.display='inline'; Codehighlighter1_50_96_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_50_96_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_50_96_Closed_Text.style.display='none'; Codehighlighter1_50_96_Open_Image.style.display='inline'; Codehighlighter1_50_96_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> </span><span style="COLOR: #0000ff">while</span> <span style="COLOR: #000000">(ie.hasNext())</span> <span id=Codehighlighter1_50_96_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_50_96_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">3</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Person&nbsp;p&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;(Person)ie.next();<br></span><span style="COLOR: #008080">4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;p.doWork();<br></span><span style="COLOR: #008080">5</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span></div>
<p><br>这种访问的特点是集合类中的对象是同一类对象Person，他们拥有功能的方法run,我们调用的恰好是这个共同的方法。<br>在大部份的情况下，这个是可以的，但在一些复杂的情况，如被访问者的继承结构复杂，被访问者的并不是同一类对象，<br>也就是说不是继承自同一个根类。方法名也并不相同。例如Java GUI中的事件就是一个例子。<br>例如这样的问题，有如下类和方法:<br>类：PA ,方法：runPA();<br>类：PB ,方法：runPB();<br>类：PC ,方法：runPC();<br>类：PD ,方法：runPD();<br>类：PE ,方法：runPE();<br>有一个集合类List<br>List list = new ArrayList();<br>list.add(new PA());<br>list.add(new PB());<br>list.add(new PC());<br>list.add(new PD());<br>list.add(new PE());<br>....<br>二:解决<br>要求能访问到每个类的对应的方法。我们第一反应应该是这样的。<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span> <img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> <span style="COLOR: #000000">Iterator&nbsp;ie&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;list.iterator();<br></span><span style="COLOR: #008080">&nbsp;2</span> <span style="COLOR: #000000"><img id=Codehighlighter1_50_330_Open_Image onclick="this.style.display='none'; Codehighlighter1_50_330_Open_Text.style.display='none'; Codehighlighter1_50_330_Closed_Image.style.display='inline'; Codehighlighter1_50_330_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_50_330_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_50_330_Closed_Text.style.display='none'; Codehighlighter1_50_330_Open_Image.style.display='inline'; Codehighlighter1_50_330_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> </span><span style="COLOR: #0000ff">while</span> <span style="COLOR: #000000">(ie.hasNext())</span> <span id=Codehighlighter1_50_330_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_50_330_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;obj&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;ie.next();<br></span><span style="COLOR: #008080">&nbsp;4</span> <span style="COLOR: #000000"><img id=Codehighlighter1_100_124_Open_Image onclick="this.style.display='none'; Codehighlighter1_100_124_Open_Text.style.display='none'; Codehighlighter1_100_124_Closed_Image.style.display='inline'; Codehighlighter1_100_124_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_100_124_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_100_124_Closed_Text.style.display='none'; Codehighlighter1_100_124_Open_Image.style.display='inline'; Codehighlighter1_100_124_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000">&nbsp;(obj&nbsp;</span> <span style="COLOR: #0000ff">instanceof</span> <span style="COLOR: #000000">&nbsp;PA)</span> <span id=Codehighlighter1_100_124_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_100_124_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;5</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((PA)obj).runPA();<br></span><span style="COLOR: #008080">&nbsp;6</span> <span style="COLOR: #000000"><img id=Codehighlighter1_151_175_Open_Image onclick="this.style.display='none'; Codehighlighter1_151_175_Open_Text.style.display='none'; Codehighlighter1_151_175_Closed_Image.style.display='inline'; Codehighlighter1_151_175_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_151_175_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_151_175_Closed_Text.style.display='none'; Codehighlighter1_151_175_Open_Image.style.display='inline'; Codehighlighter1_151_175_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #0000ff">else</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000">(obj&nbsp;</span> <span style="COLOR: #0000ff">instanceof</span> <span style="COLOR: #000000">&nbsp;PB)</span> <span id=Codehighlighter1_151_175_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_151_175_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;7</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((PB)obj).runPB();<br></span><span style="COLOR: #008080">&nbsp;8</span> <span style="COLOR: #000000"><img id=Codehighlighter1_202_226_Open_Image onclick="this.style.display='none'; Codehighlighter1_202_226_Open_Text.style.display='none'; Codehighlighter1_202_226_Closed_Image.style.display='inline'; Codehighlighter1_202_226_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_202_226_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_202_226_Closed_Text.style.display='none'; Codehighlighter1_202_226_Open_Image.style.display='inline'; Codehighlighter1_202_226_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #0000ff">else</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000">(obj&nbsp;</span> <span style="COLOR: #0000ff">instanceof</span> <span style="COLOR: #000000">&nbsp;PC)</span> <span id=Codehighlighter1_202_226_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_202_226_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;9</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((PC)obj).runPC();<br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000"><img id=Codehighlighter1_253_277_Open_Image onclick="this.style.display='none'; Codehighlighter1_253_277_Open_Text.style.display='none'; Codehighlighter1_253_277_Closed_Image.style.display='inline'; Codehighlighter1_253_277_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_253_277_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_253_277_Closed_Text.style.display='none'; Codehighlighter1_253_277_Open_Image.style.display='inline'; Codehighlighter1_253_277_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #0000ff">else</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000">(obj&nbsp;</span> <span style="COLOR: #0000ff">instanceof</span> <span style="COLOR: #000000">&nbsp;PD)</span> <span id=Codehighlighter1_253_277_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_253_277_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((PD)obj).runPD();<br></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000"><img id=Codehighlighter1_304_328_Open_Image onclick="this.style.display='none'; Codehighlighter1_304_328_Open_Text.style.display='none'; Codehighlighter1_304_328_Closed_Image.style.display='inline'; Codehighlighter1_304_328_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_304_328_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_304_328_Closed_Text.style.display='none'; Codehighlighter1_304_328_Open_Image.style.display='inline'; Codehighlighter1_304_328_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #0000ff">else</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">if</span> <span style="COLOR: #000000">(obj&nbsp;</span> <span style="COLOR: #0000ff">instanceof</span> <span style="COLOR: #000000">&nbsp;PE)</span> <span id=Codehighlighter1_304_328_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_304_328_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;((PE)obj).runPE();<br></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span></div>
<p><br>三：新问题及分析解决<br>当数目变多的时候，维护if else是个费力气的事情：<br>仔细分析if,else做的工作，首先判断类型，然後根据类型执行相应的函数<br>如何才能解决这两个问题呢？首先想到的是java的多态，多态就是根据参数执行相应的内容，<br>能很容易的解决第二个问题，我们可以写这样一个类：<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span> <img id=Codehighlighter1_20_232_Open_Image onclick="this.style.display='none'; Codehighlighter1_20_232_Open_Text.style.display='none'; Codehighlighter1_20_232_Closed_Image.style.display='inline'; Codehighlighter1_20_232_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_20_232_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_20_232_Closed_Text.style.display='none'; Codehighlighter1_20_232_Open_Image.style.display='inline'; Codehighlighter1_20_232_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">class</span> <span style="COLOR: #000000">&nbsp;visitor</span> <span id=Codehighlighter1_20_232_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_20_232_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;2</span> <span style="COLOR: #000000"><img id=Codehighlighter1_45_62_Open_Image onclick="this.style.display='none'; Codehighlighter1_45_62_Open_Text.style.display='none'; Codehighlighter1_45_62_Closed_Image.style.display='inline'; Codehighlighter1_45_62_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_45_62_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_45_62_Closed_Text.style.display='none'; Codehighlighter1_45_62_Open_Image.style.display='inline'; Codehighlighter1_45_62_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;run(PA&nbsp;pa)</span> <span id=Codehighlighter1_45_62_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_45_62_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;3</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pa.runPA();<br></span><span style="COLOR: #008080">&nbsp;4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span> <span style="COLOR: #000000"><img id=Codehighlighter1_87_104_Open_Image onclick="this.style.display='none'; Codehighlighter1_87_104_Open_Text.style.display='none'; Codehighlighter1_87_104_Closed_Image.style.display='inline'; Codehighlighter1_87_104_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_87_104_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_87_104_Closed_Text.style.display='none'; Codehighlighter1_87_104_Open_Image.style.display='inline'; Codehighlighter1_87_104_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;run(PB&nbsp;pb)</span> <span id=Codehighlighter1_87_104_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_87_104_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;6</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pb.runPB();<br></span><span style="COLOR: #008080">&nbsp;7</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;8</span> <span style="COLOR: #000000"><img id=Codehighlighter1_129_146_Open_Image onclick="this.style.display='none'; Codehighlighter1_129_146_Open_Text.style.display='none'; Codehighlighter1_129_146_Closed_Image.style.display='inline'; Codehighlighter1_129_146_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_129_146_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_129_146_Closed_Text.style.display='none'; Codehighlighter1_129_146_Open_Image.style.display='inline'; Codehighlighter1_129_146_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;run(PC&nbsp;pc)</span> <span id=Codehighlighter1_129_146_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_129_146_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;9</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc.runPC();<br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000"><img id=Codehighlighter1_171_188_Open_Image onclick="this.style.display='none'; Codehighlighter1_171_188_Open_Text.style.display='none'; Codehighlighter1_171_188_Closed_Image.style.display='inline'; Codehighlighter1_171_188_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_171_188_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_171_188_Closed_Text.style.display='none'; Codehighlighter1_171_188_Open_Image.style.display='inline'; Codehighlighter1_171_188_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;run(PD&nbsp;pd)</span> <span id=Codehighlighter1_171_188_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_171_188_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pd.runPD();<br></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000"><img id=Codehighlighter1_213_230_Open_Image onclick="this.style.display='none'; Codehighlighter1_213_230_Open_Text.style.display='none'; Codehighlighter1_213_230_Closed_Image.style.display='inline'; Codehighlighter1_213_230_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top> <img id=Codehighlighter1_213_230_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_213_230_Closed_Text.style.display='none'; Codehighlighter1_213_230_Open_Image.style.display='inline'; Codehighlighter1_213_230_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;run(PE&nbsp;pe)</span> <span id=Codehighlighter1_213_230_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_213_230_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pe.runPE();<br></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span></div>
<p><br>这样只要调用run方法，传入对应的参数就能执行了。<br>还有一个问题就是判断类型。由于重载(overloading)是静态多分配（java语言本身是支持"静态多分配"的。<br>关于这个概念请看这里)所以造成重载只根据传入对象的定义类型，而不是实际的类型，所以必须在传入前就确定类型，<br>这可是个难的问题,因为在容器中对象全是Object，出来后要是判断是什么类型必须用<br>if (xx instanceof xxx)这种方法，如果用这种方法启不是又回到了原点，有没有什么更好的办法呢？</p>
<p>我们知到Java还有另外一个特点，覆写(overriding)，而覆写是"动态单分配"的（关于这个概念见这里)，<br>那如何利用这个来实现呢？看下边这个方法:<br>&nbsp;我们让上边的一些类PA PB PC PD PE都实现一个接口P,加入一个方法,accept();<br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span> <img id=Codehighlighter1_29_55_Open_Image onclick="this.style.display='none'; Codehighlighter1_29_55_Open_Text.style.display='none'; Codehighlighter1_29_55_Closed_Image.style.display='inline'; Codehighlighter1_29_55_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_29_55_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_29_55_Closed_Text.style.display='none'; Codehighlighter1_29_55_Open_Image.style.display='inline'; Codehighlighter1_29_55_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> <span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;accept(visitor&nbsp;v)</span> <span id=Codehighlighter1_29_55_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_29_55_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;2</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000">把自己传入1</span> <span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;3</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top> </span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;v.run(</span> <span style="COLOR: #0000ff">this</span> <span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">&nbsp;4</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;5</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>然後在visitor中加入一个方法<br></span><span style="COLOR: #008080">&nbsp;6</span> <span style="COLOR: #000000"><img id=Codehighlighter1_95_124_Open_Image onclick="this.style.display='none'; Codehighlighter1_95_124_Open_Text.style.display='none'; Codehighlighter1_95_124_Closed_Image.style.display='inline'; Codehighlighter1_95_124_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_95_124_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_95_124_Closed_Text.style.display='none'; Codehighlighter1_95_124_Open_Image.style.display='inline'; Codehighlighter1_95_124_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> </span><span style="COLOR: #0000ff">public</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">void</span> <span style="COLOR: #000000">&nbsp;run(P&nbsp;p)</span> <span id=Codehighlighter1_95_124_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_95_124_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;7</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="COLOR: #008000">//</span> <span style="COLOR: #008000">把自己传入2</span> <span style="COLOR: #008000"><br></span><span style="COLOR: #008080">&nbsp;8</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top> </span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;p.accept(</span> <span style="COLOR: #0000ff">this</span> <span style="COLOR: #000000">);<br></span><span style="COLOR: #008080">&nbsp;9</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #008000">//</span> <span style="COLOR: #008000">这样你在遍历中可以这样写</span> <span style="COLOR: #008000"><br></span><span style="COLOR: #008080">11</span> <span style="COLOR: #008000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top> </span><span style="COLOR: #000000">Visitor&nbsp;v&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;</span> <span style="COLOR: #0000ff">new</span> <span style="COLOR: #000000">&nbsp;Visitor();<br></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>Iterator&nbsp;ie&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;list.iterator();<br></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000"><img id=Codehighlighter1_218_257_Open_Image onclick="this.style.display='none'; Codehighlighter1_218_257_Open_Text.style.display='none'; Codehighlighter1_218_257_Closed_Image.style.display='inline'; Codehighlighter1_218_257_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top> <img id=Codehighlighter1_218_257_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_218_257_Closed_Text.style.display='none'; Codehighlighter1_218_257_Open_Image.style.display='inline'; Codehighlighter1_218_257_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top> </span><span style="COLOR: #0000ff">while</span> <span style="COLOR: #000000">(ie.hasNext())</span> <span id=Codehighlighter1_218_257_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"> </span><span id=Codehighlighter1_218_257_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;p&nbsp;</span> <span style="COLOR: #000000">=</span> <span style="COLOR: #000000">&nbsp;(P)ie.next();<br></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p.accept(v);<br></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span> </span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" align=top>}</span> </div>
<p><br>首先执行的是"把自己传入2"，在这里由于Java的特性，实际执行的是子类的accept(),也就是实际类的accept<br>然後是"把自己传入1"，在这里再次把this传入，就明确类型，ok我们巧妙的利用overriding解决了这个问题<br>其实归纳一下第二部分，一个关键点是"自己认识自己"，是不是很可笑。<br>其实在计算计技术领域的很多技术上看起来很高深的东西，其实就是现有社会中人的生活方式的一种映射<br>而且这种方式是简单的不能再简单的方式。上边的全部过程基本上是一个简单的visitor模式实现,visitor模式<br>已经是设计模式中比较复杂的模式了，但其实原理简单到你想笑。看看下边这个比喻也许你的理解会更深刻。</p>
<p>四：一个帮助理解的比喻：<br>题目：指挥工人工作<br>条件：你有10个全能工人，10样相同工作。<br>需求：做完工作<br>实现：大喊一声所有人去工作</p>
<p>条件变了，工人不是全能，但是工作相同，ok问题不大<br>条件再变,工作不是相同，但工人是全能，ok问题不大</p>
<p>以上三种情况在现实生活中是很少发生得，最多的情况是这样：<br>10个工人，每人会做一种工作，10样工作。你又一份名单Collection)写着谁做什么。但你不认识任何人<br>这个时候你怎么指挥呢，方案一：<br>你可以一个个的叫工人，然後问他们名字，认识他们，查名单，告诉他们做什么工作。<br>你可以直接叫出他们名字，告诉他们干什么，不需要知到他是谁。<br>看起来很简单。但如果你要指挥10万人呢 ？而且人员是流动的，每天的人不同，你每天拿到一张文档。<br>其实很简单，最常用的做法是，你把这份名单贴在墙上，然後大喊一声，所有人按照去看，按照自己的分配情况去做。<br>这里利用的关键点是"所有工人自己认识自己"，你不能苛求每个工人会做所有工作，不能苛求所有工作相同，但你<br>能要求所有工人都认识自己。</p>
<p>再想想我们开始的程序,每个工人对应着PA PB PC PD PE....<br>所有的工人都使工人P<br>每个工人会做的东西不一样runPA runPB runPC<br>你有一份名单Visitor（重载）记录着谁做什么工作。</p>
<p>看完上边这些，你是不是会产生如下的问题：<br>问题：为什么不把这些方法的方法名做成一样的，那就可以解决了。<br>例如，我们每个PA ,PB ,PC都加入一个run 方法，然後run内部再调用自己对应的runPx()方法。<br>答案：有些时候从不同的角度考虑，或者因为实现的复杂度早成很难统一方法名。<br>例如上边指挥人工作的例子的例子，其实run方法就是大叫一声去工作，因为每个工人只会做一种工作，所以能行<br>但我们不能要求所有人只能会做一种事情，这个要求很愚蠢。所以如果每个工人会干两种或者多种工作呢,<br>也就是我PA 有runPA() walkPA()等等方法， PB有runPB() climbPB()等等。。。<br>这个时候按照名单做事才是最好的办法。</p>
<p>五：作者的话<br>所以说模式中很多复杂的东西，在现实中其实是很基本的东西，多多代入代出能帮助理解模式。</p>
<p>看完本文，如果你对visitor模式有更多的兴趣，想了解更多请看如下几篇文章。<br>1,<a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88947.html">静态分派，动态分派，多分派，单分派 --------------&nbsp;&nbsp; visitor模式准备<br></a>2,访问差异类型的集合类 ------------------------&nbsp;&nbsp; visitor模式入门（本文）<br><a href="http://www.blogjava.net/dreamstone/archive/2006/12/20/88948.html">3,visitor模式理论及学术概念-------------－-----&nbsp;&nbsp; visitor模式深入</a><br>4，<a href="http://www.blogjava.net/dreamstone/archive/2006/12/18/88625.html">重载overloading和覆写overriding哪个更早执行--&nbsp;&nbsp; visitor帮助篇 <br></a>虽然排列顺序是1,2,3,4 但是我个人建议的学习方式是2,1,3,4因为这个顺序更方便一般人理解</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br>&nbsp;</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/88623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-18 20:18 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/18/88623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>控制反转的资料的集合及简单的概念对比</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/04/85428.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 04 Dec 2006 09:57:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/04/85428.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/85428.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/04/85428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/85428.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/85428.html</trackback:ping><description><![CDATA[<p>控制反转：<br>控制反转的资料的集合<br>参考一、<br>标题：向依赖关系宣战－－－－依赖倒置、控制反转和依赖注入辨析<br><a href="http://www.contextfree.net/wangyw/source/dip_ioc.html">url:http://www.contextfree.net/wangyw/source/dip_ioc.html</a><br>说明:详细分析了几个概念的不同<br>参考二、<br>Spring guide<br>参考三、<br>WebWork In Action IOC一章<br>参考四、<br>Martin fowler的文章<br><a href="http://www.blogjava.net/Files/dreamstone/DependencyInjection.rar">http://www.blogjava.net/Files/dreamstone/DependencyInjection.rar</a><br>强烈建议大家看一下第一篇文章和第四篇，作者写的真的很好<br></p>
<p>对比依赖倒置，控制反转，依赖注入?<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>1，依赖倒置：<br>先说明什么是"正置"<br>正置就是，当你设计一些类库的时候，考虑到用户的需要定义一些接口，用户的应用程序依赖这些接口</p>
<p>对比"正置"和"倒置"<br>正置：应用依赖接口，接口由类库设计者定义<br>优点：类库实现上自由度大，实现容易。<br>缺点：类库设计复杂，要预测应用的需求，同时有可能不符合应用的需求</p>
<p>倒置：应用定义接口，类库设计者实现接口，按照接口实现类库<br>优点：类库设计不再需要预测，肯定符合应用需求<br>缺点：类库有可能难以实现</p>
<p>简单来说，正置和倒置的区别在于，谁来制定标准。现实中因为需求的定义是客户决定的，所以倒置更<br>适合程序的设计。从需求出发，到底层实现。</p>
<p>使用目的：便于应用按照需求设计<br>关注点:接口的设计<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>2，控制反转：<br>正常的控制：<br>&nbsp;没有一定的控制流程，下一个流程由上一个流程决定，实现应用需要自己控制流程<br>控制反转&nbsp; ：<br>&nbsp;抽象出固定的流程，实现应用就是填充流程中的一个个点。<br>&nbsp;所有的框架都是基于控制反转的。Windows GUI开发也多是这样。<br>目的：高度抽象，设计框架<br>关注点：流程的设计<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>3,依赖注入<br>原始的情况：<br>&nbsp;应用自己new 类，或者使用工厂模式创建类<br>依赖注入：<br>&nbsp;容器创建类，通过构造函数，setter方法，接口等方法，运行时"注入"到应用中</p>
<p>实现：<br>Spring&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;setter方法<br>webwork IOC&nbsp;&nbsp;实现接口的方法<br>pico&nbsp;&nbsp;&nbsp;构造函数的方法</p>
<p>目的：完全分离开发<br>关注点：构造对象</p>
<p>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>关系：<br>"控制反转"是"依赖倒置"的一种,"依赖注入"是在"控制反转"的基础上，让容器来完成"注入"过程。<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>最需要依赖注入的情况：<br>"调用者"和多个"被调用者"分别开发，分别打包分发，实施者根据实际情况决定使用哪个"被调用者"被使用<br>做成可配制的，这种情况是经常需要的。这个时候调用者内不能出现这样的代码:<br>interface inter = new interfaceimplA();类似的语句。因为使用的可能是interfaceimplB<br>为了避免这样语句的出现，我们直接使用接口，而对象的构造推迟，让容器根据实施者的配制来构造，并注入<br>正确的位置。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br>&nbsp;</p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/85428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-04 17:57 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/04/85428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>依赖倒置、控制反转和依赖注入辨析</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/04/85400.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 04 Dec 2006 08:50:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/04/85400.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/85400.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/04/85400.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/85400.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/85400.html</trackback:ping><description><![CDATA[转载自：<a href="http://www.contextfree.net/wangyw/source/dip_ioc.html">http://www.contextfree.net/wangyw/source/dip_ioc.html</a><br>
<p class=subheading>依赖倒置、控制反转和依赖注入辨析</p>
<p class=separator1>&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　在《道法自然——面向对象实践指南》一书中，我们采用了一个对立统一的辩证关系来说明&#8220;模板方法&#8221;模式—— &#8220;正向依赖 vs. 依赖倒置&#8221;（参见：《道法自然》第15章[王咏武， 王咏刚 2004]）。这种把&#8220;好莱坞&#8221;原则和 &#8220;依赖倒置&#8221;原则等量齐观的看法其实来自于轻量级容器PicoContainer主页上的一段话：<br>　　&#8220;控制反转（Inversion of Control）的一个著名的同义原则是由Robert C. Martin提出的依赖倒置原则（Dependency Inversion Principle），它的另一个昵称是好莱坞原则（Hollywood Principle：不要调用我，让我来调用你）&#8221;[PicoContainer 2004]。<br>　　和网友们在CSDN Blog上进行了深入的讨论后，我又把这些概念重新梳理了一下。我发现，这几个概念虽然在思路和动机等宏观层面上是统一的，但在具体的应用层面还是存在着许多很微妙的差别。本文通过几个简单的例子对依赖倒置（Dependency Inversion Principle）、控制反转（Inversion of Control）、依赖注入（Dependency Injection）等概念进行了更为深入的辨析，也算是对于《道法自然》正文内容的一个补充吧。 </p>
</div>
<a name=dependency></a>
<p class=separator1>依赖和耦合（Dependency and Coupling）&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　Rational Rose的帮助文档上是这样定义&#8220;依赖&#8221;关系的：&#8220;依赖描述了两个模型元素之间的关系，如果被依赖的模型元素发生变化就会影响到另一个模型元素。典型的，在类图上，依赖关系表明客户类的操作会调用服务器类的操作。&#8221;<br>　　Martin Fowler在《Reducing Coupling》一文中这样描述耦合：&#8220;如果改变程序的一个模块要求另一个模块同时发生变化，就认为这两个模块发生了耦合。&#8221; [Fowler 2001]<br>　　从上面的定义可以看出：如果模块A调用模块B提供的方法，或访问模块B中的某些数据成员（当然，在面向对象开发中一般不提倡这样做），我们就认为模块A依赖于模块B，模块A和模块B之间发生了耦合。<br>　　那么，依赖对于我们来说究竟是好事还是坏事呢？<br>　　由于人类的理解力有限，大多数人难以理解和把握过于复杂的系统。把软件系统划分成多个模块，可以有效控制模块的复杂度，使每个模块都易于理解和维护。但在这种情况下，模块之间就必须以某种方式交换信息，也就是必然要发生某种耦合关系。如果某个模块和其它模块没有任何关联（哪怕只是潜在的或隐含的依赖关系），我们就几乎可以断定，该模块不属于此软件系统，应该从系统中剔除。如果所有模块之间都没有任何耦合关系，其结果必然是：整个软件不过是多个互不相干的系统的简单堆积，对每个系统而言，所有功能还是要在一个模块中实现，这等于没有做任何模块的分解。<br>　　因此，模块之间必定会有这样或那样的依赖关系，永远不要幻想消除所有依赖。但是，过强的耦合关系（如一个模块的变化会造成一个或多个其他模块也同时发生变化的依赖关系）会对软件系统的质量造成很大的危害。特别是当需求发生变化时，代码的维护成本将非常高。所以，我们必须想尽办法来控制和消解不必要的耦合，特别是那种会导致其它模块发生不可控变化的依赖关系。依赖倒置、控制反转、依赖注入等原则就是人们在和依赖关系进行艰苦卓绝的斗争过程中不断产生和发展起来的。<br></p>
</div>
<a name=interface></a>
<p class=separator1>接口和实现分离&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　把接口和实现分开是人们试图控制依赖关系的第一个尝试，图 1是Robert C. Martin在《依赖倒置》[Martin 1996]一文中所举的第一个例子。其中，ReadKeyboard()和WritePrinter()为函数库中的两个函数，应用程序循环调用这两个函数，以便把用户键入的字符拷贝到打印机输出。<br></p>
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc1.gif"></div>
　　为了使应用程序不依赖于函数库的具体实现，C语言把函数的定义写在了一个分离的头文件（函数库.h）中。这种做法的好处是：虽然应用程序要调用函数库、依赖于函数库，但是，当我们要改变函数库的实现时，只要重写函数的实现代码，应用程序无需发生变化。例如，改变函数库.c文件，把WritePrinter()函数重新实现成向磁盘中输出，这时只要将应用程序和函数库重新链接，程序的功能就会发生相应的变化。<br>　　上面的函数库也可以采用C++语言来实现。我们通常把这种用面向对象技术实现的，为应用程序提供多个支持类的模块称为 &#8220;类库&#8221;，如图 2所示。这种通过分离接口和实现来消解应用程序和类库之间依赖关系的做法具有以下特点：<br>　　1. 应用程序调用类库，依赖于类库。<br>　　2. 接口和实现的分离从一定的程度上消解了这个依赖关系，具体实现可以在编译期间发生变化。但是，这种消解方法的作用非常有限。比如说，一个系统中无法容纳多个实现，不同的实现不能动态发生变化，用WritePrinter函数名来实现向磁盘中输出的功能也显得非常古怪，等等。<br>　　3. 类库可以单独重用。但是应用程序不能脱离类库而重用，除非提供一个实现了相同接口的类库。
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc2.gif"></div>
<p>&#160;</p>
</div>
<a name=dip></a>
<p class=separator1>依赖倒置（Dependency Inversion Principle）&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　可以看出，上面讨论的简单分离接口的方法对于依赖关系的消解作用非常有限。Java语言提供了纯粹的接口类，这种接口类不包括任何实现代码，可以更好地隔离两个模块。C++语言中虽然没有定义这种纯粹的接口类，但所有成员函数都是纯虚函数的抽象类也不包含任何实现代码，可以起到类似于Java接口类的作用。为了和上一节中提到的简单接口相区别，本文后面将把基于Java 接口类或C++抽象类定义的接口称为抽象接口。依赖倒置原则就是建立在抽象接口的基础上的。Robert Martin这样描述依赖倒置原则[Martin 1996]：<br>　　A. 上层模块不应该依赖于下层模块，它们共同依赖于一个抽象。<br>　　B. 抽象不能依赖于具象，具象依赖于抽象。<br>　　其含义是：为了消解两个模块间的依赖关系，应该在两个模块之间定义一个抽象接口，上层模块调用抽象接口定义的函数，下层模块实现该接口。如图 3所示，对于上一节的例子，我们可以定义两个抽象类Reader和Writer作为抽象接口，其中的Read()和Write()函数都是纯虚函数，而具体的KeyboardReader和PrinterWriter类实现了这些接口。当应用程序调用Read()和Write()函数时，由于多态性机制的作用，实际调用的是具体的KeyboardReader和PrinterWriter类中的实现。因此，抽象接口隔离了应用程序和类库中的具体类，使它们之间没有直接的耦合关系，可以独立地扩展或重用。例如，我们可以用类似的方法实现FileReader或DiskWriter类，应用程序既可以根据需要选择从键盘或文件输入，也可以选择向打印机或磁盘输出，甚至同时完成多种不同的输入、输出任务。由此可以总结出，这种通过抽象接口消解应用程序和类库之间依赖关系的做法具有以下特点：<br>　　1. 应用程序调用类库的抽象接口，依赖于类库的抽象接口；具体的实现类派生自类库的抽象接口，也依赖于类库的抽象接口。<br>　　2. 应用程序和具体的类库实现完全独立，相互之间没有直接的依赖关系，只要保持接口类的稳定，应用程序和类库的具体实现都可以独立地发生变化。<br>　　3. 类库完全可以独立重用，应用程序可以和任何一个实现了相同抽象接口的类库协同工作。 </p>
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc3.gif"></div>
　　一般情况下，由于类库的设计者并不知道应用程序会如何使用类库，抽象接口大多由类库设计者根据自己设想的典型使用模式总结出来，并保留一定的灵活度，以提供给应用程序的开发者使用。<br>　　但还有另外一种情况。图 4是Martin Fowler在《Reducing Coupling》一文中使用的一个例子[Fowler 2001]。其中，Domain包要使用数据库包，即Domain包依赖于数据库包。为了隔离Domain包和数据库包，可以引入一个Mapper包。如果在特定的情况下，我们希望Domain包能够被多次重用，而Mapper包可以随时变化，那么，我们就必须防止Domain包过分地依赖于Mapper包。这时，可以由 Domain包的设计者总结出自己需要的抽象接口（如Store），而由Mapper包的设计者来实现该抽象接口。这样一来，无论是在接口层面，还是在实现层面，依赖关系都完全颠倒过来了。
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc4.gif"></div>
<p>&#160;</p>
</div>
<a name=ioc></a>
<p class=separator1>控制反转（Inversion of Control）&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　前面描述的是应用程序和类库之间的依赖关系。如果我们开发的不是类库，而是框架系统，依赖关系就会更强烈一点。那么，该如何消解框架和应用程序之间的依赖关系呢？<br>　　《道法自然》第5章描述了框架和类库之间的区别：<br>　　&#8220;框架和类库最重要的区别是：框架是一个&#8216;半成品&#8217;的应用程序，而类库只包含一系列可被应用程序调用的类。<br>　　&#8220;类库给用户提供了一系列可复用的类，这些类的设计都符合面向对象原则和模式。用户使用时，可以创建这些类的实例，或从这些类中继承出新的派生类，然后调用类中相应的功能。在这一过程中，类库总是被动地响应用户的调用请求。<br>　　&#8220;框架则会为某一特定目的实现一个基本的、可执行的架构。框架中已经包含了应用程序从启动到运行的主要流程，流程中那些无法预先确定的步骤留给用户来实现。程序运行时，框架系统自动调用用户实现的功能组件。这时，框架系统的行为是主动的。<br>　　&#8220;我们可以说，类库是死的，而框架是活的。应用程序通过调用类库来完成特定的功能，而框架则通过调用应用程序来实现整个操作流程。框架是控制倒置原则的完美体现。&#8221;<br>　　框架系统的一个最好的例子就是图形用户界面（GUI）系统。一个简单的，使用面向过程的设计方法开发的GUI系统如图 5所示。 </p>
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc5.gif"></div>
　　从图 5中可以看出，应用程序调用GUI框架中的CreateWindow()函数来创建窗口，在这里，我们可以说应用程序依赖于GUI框架。但GUI框架并不了解该窗口接收到窗口消息后应该如何处理，这一点只有应用程序最为清楚。因此，当GUI框架需要发送窗口消息时，又必须调用应用程序定义的某个特定的窗口函数（如上图中的MyWindowProc）。这时，GUI框架又必须依赖于应用程序。这是一个典型的双向依赖关系。这种双向依赖关系有一个非常严重的缺陷：由于GUI框架调用了应用程序中的某个特定函数（MyWindowProc）， GUI框架根本无法独立存在；换一个新的应用程序，GUI框架多半就要做相应的修改。因此，如何消解框架系统对应用程序的依赖关系是实现框架系统的关键。<br>　　并非只有面向对象的方法才能解决这一问题。WIN32 API早就为我们提供了在面向过程的设计思路下解决类似问题的范例。类WIN32 的架构模型如图 6所示。
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc6.gif"></div>
　　在图 6中，应用程序调用CreateWindow()函数时，要传递一个消息处理函数的指针给GUI框架（对WIN32而言，我们在注册窗口类时传递这一指针），GUI框架把该指针记录在窗口信息结构中。需要发送窗口消息时，GUI框架就通过该指针调用窗口函数。和图 5 相比，GUI框架仍然需要调用应用程序，但这一调用从一个硬编码的函数调用变成了一个由应用程序事先注册被调用对象的动态调用。图 6用一条虚线表示这种动态调用。可以看出，这种动态的调用关系有一个非常大的好处：当应用程序发生变化时，它可以自行改变框架系统的调用目标，GUI框架无需随之发生变化。现在，我们可以说，虽然还存在着从GUI框架到应用程序的调用关系，但GUI框架已经完全不再依赖于应用程序了。这种动态调用机制通常也被称为&#8220;回调函数&#8221;。<br>　　在面向对象领域，&#8220;回调函数&#8221;的替代物就是&#8220;模板方法模式&#8221;，也就是&#8220;好莱坞原则（不要调用我们，让我们调用你）&#8221;。GUI框架的一个面向对象的实现如图 7所示。
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc7.gif"></div>
　　图 7中，&#8220;GUI框架抽象接口&#8221;是GUI框架系统提供给应用程序使用的接口。抽象出该接口的动机是根据&#8220;依赖倒置&#8221;的原则，消解从应用程序到GUI框架之间的直接依赖关系，以使得GUI框架实现的变化对应用程序的影响最小化。Window接口类则是&#8220;模板方法模式&#8221;的核心。应用程序调用CreateWindow()函数时，GUI框架会把该窗口的引用保存在窗口链表中。需要发送窗口消息时，GUI框架就调用窗口对象的SendMessage()函数，该函数是实现在Window类中的非虚成员函数。SendMessage()函数又调用WindowProc()虚函数，这里实际执行的是应用程序MyWindow类中实现的WindowProc()函数。在图 7中，我们已经看不到从GUI框架到应用程序之间的直接依赖关系了。因此，模板方法模式完全实现了回调函数的动态调用机制，消解了从框架到应用程序之间的依赖关系。<br>　　从上面的分析可以看出，模板方法模式是框架系统的基础，任何框架系统都离不开模板方法模式。Martin Fowler也说 [Folwer 2004]，&#8220;几位轻量级容器的作者曾骄傲地对我说：这些容器非常有用，因为它们实现了&#8216;控制反转&#8217;。这样的说辞让我深感迷惑：控制反转是框架所共有的特征，如果仅仅因为使用了控制反转就认为这些轻量级容器与众不同，就好像在说&#8216;我的轿车是与众不同的，因为它有四个轮子&#8217;。问题的关键在于：它们反转了哪方面的控制？我第一次接触到的控制反转针对的是用户界面的主控权。早期的用户界面是完全由应用程序来控制的，你预先设计一系列命令，例如&#8216;输入姓名&#8217;、&#8216;输入地址&#8217;等，应用程序逐条输出提示信息，并取回用户的响应。而在图形用户界面环境下，UI 框架将负责执行一个主循环，你的应用程序只需为屏幕的各个区域提供事件处理函数即可。在这里，程序的主控权发生了反转：从应用程序移到了框架。&#8221;<br>　　确实：对比图 3和图 7可以看出，使用普通类库时，程序的主循环位于应用程序中，而使用框架系统的应用程序不再包括一个主循环，只是实现某些框架定义的接口，框架系统负责实现系统运行的主循环，并在必要的时候通过模板方法模式调用应用程序。<br>　　也就是说，虽然&#8220;依赖倒置&#8221;和&#8220;控制反转&#8221;在设计层面上都是消解模块耦合的有效方法，也都是试图令具体的、易变的模块依赖于抽象的、稳定的模块的基本原则，但二者在使用语境和关注点上存在差异：&#8220;依赖倒置&#8221;强调的是对于传统的、源于面向过程设计思想的层次概念的&#8220;倒置&#8221;，而&#8220;控制反转&#8221;强调的是对程序流程控制权的反转；&#8220;依赖倒置&#8221;的使用范围更为宽泛，既可用于对程序流程的描述（如流程的主从和层次关系），也可用于描述其他拥有概念层次的设计模型（如服务组件与客户组件、核心模块与外围应用等），而&#8220;控制反转&#8221;则仅适用于描述流程控制权的场合（如算法流程或业务流程的控制权）。<br>　　从某种意义上说，我们也可以把&#8220;控制反转&#8221;看作是&#8220;依赖倒置&#8221;的一个特例。例如，用模板方法模式实现的&#8220;控制反转&#8221;机制其实就是在框架系统和应用程序之间抽象出了一个描述所有算法步骤原型的接口类，框架系统依赖于该接口类定义并实现程序流程，应用程序依赖于该接口类提供具体算法步骤的实现，应用程序对框架系统的依赖被&#8220;倒置&#8221;为二者对抽象接口的依赖。<br>　　总地说来，应用程序和框架系统之间的依赖关系有以下特点：<br>　　1. 应用程序和框架系统之间实际上是双向调用，双向依赖的关系。<br>　　2. 依赖倒置原则可以减弱应用程序到框架之间的依赖关系。<br>　　3. &#8220;控制反转&#8221;及具体的模板方法模式可以消解框架到应用程序之间的依赖关系，这也是所有框架系统的基础。<br>　　4. 框架系统可以独立重用。
<p>&#160;</p>
</div>
<a name=inject></a>
<p class=separator1>依赖注入（Dependency Injection）&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　在前面的例子里，我们通过&#8220;依赖倒置&#8221;原则，最大限度地减弱了应用程序Copy类和类库提供的服务Read，Write之间的依赖关系。但是，如果需要把Copy()函数也实现在类库中，又会发生什么情况呢？假设在类库中实现一个&#8220;服务类&#8221;，&#8220;服务类&#8221;提供Copy()方法供应用程序使用。应用程序使用时，首先创建&#8220;服务类&#8221;的实例，调用其中的Copy()函数。&#8220;服务类&#8221;的实例初始化时会创建KeyboardReader 和PrinterWriter类的实例对象。如图 8所示。 </p>
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc8.gif"></div>
　　从图 8中可以看出，虽然Reader和Writer接口隔离了&#8220;服务类&#8221;和具体的Reader和Writer类，使它们之间的耦合降到了最小。但当 &#8220;服务类&#8221;创建具体的Reader和Writer对象时，&#8220;服务类&#8221;还是和具体的Reader和Writer对象发生了依赖关系——图 8中用蓝色的虚线描述了这种依赖关系。<br>　　在这种情况下，如何实例化具体的Reader和Writer类，同时又尽量减少服务类对它们的依赖，就是一个非常关键的问题了。如果服务类位于应用程序中，这一依赖关系对我们造成的影响还不算大。但当&#8220;服务类&#8221;位于需要独立发布的类库中，它的代码就不能随着应用程序的变化而改变了。这也意味着，如果&#8220;服务类&#8221;过度依赖于具体的Reader和Writer类，用户就无法自行添加新的Reader和Writer 的实现了。<br>　　解决这一问题的方法是&#8220;依赖注入&#8221;，即切断&#8220;服务类&#8221;到具体的Reader和Writer类之间的依赖关系，而由应用程序来注入这一依赖关系。如图 9所示。
<div align=center><img src="http://www.contextfree.net/wangyw/source/images/dip_ioc9.gif"></div>
　　在图 9中，&#8220;服务类&#8221;并不负责创建具体的Reader和Writer类的实例对象，而是由应用程序来创建。应用程序创建&#8220;服务类&#8221;的实例对象时，把具体的Reader和Write对象的引用注入&#8220;服务类&#8221;内部。这样，&#8220;服务类&#8221;中的代码就只和抽象接口相关的了。具体实现代码发生变化时，&#8220;服务类&#8221;不会发生任何变化。添加新的实现时，也只需要改变应用程序的代码，就可以定义并使用新的Reader和Writer类，这种依赖注入方式通常也被称为&#8220;构造器注入&#8221;。<br>　　如果专门为Copy类抽象出一个注入接口，应用程序通过接口注入依赖关系，这种注入方式通常被称为&#8220;接口注入&#8221;。如果为Copy类提供一个设值函数，应用程序通过调用设值函数来注入依赖关系，这种依赖注入的方法被称为&#8220;设值注入&#8221;。具体的&#8220;接口注入&#8221;和&#8220;设值注入&#8221;请参考[Martin 2004]。<br>　　PicoContainer和Spring轻量级容器框架都提供了相应的机制来帮助用户实现各种不同的&#8220;依赖注入&#8221;。并且，通过不同的方式，他们也都支持在XML文件中定义依赖关系，然后由应用程序调用框架来注入依赖关系，当依赖关系需要发生变化时，只要修改相应的 XML文件即可。<br>　　因此，依赖注入的核心思想是：<br>　　1. 抽象接口隔离了使用者和实现之间的依赖关系，但创建具体实现类的实例对象仍会造成对于具体实现的依赖。<br>　　2. 采用依赖注入可以消除这种创建依赖性。使用依赖注入后，某些类完全是基于抽象接口编写而成的，这可以最大限度地适应需求的变化。
<p>&#160;</p>
</div>
<a name=conclusion></a>
<p class=separator1>结论&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>　　分离接口和实现是人们有效地控制依赖关系的最初尝试，而纯粹的抽象接口更好地隔离了相互依赖的两个模块，&#8220;依赖倒置&#8221;和 &#8220;控制反转&#8221;原则从不同的角度描述了利用抽象接口消解耦合的动机，GoF的设计模式正是这一动机的完美体现。具体类的创建过程是另一种常见的依赖关系，&#8220;依赖注入&#8221;模式可以把具体类的创建过程集中到合适的位置，这一动机和GoF的创建型模式有相似之处。<br>　　这些原则对我们的实践有很好的指导作用，但它们不是圣经，在不同的场合可能会有不同的变化，我们应该在开发过程中根据需求变化的可能性灵活运用。 </p>
</div>
<a name=reference></a>
<p class=separator1>参考文献&nbsp;</p>
<div style="PADDING-RIGHT: 30px; PADDING-LEFT: 30px">
<p>[PicoContainer 2004]　　<a href="http://www.picocontainer.org/Inversion+of+Control">http://www.picocontainer.org/Inversion+of+Control</a><br>[Martin 1996]　　The Dependency Inversion Principle, Robert C. Martin, C++ Report, May, 1996, <a href="http://www.objectmentor.com/resources/articles/dip.pdf">http://www.objectmentor.com/resources/articles/dip.pdf</a><br>[Fowler 2001]　　Martin Fowler: Reducing Coupling. IEEE Software 18(4): 102-104 (2001) <a href="http://www.martinfowler.com/ieeeSoftware/coupling.pdf">http://www.martinfowler.com/ieeeSoftware/coupling.pdf</a><br>[Folwer 2004]　　Inversion of Control Containers and the Dependency Injection pattern <a href="http://martinfowler.com/articles/injection.html">http://martinfowler.com/articles/injection.html</a><br>[透明2004]　　透明，Inversion of Control Containers and the Dependency Injection pattern 的译文<a href="http://gigix.blogdriver.com/gigix/inc/DependencyInjection.pdf">http://gigix.blogdriver.com/gigix/inc/DependencyInjection.pdf</a><br>[王咏武, 王咏刚 2004]　　王咏武, 王咏刚. 道法自然—面向对象实践指南. 电子工业出版社, 2004 </p>
</div>
<img src ="http://www.blogjava.net/dreamstone/aggbug/85400.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-04 16:50 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/04/85400.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 中的模式 --- 简单的状态模式</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/03/85173.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sun, 03 Dec 2006 03:51:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/03/85173.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/85173.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/03/85173.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/85173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/85173.html</trackback:ping><description><![CDATA[状态模式很简单，无论是理解，还是实现，都很简单。<br>一、定义：<br>1，状态模式允许一个"对象"在其内部状态改变的时候改变其行为。<br>2，状态模式的角色：<br>抽象状态，具体状态，环境(context)角色<br>状态模式的角色比较简单，不用解释了，看名字就能了解。<br>二、状态模式的实现<br>1,简单实例<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img id=Codehighlighter1_20_167_Open_Image onclick="this.style.display='none'; Codehighlighter1_20_167_Open_Text.style.display='none'; Codehighlighter1_20_167_Closed_Image.style.display='inline'; Codehighlighter1_20_167_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_20_167_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_20_167_Closed_Text.style.display='none'; Codehighlighter1_20_167_Open_Image.style.display='inline'; Codehighlighter1_20_167_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;Context</span><span id=Codehighlighter1_20_167_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_20_167_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">&nbsp;State&nbsp;state;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img id=Codehighlighter1_74_104_Open_Image onclick="this.style.display='none'; Codehighlighter1_74_104_Open_Text.style.display='none'; Codehighlighter1_74_104_Closed_Image.style.display='inline'; Codehighlighter1_74_104_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_74_104_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_74_104_Closed_Text.style.display='none'; Codehighlighter1_74_104_Open_Image.style.display='inline'; Codehighlighter1_74_104_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sampleOperation()</span><span id=Codehighlighter1_74_104_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_74_104_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;state.sampleOperation();<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img id=Codehighlighter1_140_165_Open_Image onclick="this.style.display='none'; Codehighlighter1_140_165_Open_Text.style.display='none'; Codehighlighter1_140_165_Closed_Image.style.display='inline'; Codehighlighter1_140_165_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_140_165_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_140_165_Closed_Text.style.display='none'; Codehighlighter1_140_165_Open_Image.style.display='inline'; Codehighlighter1_140_165_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;setState(State&nbsp;state)</span><span id=Codehighlighter1_140_165_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_140_165_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.state&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;state;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img id=Codehighlighter1_191_218_Open_Image onclick="this.style.display='none'; Codehighlighter1_191_218_Open_Text.style.display='none'; Codehighlighter1_191_218_Closed_Image.style.display='inline'; Codehighlighter1_191_218_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_191_218_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_191_218_Closed_Text.style.display='none'; Codehighlighter1_191_218_Open_Image.style.display='inline'; Codehighlighter1_191_218_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">interface</span><span style="COLOR: #000000">&nbsp;State</span><span id=Codehighlighter1_191_218_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_191_218_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sampleOperation();<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"><br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img id=Codehighlighter1_264_298_Open_Image onclick="this.style.display='none'; Codehighlighter1_264_298_Open_Text.style.display='none'; Codehighlighter1_264_298_Closed_Image.style.display='inline'; Codehighlighter1_264_298_Closed_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_264_298_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_264_298_Closed_Text.style.display='none'; Codehighlighter1_264_298_Open_Image.style.display='inline'; Codehighlighter1_264_298_Open_Text.style.display='inline';" src="http://www.blogjava.net/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">&nbsp;ConcreteState&nbsp;</span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000">&nbsp;State&nbsp;</span><span id=Codehighlighter1_264_298_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.blogjava.net/Images/dot.gif"></span><span id=Codehighlighter1_264_298_Open_Text><span style="COLOR: #000000">{<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000">&nbsp;sampleOperation();<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.blogjava.net/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
2、状态模式的经典实现<br>Tcp就是状态模式的一个经典实现：TcpConnect 他有三个状态，TcpEstablished&nbsp; TcpListen&nbsp; TcpClosed<br>TcpConnect的功能会跟着状态的改变而改变。或是Established,或是Listen,或是Closed<br>三、状态模式的与策略模式，看到上边的部分，很容易让人想到策略模式，这两个模式有什么区别呢？如何使用<br>策略模式：<br>1，当一个环境角色选择了一个具体的策略，那么在整个环境类的生命周期都不会改变<br>2，策略模式的环境自己选择一个具体的策略<br>3，策略模式并不明确告诉客户端它所选择的具体策略是什么，对客户是黑箱。<br>状态模式：<br>1，在整个环境类的生命周期中会有明显的状态改变。<br>2，状态模式是被外在原因放入一个策略<br>3,状态模式明显的告诉客户端当前的状态，对客户是白箱。 
<img src ="http://www.blogjava.net/dreamstone/aggbug/85173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-03 11:51 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/03/85173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的模式 --- 双重接口的实现,备忘录模式</title><link>http://www.blogjava.net/dreamstone/archive/2006/12/03/85159.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sun, 03 Dec 2006 02:40:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/12/03/85159.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/85159.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/12/03/85159.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/85159.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/85159.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、定义：备忘录(memento)模式又叫快照(snapshot)模式或者token模式，主要功能：备忘录模式是用一个对象来存储另外一个对象的内部状态的快照，实现备忘录模式的关键点是在不破坏封装的情况下，将一个对象的状态捕捉住，并外部化，存储起来，从而可以在合适的时候，把这个对象还原。说明：备忘录模式适模式中比较好理解的一个，这里就不举例子，但是备忘录模式是模式中实现比较难，或者说实现比较巧的，这...&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2006/12/03/85159.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/85159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-12-03 10:40 <a href="http://www.blogjava.net/dreamstone/archive/2006/12/03/85159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的模式 --- 命令模式的(实现,功能,使用场合)及如何配合其它模式使用命令模式</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/27/83690.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sun, 26 Nov 2006 18:31:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/27/83690.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/83690.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/27/83690.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/83690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/83690.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一,命令模式的实现:命令模式里边一般都有以下几个角色：客户端，请求者，命令接口，命令实现，接受者,下边是简单命令模式的实现代码实现：&nbsp;1public&nbsp;class&nbsp;Client{&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args){&nbsp...&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2006/11/27/83690.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/83690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-27 02:31 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/27/83690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring的Aop的实现方式</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/14/81007.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Mon, 13 Nov 2006 16:51:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/14/81007.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/81007.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/14/81007.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/81007.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/81007.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 最近看了一下Spring的Aop和Java的动态代理，下边利用个小例子，简单的表述一下。Spring中的Aop实现一，什么是Aop呢：AOP是Aspect Oriented Programming的缩写，意思是面向方面编程。AOP实际是GoF设计模式的延续，设计模式孜孜不倦追求的是调用者和被调用者之间的解耦，AOP可以说也是这种目标的一种实现。二,Spring中的Aopspring中的aop运用了...&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2006/11/14/81007.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/81007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-14 00:51 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/14/81007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的模式 --工厂模式</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/07/79608.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Tue, 07 Nov 2006 07:02:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/07/79608.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/79608.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/07/79608.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/79608.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/79608.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 工厂模式主要负责将大量有共通接口的类实例化，工场模式有以下几种形态简单工厂(Simple Factory)&nbsp;&nbsp; 又称 静态工厂方法(Static Factory Method)工厂方法(Factory Method)&nbsp;&nbsp; 又称 多态性工厂(Polymorphic Factory)抽象工厂(Abstract Factory) 又称 工具箱(Kit or Too...&nbsp;&nbsp;<a href='http://www.blogjava.net/dreamstone/archive/2006/11/07/79608.html'>阅读全文</a><img src ="http://www.blogjava.net/dreamstone/aggbug/79608.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-07 15:02 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/07/79608.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的模式  --单态 （部分翻译 double-checked locking break）</title><link>http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html</link><dc:creator>dreamstone</dc:creator><author>dreamstone</author><pubDate>Sat, 04 Nov 2006 01:26:00 GMT</pubDate><guid>http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html</guid><wfw:comment>http://www.blogjava.net/dreamstone/comments/79026.html</wfw:comment><comments>http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.blogjava.net/dreamstone/comments/commentRss/79026.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/dreamstone/services/trackbacks/79026.html</trackback:ping><description><![CDATA[<p>单态定义:<br>Singleton模式主要作用是保证在Java应用程序中，一个类Class只有一个实例存在。</p>
<p>Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存，因为它限制了<br>实例的个数，有利于Java垃圾回收（garbage collection）。</p>
<p>使用Singleton注意事项：<br>有时在某些情况下，使用Singleton并不能达到Singleton的目的，如有多个Singleton对象同时被不同的类<br>装入器装载；在EJB这样的分布式系统中使用也要注意这种情况，因为EJB是跨服务器，跨JVM的</p>
<p>单态模式的演化：<br>单态模式是个简单的模式，但是这个简单的模式也有很多复杂的东西。<br></p>
<p>（注意：在这里补充一下，现在单态模式其实有一个写法是不错的见这里：<a href="http://www.blogjava.net/dreamstone/archive/2007/02/27/101000.html">http://www.blogjava.net/dreamstone/archive/2007/02/27/101000.html</a>，但还是建议看完这篇文章，因为解释的事情是不一样的，这里说的是为什么double-checked不能使用.）<br>一，首先最简单的单态模式，单态模式1<br>import java.util.*;<br>class Singleton<br>{<br>&nbsp; private static Singleton instance;<br>&nbsp; private Vector v;<br>&nbsp; private boolean inUse;</p>
<p>&nbsp; private Singleton()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; v = new Vector();<br>&nbsp;&nbsp;&nbsp; v.addElement(new Object());<br>&nbsp;&nbsp;&nbsp; inUse = true;<br>&nbsp; }</p>
<p>&nbsp; public static Singleton getInstance()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp; //2<br>&nbsp;&nbsp;&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //3<br>&nbsp; }<br>}<br>这个单态模式是不安全的，为什么说呢 ？因为没考虑多线程，如下情况<br>Thread 1 调用getInstance() 方法，并且判断instance是null，然後进入if模块，<br>在实例化instance之前，<br>Thread 2抢占了Thread 1的cpu<br>Thread 2 调用getInstance() 方法，并且判断instance是null，然後进入if模块，<br>Thread 2 实例化instance 完成，返回<br>Thread 1 再次实例化instance<br>这个单态已经不在是单态</p>
<p>二，为了解决刚才的问题：单态模式2<br>public static synchronized Singleton getInstance()<br>{<br>&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //1<br>&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp; //2<br>&nbsp; return instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //3<br>}<br>采用同步来解决，这种方式解决了问题，但是仔细分析<br>正常的情况下只有第一次时候，进入对象的实例化，须要同步，<br>其它时候都是直接返回已经实例化好的instance不须要同步，<br>大家都知到在一个多线程的程序中，如果同步的消耗是很大的，很容易造成瓶颈</p>
<p>三，为了解决上边的问题：单态模式3，加入同步<br>public static Singleton getInstance()<br>{<br>&nbsp; if (instance == null)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; synchronized(Singleton.class) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; return instance;<br>}<br>同步改成块同步，而不使用函数同步，但是仔细分析，<br>又回到了模式一的状态，再多线程的时候根本没有解决问题</p>
<p>四，为了对应上边的问题：单态模式4，也就是很多人采用的Double-checked locking<br>public static Singleton getInstance()<br>{<br>&nbsp; if (instance == null)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; synchronized(Singleton.class) {&nbsp; //1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (instance == null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp; //3<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; return instance;<br>}<br>这样，模式一中提到的问题解决了。不会出现多次实例化的现象<br>当第一次进入的时候，保正实例化时候的单态,在实例化后，多线程访问的时候直接返回，不须要进入同步模块，<br>既实现了单态，又没有损失性能。表面上看我们的问题解决了，但是再仔细分析：<br>我们来假象这中情况：<br>Thread 1 :进入到//3位置，执行new Singleton()，但是在构造函数刚刚开始的时候被Thread2抢占cpu<br>Thread 2 :进入getInstance()，判断instance不等于null,返回instance，<br>（instance已经被new，已经分配了内存空间,但是没有初始化数据)<br>Thread 2 :利用返回的instance做某些操做，失败或者异常<br>Thread 1 :取得cpu初始化完成<br>过程中可能有多个线程取到了没有完成的实例，并用这个实例作出某些操做。<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br>出现以上的问题是因为<br>mem = allocate();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //分配内存<br>instance = mem;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //标记instance非空<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //未执行构造函数,thread 2从这里进入<br>ctorSingleton(instance);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //执行构造函数<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //返回instance<br>－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>五，证明上边的假想是可能发生的，字节码是用来分析问题的最好的工具，可以利用它来分析<br>下边一段程序：（为了分析方便，所以渐少了内容）<br>字节码的使用方法见这里，<a href="http://www.blogjava.net/dreamstone/archive/2006/11/04/79058.html">利用字节码分析问题</a><br>class Singleton<br>{<br>&nbsp; private static Singleton instance;<br>&nbsp; private boolean inUse;<br>&nbsp; private int val;&nbsp; </p>
<p>&nbsp; private Singleton()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; inUse = true;<br>&nbsp;&nbsp;&nbsp; val = 5;<br>&nbsp; }<br>&nbsp; public static Singleton getInstance()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; if (instance == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();<br>&nbsp;&nbsp;&nbsp; return instance;<br>&nbsp; }<br>}<br>得到的字节码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>;asm code generated for getInstance<br>054D20B0&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,[049388C8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;load instance ref<br>054D20B5&nbsp;&nbsp; test&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;test for null<br>054D20B7&nbsp;&nbsp; jne&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 054D20D7<br>054D20B9&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eax,14C0988h<br>054D20BE&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 503EF8F0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;allocate memory<br>054D20C3&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [049388C8],eax&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;store pointer in <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;instance ref. instance&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;non-null and ctor<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ;has not run<br>054D20C8&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ecx,dword ptr [eax] <br>054D20CA&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ecx],1&nbsp;&nbsp; ;inline ctor - inUse=true;<br>054D20D0&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dword ptr [ecx+4],5 ;inline ctor - val=5;<br>054D20D7&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ebx,dword ptr ds:[49388C8h]<br>054D20DD&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 054D20B0</p>
<p>上边的字节码证明，猜想是有可能实现的</p>
<p>六：好了，上边证明Double-checked locking可能出现取出错误数据的情况，那么我们还是可以解决的<br>public static Singleton getInstance()<br>{<br>&nbsp; if (instance == null)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; synchronized(Singleton.class) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Singleton inst = instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inst == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(Singleton.class) {&nbsp; //3<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inst = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //4<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = inst;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //5<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; return instance;<br>}<br>利用Double-checked locking 两次同步，中间变量,解决上边的问题。<br>（下边这段话我只能简单的理解，翻译过来不好，所以保留原文，list 7是上边的代码，list 8是下边的<br>The code in Listing 7 doesn't work because of the current definition of the memory model.<br>&nbsp;The Java Language Specification (JLS) demands that code within a synchronized block <br>&nbsp;not be moved out of a synchronized block. However, it does not say that <br>&nbsp;code not in a synchronized block cannot be moved into a synchronized block.<br>A JIT compiler would see an optimization opportunity here. <br>This optimization would remove the code at <br>//4 and the code at //5, combine it and generate the code shown in Listing 8:）<br>-------------------------------------------------&nbsp;<br>list 8<br>public static Singleton getInstance()<br>{<br>&nbsp; if (instance == null)<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; synchronized(Singleton.class) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Singleton inst = instance;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (inst == null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(Singleton.class) {&nbsp; //3<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //inst = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //4<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; instance = new Singleton();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //instance = inst;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //5<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp; }<br>&nbsp; return instance;<br>}<br>If this optimization takes place, you have the same out-of-order write problem we discussed earlier.<br>如果这个优化发生，将再次发生上边提到的问题，取得没有实例化完成的数据。<br>-------------------------------------------------</p>
<p>以下部分为了避免我翻译错误误导打家，保留原文</p>
<p>Another idea is to use the keyword volatile for the variables inst and instance. <br>According to the JLS (see Resources), variables declared volatile are supposed to <br>be sequentially consistent, and therefore, not reordered. <br>But two problems occur with trying to use volatile to fix the problem with <br>double-checked locking:</p>
<p>The problem here is not with sequential consistency. <br>Code is being moved, not reordered.</p>
<p>Many JVMs do not implement volatile correctly regarding sequential consistency anyway. <br>The second point is worth expanding upon. Consider the code in Listing 9:</p>
<p>Listing 9. Sequential consistency with volatile</p>
<p>class test<br>{<br>&nbsp; private volatile boolean stop = false;<br>&nbsp; private volatile int num = 0;</p>
<p>&nbsp; public void foo()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; num = 100;&nbsp;&nbsp;&nbsp; //This can happen second<br>&nbsp;&nbsp;&nbsp; stop = true;&nbsp; //This can happen first<br>&nbsp;&nbsp;&nbsp; //...<br>&nbsp; }</p>
<p>&nbsp; public void bar()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; if (stop)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; num += num;&nbsp; //num can == 0!<br>&nbsp; }<br>&nbsp; //...<br>}<br>&nbsp;<br>According to the JLS, because stop and num are declared volatile, <br>they should be sequentially consistent. This means that if stop is ever true, <br>num must have been set to 100. <br>However, because many JVMs do not implement the sequential consistency feature of volatile,<br>you cannot count on this behavior. <br>Therefore, if thread 1 called foo and thread 2 called bar concurrently, <br>thread 1 might set stop to true before num is set to 100. <br>This could lead thread 2 to see stop as true, but num still set to 0. <br>There are additional problems with volatile and the atomicity of 64-bit variables,<br>but this is beyond the scope of this article. <br>See Resources for more information on this topic. </p>
<p>简单的理解上边这段话，使用volatile有可能能解决问题，volatile被定义用来保正一致性，但是很多虚拟机<br>并没有很好的实现volatile，所以使用它也会存在问题。</p>
<p>最终的解决方案：<br>&nbsp;（1），单态模式2，使用同步方法<br>&nbsp;（2），放弃同步，使用一个静态变量，如下<br>class Singleton<br>{<br>&nbsp; private Vector v;<br>&nbsp; private boolean inUse;<br>&nbsp; private static Singleton instance = new Singleton();</p>
<p>&nbsp; private Singleton()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; v = new Vector();<br>&nbsp;&nbsp;&nbsp; inUse = true;<br>&nbsp;&nbsp;&nbsp; //...<br>&nbsp; }</p>
<p>&nbsp; public static Singleton getInstance()<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; return instance;<br>&nbsp; }<br>}<br>但使用静态变量也会存在问题，问题见 <a href="http://www-128.ibm.com/developerworks/cn/java/j-lo-clobj-init/index.html">这篇文章</a></p>
<p>而且如在文章开头提到的，使用EJB跨服务器，跨JVM的情况下，单态更是问题</p>
<p>好了是不是感觉单态模式根本没法使用了，其实上边都是特殊情况，这中特殊情况的出现是有条件的，只要<br>根据你的具体应用，回避一些，就能解决问题，所以单态还是可以使用的。但是在使用前慎重，自己考虑好自己<br>的情况适合哪种情况。</p>
<p>参考<br><a href="http://www.jdon.com/designpatterns/singleton.htm">http://www.jdon.com/designpatterns/singleton.htm</a><br></p>
<p><a href="http://www-106.ibm.com/developerworks/java/library/j-dcl.html?dwzone=java" target=_blank>Double-checked locking and the Singleton pattern</a> </p>
<p><a href="http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton-p3.html#resources" target=_blank>When is a singleton not a singleton?</a> </p>
<img src ="http://www.blogjava.net/dreamstone/aggbug/79026.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/dreamstone/" target="_blank">dreamstone</a> 2006-11-04 09:26 <a href="http://www.blogjava.net/dreamstone/archive/2006/11/04/79026.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>