﻿<?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-我的隐式生活（My Implicit Life）</title><link>http://www.blogjava.net/marco/</link><description>&lt;b&gt;继续搞“对象”，玩OO.&lt;/b&gt;
</description><language>zh-cn</language><lastBuildDate>Tue, 28 Apr 2026 19:00:08 GMT</lastBuildDate><pubDate>Tue, 28 Apr 2026 19:00:08 GMT</pubDate><ttl>60</ttl><item><title>一个电子书下载工具－－CoolBook V1</title><link>http://www.blogjava.net/marco/archive/2006/10/15/75259.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Sun, 15 Oct 2006 05:21:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/10/15/75259.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/75259.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/10/15/75259.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/75259.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/75259.html</trackback:ping><description><![CDATA[
		<p>近期写了个电子书的C/S模式的下载工具，一个server端，一个client端。<br /><br />目的就是想在公司能很方便的访问家里那些收集很久电子书，方便查阅。<br /><br />用了1，2个星期，虽然写的很烂，但是没有用任何第三方的产品（server or db）。<br /><br />现在里面的书籍已经接近200本了。<br /><br />注：server就用了家里的adsl，所以速度慢，关闭不定时。毕竟玩玩嘛。<br /><br />有兴趣的朋友先装个jdk1.5。再运行下面压缩包里的exe文件执行即可。<br /><br /><a href="/Files/marco/CoolBook.rar"><strong><font size="5">点此下载</font></strong></a><br /><br /><font color="#ff0000">User ID:               <strong>blogjava<br /></strong>Password:             <strong>blogjava</strong></font><strong> </strong><br /><br /></p>
<img src ="http://www.blogjava.net/marco/aggbug/75259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-10-15 13:21 <a href="http://www.blogjava.net/marco/archive/2006/10/15/75259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA Container Class</title><link>http://www.blogjava.net/marco/archive/2006/09/20/70845.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Wed, 20 Sep 2006 08:53:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/09/20/70845.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/70845.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/09/20/70845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/70845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/70845.html</trackback:ping><description><![CDATA[
		<p>Java Collection Framwork中的类的确是最重要的基础api，实现任何算法，基本上都很难离开它。</p>
		<p>因此理解这堆“集合（Collection）类”很有必要。声明一下，以前一直都是叫它们集合类，但是好像Think In Java的作者鄙视了这个说法，严格的说应该叫Container类，而后看了它整整一章书以后，觉得还是人家说的有道理。</p>
		<p>它说这个container类库，包含了两大类，Collection和Map，而Collection又可以分为List和Set。当然这些抽象概念都被定义成了接口。</p>
		<p>话说，这样的分类的确是严格按照类之间的继承关系来说得，但是俺总觉得很别扭，真动手的时候，还是很难选择。当然，Anytime and Anywhere使用ArrayList绝对都能解决问题，但这样做毕竟太农民了一点。</p>
		<p>所以，我自己有了一些想法。先回归到最基本最基本的数据结构的层面，管你是Collection还是Container，反正描述的都是一堆东西吧。数据结构第一章讲了一个结构：在物理上连续分配空间的顺序结构，叫顺序表（希望记性是好的），而离散分配空间的，应该叫做链表，最常用的就是单链表。这两个东西，其实就是很多复杂数据结构的基础，还记得吗，当时就是讲完这些东西，才开始讲栈、队列、二叉树、有向无向图的。所以，这个顺序结构是很基础的。而在JAVA中，顺序表对应的就是List接口，而一般顺序表就是ArrayList（有效进行随机index查找）；而单链表就是LinkedList（有效进行插入和删除），两个的优劣当年都讲烂了，这里就不说了。</p>
		<p>有了这两个结构以后，JAVA就不提供Stack和Queue单独的类了，因为，用户可以用上面两个类轻易的去实现。</p>
		<p>那Set和Map有怎么跟List连上关系呢？</p>
		<p>我认为可以把它们看成是无序和单一的List（Map只是两个有映射关系的List罢了）。</p>
		<p>Set和Map无序和单一的特性，决定了它们天大的需求就是根据关键字（元素对象）检索。so，为了效率，必须hash。</p>
		<p>有了HashSet和HashMap。</p>
		<p>同时，如果非要保持住元素的顺序，有了LinkedHashSet、LinkedHashMap。</p>
		<p>
				<br />结论：</p>
		<p>假如你的需求是<br />1：往Container中放的对象是无序且单一的；<br />2：经常要检索。<br />用HashSet或HashMap吧。</p>
		<p>ps：这两个条件其实是一回事，因为如果是不单一的话，你去检索它干嘛。</p>
		<p>如果进而需要保持元素的顺序，不要让他顺便iteration，那就选择LinkedHashSet和LinkedHashMap。</p>
		<p>假如你的需求不满足以上1&amp;2，那你放心，List肯定能帮你解决，你只要稍微想一下是ArrayList好还是LinkedList好。</p>
		<p>题外话：</p>
		<p>关于Hash，务必记得要让自己的元素对象override hashCode()和 equles() 方法，要不你直接可以洗了睡。</p>
		<p>关于所有这些Container，务必记得有个辅助类叫Interator，遍历尽量要用它。<br /><br />关于一些老的Stack、Vector、HashTable，听说以后不要用了哦。收到啦！！</p>
<img src ="http://www.blogjava.net/marco/aggbug/70845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-09-20 16:53 <a href="http://www.blogjava.net/marco/archive/2006/09/20/70845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 字符串操作小节（Regular Expression）</title><link>http://www.blogjava.net/marco/archive/2006/08/31/66870.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Thu, 31 Aug 2006 07:13:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/08/31/66870.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/66870.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/08/31/66870.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/66870.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/66870.html</trackback:ping><description><![CDATA[
		<p>任何信息，基本都是以文字的形式传播和记录下来的。</p>
		<p>在计算机中，文字就是字符的集合，也就是字符串，C就是因为对字符串设计的不好，才那么容易溢出。而别的一些高级语言，对于这个进行了很多的改进。</p>
		<p>编程的人由于技术方向和应用方向的不同，日常编程的内容差距很大。但是对于字符串的处理，那可是永远都避不开的工作。</p>
		<p>昨天跑步的时候，想了一下，对于字符串的操作有那么多（search，match，split，replace），感觉很烦杂，能不能抓住这些操作的一个基本集？</p>
		<p>不知道对不对，反正想出来了一个，这个基本操作就是search，这里的search的意思是：在输入串中找到目标串的开始位置（start index），和结束位置（end index）。</p>
		<p>有了这个基本集，别的操作都很好衍生出来：</p>
		<p>
				<strong>局部match：</strong>其实就是要求search操作至少返回一个start index。</p>
		<p>
				<strong>全match：</strong>其实要求search操作的至少返回一个start index，并且start index要为零，end index要为输入串的全长。</p>
		<p>
				<strong>split：</strong>其实就是search操作之后，把前一个end index和当前的start index之间的字符串截出来而已。</p>
		<p>
				<strong>replace：</strong>其实就是search操作之后，把start index和end index之间的字符串换成另外的而已。</p>
		<p>所以，归根到底，都是一个search操作的拓展罢了。这么一想，感觉清晰多了。</p>
		<p>这么一来，API对search的能力支持的好坏和效率高低是衡量字符串操作功能的标准，当然，如果有直接支持match，split，replace操作的话就更好了。</p>
		<p>java对字符串search的支持，最基本的就是下面的String的indexOf方法：</p>
		<p>
				<strong>int indexOf(String str) <br />          Returns the index within this string of the first occurrence of the specified substring.</strong>
		</p>
		<p>这里我想说的是，很多时候我们所谓要search的目标串，根本就不是固定单一的，而是变化多样的。如果只有一两种情况，最多用两次上面的方法呗。但是有些情况是近乎不可能罗列的，例如，我们讲的代表email的字符串，我们不可能遍历它吧。</p>
		<p>所以，需要一种能够通用表达字符串格式的语言。这就是Regular Expression（re）。</p>
		<p>假如上面方法indexOf的str参数能支持re做为参数的话，那对于这种多样的search也可以用上面的方法了。</p>
		<p>可惜，indexOf不支持re作为参数。<br /><br />so，以下就介绍java api中可以用re作为参数的字符串操作方法（参数中的regex就是re）。</p>
		<p>－－－－－－－－－－－－－－－－－－－－－&gt;&gt;<br />String类的：</p>
		<p>全match操作：<br /><strong><font face="Courier New"><font color="#0000ff">boolean matches(String regex)</font><br />          Tells whether or not this string matches the given regular expression.</font></strong></p>
		<p>全replace操作：<br /><strong><font face="Courier New"><font color="#0000ff">String replaceAll(String regex, String replacement)</font><br />          Replaces each substring of this string that matches the given regular expression with the given replacement.</font></strong></p>
		<p>
				<font color="#000000">首个replace操作：<br /></font>
				<strong>
						<font face="Courier New">
								<font color="#0000ff">String replaceFirst(String regex, String replacement) <br /></font>          Replaces the first substring of this string that matches the given regular expression with the given replacement.</font>
				</strong>
		</p>
		<p>全split操作：<br /><strong><font face="Courier New"><font color="#0000ff">String[] split(String regex)</font><br />          Splits this string around matches of the given regular expression.</font></strong><br /><br />有限制数的split操作：<br /><strong><font face="Courier New"><font color="#0000ff">String[] split(String regex, int limit)</font><br />          Splits this string around matches of the given regular expression.</font></strong></p>
		<p>&lt;&lt;－－－－－－－－－－－－－－－－－－－－－</p>
		<p>可惜啊，可惜，可惜java的String类里面没有可以支持re的search方法，那如果要用re来search，只好使用java中专门的re类库。</p>
		<p>java中的re类库主要就两个类，一个叫Pattern，顾名思义，代表re的类。一个叫Matcher类，反映当前match状况的类（如存放了当前search到的位置，匹配的字符串等等信息）。</p>
		<p>一般在构造中，“re的表达式”作为参数传递入Pattern类，“输入串（待过滤串）”作为参数传递入Matcher类。</p>
		<p>然后使用Matcher类的字符串search方法就可以了。Matcher真正提供search功能的API叫find。下面列出。<br />－－－－－－－－－－－－－－－－－－－－－&gt;&gt;<br />Matcher类search操作相关的方法：</p>
		<p>
				<strong>
						<font face="Courier New">
								<font color="#0000ff">boolean lookingAt()</font>
								<br />          Attempts to match the input sequence, starting at the beginning, against the pattern. </font>
				</strong>
		</p>
		<p>
				<strong>
						<font face="Courier New">
								<font color="#0000ff">boolean matches()</font>
								<br />          Attempts to match the entire input sequence against the pattern. </font>
				</strong>
		</p>
		<p>
				<strong>
						<font face="Courier New">
								<font color="#0000ff">boolean find()</font>
								<br />          Attempts to find the next subsequence of the input sequence that matches the pattern. </font>
				</strong>
		</p>
		<p>
				<strong>
						<font face="Courier New">
								<font color="#0000ff">String group() <br /></font>          Returns the input subsequence matched by the previous match.</font>
				</strong>
		</p>
		<p>&lt;&lt;－－－－－－－－－－－－－－－－－－－－－</p>
		<p>前三个都是search方法，返回成功与否。第四个是返回当前search上的字符串。<br /><br />ok，至此。使用re的search操作也有眉目了。</p>
		<p>当然，Pattern和Matcher也包含直接使用re进行的match，split，replace操作。</p>
		<p>－－－－－－－－－－－－－－－－－－－－－&gt;&gt;<br />Patter类别的字符串操作方法</p>
		<p>全match操作：<br /><strong><font face="Courier New"><font color="#0000ff">static boolean matches(String regex, CharSequence input)</font><br />          Compiles the given regular expression and attempts to match the given input against it.</font></strong></p>
		<p>全split操作：<br /><font face="Courier New"><strong><font color="#0000ff">String[] split(CharSequence input)</font><br />          Splits the given input sequence around matches of this pattern.</strong></font></p>
		<p>有限制数的split操作：<br /><font face="Courier New"><strong><font color="#0000ff">String[] split(CharSequence input, int limit)</font><br />          Splits the given input sequence around matches of this pattern.</strong></font></p>
		<p>
				<br />Matcher类别的字符串操作方法</p>
		<p>全replace操作：<br /><strong><font face="Courier New"><font color="#0000ff">String replaceAll(String replacement) <br /></font>          Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.</font></strong></p>
		<p>首个replace操作：<br /><strong><font face="Courier New"><font color="#0000ff">String replaceFirst(String replacement) <br /></font>          Replaces the first subsequence of the input sequence that matches the pattern with the given replacement string.</font></strong></p>
		<p>动态replace（replacement可以根据被替代的字符串变化而变化）<br /><font face="Courier New" color="#000000"><strong><font color="#0000ff">Matcher appendReplacement(StringBuffer sb, String replacement)</font><br />          Implements a non-terminal append-and-replace step. </strong></font></p>
		<p>
				<font face="Courier New" color="#000000">
						<strong>
								<font color="#0000ff">StringBuffer appendTail(StringBuffer sb)</font>
								<br />          Implements a terminal append-and-replace step.</strong>
				</font>
		</p>
		<p>&lt;&lt;－－－－－－－－－－－－－－－－－－－－－<br /><br />总结：<br />当必须使用re的时候，search操作就要用到Pattern，Matcher，当然动态的replace操作也要用到这两个类。而别的match，replace，split操作，可以使用pattern，Matcher，当然也可以直接使用String，推荐还是用回咱们的String吧。<br /><br />注：以上都是看jdk1.4以上的文档得出的结论，以前版本不能用不负责任。</p>
<img src ="http://www.blogjava.net/marco/aggbug/66870.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-08-31 15:13 <a href="http://www.blogjava.net/marco/archive/2006/08/31/66870.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA CODING 基本功 Ⅰ（1）――读 JAVA EFFECTIVE 笔记</title><link>http://www.blogjava.net/marco/archive/2006/07/15/58305.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Sat, 15 Jul 2006 04:35:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/07/15/58305.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/58305.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/07/15/58305.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/58305.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/58305.html</trackback:ping><description><![CDATA[
		<h2>
				<span style="COLOR: blue; FONT-FAMILY: 黑体">创建和销毁对象</span>
				<span lang="EN-US" style="COLOR: blue">
						<?xml:namespace prefix = o /?>
						<o:p>
						</o:p>
				</span>
		</h2>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">重点关注对象的创建和销毁：什么时候、如何创建对象，什么时候、什么条件下应该避免创建对象，如何保证对象在合适的方式下被销毁，如何在销毁对象之前操作一些必须的清理行为。</span>
		</p>
		<h3>
				<span style="FONT-SIZE: 12pt; COLOR: rgb(153,51,102); LINE-HEIGHT: 173%; FONT-FAMILY: 宋体">尝试用静态工厂方法代替构造器</span>
				<span lang="EN-US" style="FONT-SIZE: 12pt; COLOR: rgb(153,51,102); LINE-HEIGHT: 173%">
						<o:p>
						</o:p>
				</span>
		</h3>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">如果一个</span>
				<span lang="EN-US">client</span>
				<span style="FONT-FAMILY: 宋体">要实例化一个对象来使用，傻</span>
				<span lang="EN-US">b</span>
				<span style="FONT-FAMILY: 宋体">都知道应该先调用类的构造器来</span>
				<span lang="EN-US">new</span>
				<span style="FONT-FAMILY: 宋体">一个对象，之后再调用相应的方法。除了这个方式，</span>
				<span lang="EN-US">Java Effective</span>
				<span style="FONT-FAMILY: 宋体">还建议了另一种方法：<b><u>用静态工厂方法来提供一个类的实例</u></b>。以下的例子不反映两者的优劣，只是反映两者在代码实现上的不同，优劣之后再谈：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">假设咱们要一个颜色为黑色、长度为</span>
				<?xml:namespace prefix = st1 /?>
				<st1:chmetcnv w:st="on" tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="50" unitname="cm">
						<span lang="EN-US">50cm</span>
				</st1:chmetcnv>
				<span style="FONT-FAMILY: 宋体">的锤子，自然就用构造器创建一个</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">Hammer myHammer =<span>  </span>new Hammer(Color.BLACK, 50);</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">而用静态工厂方法来实例化一个对象，如下</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">Hammer myHammer = Hammer.factory(Color.BLACK,50);</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">也可以用专门的一个工厂类来实例化</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">Hammer myHammer = Toolkit.factory(“Hammer”, Color.BLACK,50);</span> <span lang="EN-US"><o:p> </o:p></span></p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">单纯从上面的代码上看，真的只有傻</span>
				<span lang="EN-US">b</span>
				<span style="FONT-FAMILY: 宋体">才会选择静态工厂的方法，完全就是多此一举，直接</span>
				<span lang="EN-US">new</span>
				<span style="FONT-FAMILY: 宋体">又快又爽，搞这么麻烦做莫斯（武汉话“什么”的意思）？</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">别急，别急，你急个莫</span>
				<span lang="EN-US">b</span>
				<span style="FONT-FAMILY: 宋体">（武汉粗话：基本就是“你急个毛”的意思）？</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">下面就说说用静态工厂代替构造器的好处（</span>
				<span lang="EN-US">advantage</span>
				<span style="FONT-FAMILY: 宋体">）和不好处（</span>
				<span lang="EN-US">disadvantage</span>
				<span style="FONT-FAMILY: 宋体">）。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<b>
						<span style="FONT-FAMILY: 宋体">第一个好处，讲你都不信，行家们认为，构造器有一个不好的地方就是：这个方法的签名（</span>
						<span lang="EN-US">signture</span>
				</b>
				<b>
						<span style="FONT-FAMILY: 宋体">）太固定了。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">构造器的名字是固定的，生个</span>
				<span lang="EN-US">Hammer</span>
				<span style="FONT-FAMILY: 宋体">，构造器的名字就是</span>
				<span lang="EN-US">Hammer</span>
				<span style="FONT-FAMILY: 宋体">（……），唯一能变化的地方就是参数，假设我的这个锤子有两个很变态的构造需要：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">：第一个参数是颜色（</span>
				<span lang="EN-US">Color</span>
				<span style="FONT-FAMILY: 宋体">型），第二个参数是锤子头的重量（</span>
				<span lang="EN-US">int</span>
				<span style="FONT-FAMILY: 宋体">型）。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">Hammer</span>
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">Color c, int kg</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">{</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">//remainder omited</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">}</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">2</span>
				<span style="FONT-FAMILY: 宋体">：第一个参数是颜色（</span>
				<span lang="EN-US">Color</span>
				<span style="FONT-FAMILY: 宋体">型），第二个参数是锤子的长度（</span>
				<span lang="EN-US">int</span>
				<span style="FONT-FAMILY: 宋体">型）。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">Hammer</span>
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">Color c, int cm</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">{</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">//remainder omited</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">}</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">感觉满足需要了，但是细心一看，完了，构造器的参数列表类型重复了，肯定编译通不过，这是面向对象构造器天生的缺陷——唯一的变化就是参数，参数都分辨不了，就真的分辨不了。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">而另外就算参数能分辨的了，构造器一多，它的参数一多，您根本就不知道每个参数是用来干什么的，只能去查阅文档，在您已经眼花缭乱的时候再去查文档，一个一个的对，折磨人的活。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">这个时候，您就可以考虑用静态工厂方法来实例化对象了。因为静态工厂方法有一个最简单的特点就是：他有可以变化的方法名（构造器的名字变不了）。用名字的不同来代表不同的构造需要，这么简单的普通的特点在这里就是它相对于构造器的</span>
				<span lang="EN-US">advantage</span>
				<span style="FONT-FAMILY: 宋体">。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">如上面的锤子的例子可以这样：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">：</span>
				<span lang="EN-US">Hammer.produceByWeight (Color c, int kg){</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">//remainder omited</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">}</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">2</span>
				<span style="FONT-FAMILY: 宋体">：</span>
				<span lang="EN-US">Hammer.produceByHeight (Color c, int cm){</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">//remainder omited</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">}</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">这是不是一目了然多了。嗯，我是这样认为的。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<b>
						<span style="FONT-FAMILY: 宋体">第二个好处，“静态工厂方法不需要每次都真的去实例化一个对象”——其实这也是另一些优化方法的前提。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">构造器的每次</span>
				<span lang="EN-US">invoke</span>
				<span style="FONT-FAMILY: 宋体">必定会产生一个新的对象，而静态工厂方法经过一定的控制，完全可以不用每次</span>
				<span lang="EN-US">invoke</span>
				<span style="FONT-FAMILY: 宋体">都生成一个新的对象。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">为什么不每次都生成一个对象的原因就不必说了，因为原因太明显。这个原因就是为什么要“共享”对象的原因。</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">下面讲讲通常使用的两种共享具体策略，也就是具体方法了：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">：单例模式的需要，一旦需要某个对象有单例的需要，必定对于这类对象的构造只能用静态工厂方法了。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">2</span>
				<span style="FONT-FAMILY: 宋体">：</span>
				<span lang="EN-US">flyweight</span>
				<span style="FONT-FAMILY: 宋体">模式和不变（</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">immutable</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">）</span>
				<span style="FONT-FAMILY: 宋体">模式的需要，这两个模式很多时候都说一起使用的，一旦一些对象我们认为是不变的，那自然就想拿来重用，也就说共享，而</span>
				<span lang="EN-US">flyweight</span>
				<span style="FONT-FAMILY: 宋体">就是用来重用这些小粒度对象的。</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-FAMILY: 宋体">如</span>
				<span lang="EN-US">Boolean.valueOf (boolean)</span>
				<span style="FONT-FAMILY: 宋体">方法：</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">Boolean a = Boolean.valueOf (100);</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">Boolean b = Boolean.valueOf (100);</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN-LEFT: 18pt; TEXT-INDENT: -18pt; TEXT-ALIGN: left" align="left"> <span lang="EN-US"><span>a，<span style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">  </span></span></span><span lang="EN-US">b</span><span style="FONT-FAMILY: 宋体">两个引用都是指向同一个对象。</span></p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-FAMILY: 宋体">这些对象都是不变的，而</span>
				<span lang="EN-US">valueOf</span>
				<span style="FONT-FAMILY: 宋体">的控制就是用的</span>
				<span lang="EN-US">flyweight</span>
				<span style="FONT-FAMILY: 宋体">方法。</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-FAMILY: 宋体">这种一个状态（如上面一个数字）对应的对象只有一个还有一个好处，就是可以直接通过比较“引用”来判断他们是否</span>
				<span lang="EN-US">equel</span>
				<span style="FONT-FAMILY: 宋体">（这里的</span>
				<span lang="EN-US">equel</span>
				<span style="FONT-FAMILY: 宋体">是逻辑相等的意思），以前需要</span>
				<span lang="EN-US">a.equels(b)</span>
				<span style="FONT-FAMILY: 宋体">，而一旦用“</span>
				<span lang="EN-US">flyweight</span>
				<span style="FONT-FAMILY: 宋体">模式和不变（</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">immutable</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">）</span>
				<span style="FONT-FAMILY: 宋体">模式”后，避免了产生多余的相同对象，用</span>
				<span lang="EN-US">a==b</span>
				<span style="FONT-FAMILY: 宋体">就可以达到</span>
				<span lang="EN-US">a.equels(b)</span>
				<span style="FONT-FAMILY: 宋体">的目的了。这样当然优化了</span>
				<span lang="EN-US">performance</span>
				<span style="FONT-FAMILY: 宋体">。</span> <span lang="EN-US"><o:p> </o:p></span></p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<b>
						<span style="FONT-FAMILY: 宋体">第三个好处，其实就是工厂方法的核心好处——我把它称为“抽象类型构造器”。它可以为我们提供一个抽象类型的实例，同时必要的隐藏了抽象类型的具体结构。这是</span>
						<span lang="EN-US">new</span>
				</b>
				<b>
						<span style="FONT-FAMILY: 宋体">怎么都达不到的。</span>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-FAMILY: 宋体">这种模式的好处其实就是面向对象的最核心的好处，抽象和具体可以分离，一旦抽象定义好了，具体的东西可以慢慢的变化，慢慢的拓展——开闭原则。</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-FAMILY: 宋体">如</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Collections Framework API</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">，都是描述集合类型的接口，也就是对于客户端来看，只有</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Collection</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">这个类要认识，而实际上，实现这个接口的</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Collection</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">是多种多样的。如果要让用户都知道这些具体实现的</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Collection</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">，就增加了复杂度。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">这时，通过一个静态工厂方法，就可以隐藏各种</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Collection</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">的具体实现，而让</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Client</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">只使用返回的</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">Collection</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">对象就可以了。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">这里还可以加上一些权限控制，如这些实现只要对于工厂来讲是可以访问的，不用是</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">public</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">的，而他们只要通过</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">public</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">的工厂就可以提供给用户。非常有利于代码的安全。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<b>
						<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">静态工厂方法的第一个缺点就是：使用静态工厂方法创建的类的构造器经常都是非公共或非</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">protected</span>
				</b>
				<b>
						<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">的。</span>
				</b>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">这样，以后这些类就没有办法被继承了。不过也有人说，不用继承就用</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">composition</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">呗。也是！呵呵。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<b>
						<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">静态工厂方法的第二个缺点是：在</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">jdk</span>
				</b>
				<b>
						<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">文档里，这些静态工厂方法很难跟别的静态方法相区别。</span>
				</b>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">而文档中，构造器是很容易看到的。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">为了一定程度解决这个问题，我们可以用一些比较特别的名字来给这类静态工厂方法来命名。最常用的有：</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">valueOf </span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">——</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
				</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">用来放回跟参数“相同值”的对象。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">getInstance </span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">——</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
				</span>
				<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">返回一个对象的实例。单例模式中，就是返回单例对象。</span>
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="TEXT-ALIGN: left" align="left">
				<b>
						<span style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">总结：静态工厂方法和构造器都有各自的特点。最好在考虑用构造器之前能先考虑一下静态工厂方法，往往，后者更有用一点。如果权衡了以后也看不出那个好用一些，那就用构造器，毕竟简单本分多了。</span>
				</b>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 11.5pt; FONT-FAMILY: TimesNewRoman">
								<o:p>
								</o:p>
						</span>
				</b>
		</p>
<img src ="http://www.blogjava.net/marco/aggbug/58305.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-07-15 12:35 <a href="http://www.blogjava.net/marco/archive/2006/07/15/58305.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>&lt;b&gt;Swing联想杂忆&lt;/b&gt;</title><link>http://www.blogjava.net/marco/archive/2006/03/14/35154.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Mon, 13 Mar 2006 17:51:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/03/14/35154.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/35154.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/03/14/35154.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/35154.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/35154.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 关键字：Observer Pattern、Java Thread、Java Swing Application1 近来的阅读近来寒暑不常，希自珍慰。武汉天气不是狂冷，就是狂热，不时还给我整个雪花，就差冰雹了。&nbsp;自己做的事吧，也没有什么劲儿。看看自己喜欢的东西，等着希望中的学校能给我offers（是复数），看着自己想去又不想去的公司的未来同事在群里面幻想未来的样子，别操你大...&nbsp;&nbsp;<a href='http://www.blogjava.net/marco/archive/2006/03/14/35154.html'>阅读全文</a><img src ="http://www.blogjava.net/marco/aggbug/35154.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-03-14 01:51 <a href="http://www.blogjava.net/marco/archive/2006/03/14/35154.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Web应用程序安全问题</title><link>http://www.blogjava.net/marco/archive/2006/03/09/34388.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Wed, 08 Mar 2006 16:12:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/03/09/34388.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/34388.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/03/09/34388.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/34388.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/34388.html</trackback:ping><description><![CDATA[<P>昨天，以前师兄做的系统因为漏洞又被投诉，头让俺做个presentation给实验室下一级同学总结一下，避免以后再犯错。今天讲完了就放上来，存个证，以后也好翻阅沟通。<BR><BR>不涉及主机安全、网络安全、数据库安全，只从Web应用程序的角度，整理归纳一下面临的主要安全问题。<BR><BR>点击看大图。<BR><A href="/images/blogjava_net/marco/8279/o_Web应用程序安全问题.jpg" target="_blank"><IMG title=Web应用程序安全问题 height=480 alt=r_Web应用程序安全问题.jpg src="http://www.blogjava.net/images/blogjava_net/marco/8279/r_Web应用程序安全问题.jpg" width=530 border=2></A></P><img src ="http://www.blogjava.net/marco/aggbug/34388.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-03-09 00:12 <a href="http://www.blogjava.net/marco/archive/2006/03/09/34388.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OO设计原则体会 </title><link>http://www.blogjava.net/marco/archive/2006/02/27/32568.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Sun, 26 Feb 2006 23:40:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/02/27/32568.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/32568.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/02/27/32568.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/32568.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/32568.html</trackback:ping><description><![CDATA[<P>这几天瞄了几本设计模式的书，没有细看具体模式啦，而是老是琢磨那些深奥无比的话。这些话经常出现在计算机的书籍中，很有禅意，也有哲理。听说，高手就喜欢写点这样的话。</P>
<P>还有就是细心体味了一下OO的设计原则，这些原则是凌驾于模式之上的，也就是更宏观的原则。</P>
<P>其中，最高指导的一个就是“开－闭”原则。别的原则，里氏代换原则、依赖倒置原则、组合/聚合复用原则和迪米特法则都是为了达到“开－闭”原则而出现的规则。</P>
<P>这些原则告诉我很多东西，聚焦于一点就是要“面向抽象”来做一切事情。</P>
<P>分析对象的时候，要多分析设计“抽象”的概念，对象之间的联系要多基于抽象的概念而不是具体，这样具体才能能够变化，这样才是开闭。用我自己的话就是要“游走于 抽象”。</P>
<P>这里有一个我必须记住的就是，在封装变化时候，多用聚合/组合，少用继承。在封装原子变化并且是同类型对象时才用继承，别的都尽量用聚合/组合。而且尽量不要用多级继承，多级继承一般意味着有两种变化脉络，可能的话，让两种变化脉络独立演化。很明显，一独立演化，又要聚合/组合了。</P>
<P>还有一个必须记住的是：运用抽象以后，客户端的使用发生了巨大的变化。不再是指那儿用那儿。而是要做更多的准备工作，因为运用抽象，本身就把具体“组合”的职责推迟到使用的阶段。那谁使用，肯定是客户端。所以，客户端的使用要革新。要习惯用工厂，习惯把一系列的抽象定具体了，并按照一定方式“组合”起来用。而且，最终要善于用接口来调用方法。<BR><BR>用小飞推荐的一个工具画了个图，如下：<BR><IMG height=302 alt=o_好的OO思想.jpg src="http://www.blogjava.net/images/blogjava_net/marco/7898/o_好的OO思想.jpg" width=800 border=0><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;MARCO ZHANG 2006年2月27日7:18:57</P><img src ="http://www.blogjava.net/marco/aggbug/32568.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-02-27 07:40 <a href="http://www.blogjava.net/marco/archive/2006/02/27/32568.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>&lt;b&gt;Java Web Application开发日志之五&lt;/b&gt;&lt;br&gt;－－“design with the think of sharing objects”，Flyweight模式应用</title><link>http://www.blogjava.net/marco/archive/2006/02/23/32097.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Thu, 23 Feb 2006 06:14:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/02/23/32097.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/32097.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/02/23/32097.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/32097.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/32097.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"></SPAN></P><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体"><BR>“共享”的思想</SPAN></B><B><SPAN lang=EN-US style="FONT-SIZE: 14pt"><?xml:namespace prefix = o /><o:p></o:p></SPAN></B> 
<P></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">共享的</SPAN><SPAN lang=EN-US>idea</SPAN><SPAN style="FONT-FAMILY: 宋体">是生活中最基本的</SPAN><SPAN lang=EN-US>idea</SPAN><SPAN style="FONT-FAMILY: 宋体">，不必有意的使用，到处已经存在了。在生活中，大部分事物都是被多人多次使用的，这都是共享的实际应用。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">之于</SPAN></B><B><SPAN lang=EN-US style="FONT-SIZE: 14pt">OO</SPAN></B><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">的共享</SPAN></B><B><SPAN lang=EN-US style="FONT-SIZE: 14pt"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>OO</SPAN><SPAN style="FONT-FAMILY: 宋体">中的共享，无非就是说让“对象”也能被“多人多次”（这里的“人”也无非就是进程、线程而已）使用，更详细的说，就是要让对象的生存空间更大一些，生存周期更长一些。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">自己闷个儿脑子，提炼出了几个需要使用共享的环境（</SPAN><SPAN lang=EN-US>context</SPAN><SPAN style="FONT-FAMILY: 宋体">），也可以说是原因吧：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>1.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">为了保持“对象”的一致，我们需要共享。例如，“国家主席”就一个，不能多了，如果多了，难免决策混乱。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>2.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">为了控制“对象”的存储空间，我们需要共享。毕竟，目前来说，系统的</SPAN><SPAN lang=EN-US>memory</SPAN><SPAN style="FONT-FAMILY: 宋体">还是编程时最珍贵的资源。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>3.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">为了优化“对象”的创建消耗，我们需要共享。如果，一个对象的创建过程消耗太大，系统不能支持频繁的创建，共享的使用它也是一个好主意。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>4.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">等等。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">而在实际的应用中，往往我并没有细想“我为什么使用共享？”，已经不自觉的就用了；如果真的认真分析起来，基于的环境也是多样，并不会只是上面的其中一种。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-FAMILY: 宋体">常用的“共享”方法或模式（我曾经用过的，知道的不多，望谅解）：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>1.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">“</SPAN><SPAN lang=EN-US>Singleton</SPAN><SPAN style="FONT-FAMILY: 宋体">模式”：一个</SPAN><SPAN lang=EN-US>class</SPAN><SPAN style="FONT-FAMILY: 宋体">就一个对象实例，大家都用它，满足</SPAN><SPAN lang=EN-US>context1</SPAN><SPAN style="FONT-FAMILY: 宋体">。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>2.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">“</SPAN><SPAN lang=EN-US>pool</SPAN><SPAN style="FONT-FAMILY: 宋体">技术”：只提供一定数目的对象，大家都用他们，实现</SPAN><SPAN lang=EN-US>context2</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>context3</SPAN><SPAN style="FONT-FAMILY: 宋体">。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>3.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">“</SPAN><SPAN lang=EN-US>flyweight</SPAN><SPAN style="FONT-FAMILY: 宋体">模式”：一个</SPAN><SPAN lang=EN-US>class</SPAN><SPAN style="FONT-FAMILY: 宋体">的一个状态就一个对象实例，实现一个状态对象的共享，实现</SPAN><SPAN lang=EN-US>context2</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>context3</SPAN><SPAN style="FONT-FAMILY: 宋体">。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-FAMILY: 宋体">使用时要注意的地方：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>1.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">确定共享的</SPAN><SPAN lang=EN-US>scope</SPAN><SPAN style="FONT-FAMILY: 宋体">。例如，在</SPAN><SPAN lang=EN-US>Java Web Application</SPAN><SPAN style="FONT-FAMILY: 宋体">中就是选择是</SPAN><SPAN lang=EN-US>page</SPAN><SPAN style="FONT-FAMILY: 宋体">，</SPAN><SPAN lang=EN-US>session</SPAN><SPAN style="FONT-FAMILY: 宋体">还是</SPAN><SPAN lang=EN-US>application</SPAN><SPAN style="FONT-FAMILY: 宋体">，当然也可以是</SPAN><SPAN lang=EN-US>jvm</SPAN><SPAN style="FONT-FAMILY: 宋体">级别的</SPAN><SPAN lang=EN-US>static</SPAN><SPAN style="FONT-FAMILY: 宋体">。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>2.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">确认</SPAN><SPAN lang=EN-US>thread safe</SPAN><SPAN style="FONT-FAMILY: 宋体">。当共享的对象可能被多个线程共享时，这是不可以回避的问题。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>3.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">应对对象状态的变化。一旦共享的对象发生了变化，我们怎么处理？改变之，舍弃之？也是我们需要确定的。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">项目中的应用：</SPAN></B><B><SPAN lang=EN-US style="FONT-SIZE: 14pt"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-FAMILY: 宋体">项目需求：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">为学校的同学提供</SPAN><SPAN lang=EN-US>Web</SPAN><SPAN style="FONT-FAMILY: 宋体">查询，查询的内容有很多。其中，“查课表”、“查考表”是最为关键的需求，以后可能还要提供“查询空闲自习教室”的功能。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">在这些查询中，有一个共同点，就是都涉及“教室”这一对象。“查课表”时要告诉同学在哪个教室上课，“查考表”时要告诉同学在哪个教室考试，等等。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-FAMILY: 宋体">数据库设计：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">对于“查课表”用例，有关的数据库设计如下：</SPAN><SPAN lang=EN-US><o:p><BR><IMG style="WIDTH: 493px; HEIGHT: 416px" height=416 alt=o_5-1-1.jpg hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7744/o_5-1-1.jpg" width=493 border=0>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-FAMILY: 宋体"><BR>对象层的设计：<BR></SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><IMG height=529 alt=o_5-1.JPG src="http://www.blogjava.net/images/blogjava_net/marco/7744/o_5-1.JPG" width=308 border=0><BR>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">学生每查询一门课程的课表，系统就会</SPAN><SPAN lang=EN-US>sql</SPAN><SPAN style="FONT-FAMILY: 宋体">查询“视图</SPAN><SPAN lang=EN-US>V_LESSONSCHEDULE</SPAN><SPAN style="FONT-FAMILY: 宋体">”，进而生成一个</SPAN><SPAN lang=EN-US>LessonSchedule</SPAN><SPAN style="FONT-FAMILY: 宋体">对象，然后返回给用户显示。当然，在生成这个</SPAN><SPAN lang=EN-US>LessonSchedule</SPAN><SPAN style="FONT-FAMILY: 宋体">对象的过程中，属于它的</SPAN><SPAN lang=EN-US>Classroom</SPAN><SPAN style="FONT-FAMILY: 宋体">对象，以及更深一步的</SPAN><SPAN lang=EN-US>Building</SPAN><SPAN style="FONT-FAMILY: 宋体">、</SPAN><SPAN lang=EN-US>Area</SPAN><SPAN style="FONT-FAMILY: 宋体">对象都会生成。下面就是这个过程的顺序图：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;<BR></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><IMG height=391 alt=o_5-2.JPG src="http://www.blogjava.net/images/blogjava_net/marco/7744/o_5-2.JPG" width=604 border=0>&nbsp;<BR></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体"><BR>因此，每生成一个“课表”对象（</SPAN><SPAN lang=EN-US>LessonSchedule</SPAN><SPAN style="FONT-FAMILY: 宋体">）或“考表”对象（</SPAN><SPAN lang=EN-US>ExamSchedule</SPAN><SPAN style="FONT-FAMILY: 宋体">）时，都要：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>1.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">查数据库中的教室、教学楼、校区的信息；</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>2.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">创建相应的“教室对象”（包括了属于它的“教学楼”对象和“校区”对象）。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B><SPAN style="FONT-FAMILY: 宋体">考虑共享“教室”对象</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">“教室”对象一旦可以生成以后，完全可以给后续共享使用，不必要每个查询都要去生成。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体">详细说是基于下面的考虑：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>1.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">这类查询用例（查课表，查考表）发生的频繁很高很高，也就是说，一旦让用户查起来，系统中会产生大量的“教室”对象这类对象，应该说会占很大的内存空间。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt"><SPAN lang=EN-US><SPAN>2.<SPAN style="FONT: 7pt 'Times New Roman'; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体">共享“教室”对象后，可以减少对数据库的查询次数，并降低了查询粒度（以前是基于二级视图查询，现在可以基于基本表查询），提高了一点数据库查询性能。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P><SPAN style="FONT-FAMILY: 宋体">
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当然，同时我脑袋中也有反对的声音：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1.<SPAN style="FONT: 7pt 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">虽说，这类查询会产生很多相同的“教室”对象，但是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">JVM</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">本生提供的垃圾回收功能完全可以处理它。除非，“同时”有很多很多这类对象都在被使用，根本回收不了，才会造成内存短缺。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l0 level1 lfo2"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2.<SPAN style="FONT: 7pt 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果，我以某种共享机制让这些“教室”对象，在系统中存在下来（延长了生命周期）了。而它们本身的数目就很多（如，我们学校就有××），可能还没有等你用上，系统已经挂了。另外，如果不是同时有很多查询需要，我留这么多“教室”对象在系统里，反而是占了内存，而不是优化了内存的使用。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l2 level1 lfo1"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1.<SPAN style="FONT: 7pt 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所有模式的通病――“增加了复杂度”。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结论：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">经过我们分析，系统对于“教室”对象的重复使用，频繁程度非常高。一般，有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">10</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个人同时使用，就有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">5</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个人左右涉及的用例要使用“教室”对象。把它共享起来，还是有一定必要的。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进一步考虑：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而实际上，我们可以进一步共享下去：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">除了让客户端共享“教室对象（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Classroom</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）”外，还可以让“教室对象”共享“教学楼对象（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Building</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）”，和让“教学楼对象”共享“校区对象（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Area</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）”。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">因此，最终的共享是在三级上都实现。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><FONT face="Times New Roman">Flyweight</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式：</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">特点：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">书上说：“享元模式可以使系统中的大量小粒度对象被共享使用”。第一，对象出现的量要大，想必这比较好理解，很少使用的也就没有必要共享了；第二，要小粒度，我比较纳闷？难道对于大粒度对象就不行吗？可能书上认为，大粒度对象的共享已经占了比较大的空间，没有小对象那么有效吧。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">另外，书上还说，要使用“享元模式”，被共享的对象的状态（类别）要比较固定，这样就可以为每一个状态仅仅创建一个对象。当然，如果每次使用对象时，对象的状态都是不一样的，那就根本不存在共享这些对象的必要了。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">联系项目思考：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">基于上面对项目的分析，“教室”、“教学楼”、“校区”对象都是在系统中会被大量使用的对象，而且粒度的确比较小；并且它们有固定的类别，而且不易改变。如校区对象，暂时就有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">4</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个。教学楼可能</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">40</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">－</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">50</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个左右。很适合“享元模式”的使用环境。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">确定共享方式：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l1 level1 lfo3"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1.<SPAN style="FONT: 7pt 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">确定共享对象的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">scope</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。在本</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">web</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">程序中，这些共享对象的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">scope</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">理应是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">application</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，而更简单的一个作法就是把这些对象设为</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">static</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，我选择后者。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l1 level1 lfo3"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2.<SPAN style="FONT: 7pt 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">确认</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">thread safe</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。这些对象是可能被多个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">servlet</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">访问的，也就是有可能存在多线程访问。但是，由于这些对象的可变性很差，一旦创建就不大可能变化。因此，我决定把这写共享对象设计成不变模式的，一旦创建就只会被读取，而不会改写，这样就不存在多线程控制的问题了。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; tab-stops: list 21.0pt; mso-list: l1 level1 lfo3"><SPAN lang=EN-US style="mso-fareast-font-family: 'Times New Roman'"><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">3.<SPAN style="FONT: 7pt 'Times New Roman'"><FONT size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">应对对象状态的变化，如某个教室的类型变了。这里采取的是舍弃的方法，为每个工厂添加了一个清空方法――</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">clear()</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，用于清空已经生成的共享对象。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">设计类图：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt -0.3pt; TEXT-INDENT: -80.85pt; mso-para-margin-left: -7.73gd; mso-char-indent-count: -7.67"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><v:shapetype id=_x0000_t75 path="m@4@5l@4@11@9@11@9@5xe" coordsize="21600,21600" o:spt="75" o:preferrelative="t" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman"><IMG height=506 alt=o_5-3.JPG src="http://www.blogjava.net/images/blogjava_net/marco/7744/o_5-3.JPG" width=772 border=0>&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当然，也可以把这些工厂都设计成“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Singleton</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">模式”的，使它们只会有一个实例。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">客户端使用：</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由于共享的对象都被包含在了“课表”和“考表”对象里，不会被客户端直接访问，因而不会对客户端的使用有任何影响：</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实例代码</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt">
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US style="COLOR: blue"><FONT face="Times New Roman"><o:p></o:p></FONT></SPAN></P><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp; 
<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: #008000">//</SPAN><SPAN style="COLOR: #008000">取得编号为32号课程的“课表对象”</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><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/None.gif" align=top>LessonSchedule&nbsp;oneLesson&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;LessonSchedule.findByLessonNum(</SPAN><SPAN style="COLOR: #000000">32</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/None.gif" align=top><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>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">&nbsp;7</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">&nbsp;8</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></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/None.gif" align=top>Classroom&nbsp;oneClassroom&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;oneLesson.getLnkClassroom();<BR></SPAN><SPAN style="COLOR: #008080">10</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">11</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">12</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">13</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">14</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></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/None.gif" align=top>Building&nbsp;oneBuilding&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;oneClassroom.getLnkBuilding();<BR></SPAN><SPAN style="COLOR: #008080">16</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">17</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">18</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">19</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">20</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">21</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Area&nbsp;oneArea&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;oneBuilding.&nbsp;getLnkArea();<BR></SPAN><SPAN style="COLOR: #008080">22</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">23</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">24</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">25</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">再次重新生成一个编号为32号的“课表对象”</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">26</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">27</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>LessonSchedule&nbsp;twoLesson&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;LessonSchedule.findByLessonNum(</SPAN><SPAN style="COLOR: #000000">32</SPAN><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">28</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">29</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">30</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">31</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">32</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">33</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Classroom&nbsp;twoClassroom&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;twoLesson.getLnkClassroom();<BR></SPAN><SPAN style="COLOR: #008080">34</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">35</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">36</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">37</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">38</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">39</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Building&nbsp;twoBuilding&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;twoClassroom.getLnkBuilding();<BR></SPAN><SPAN style="COLOR: #008080">40</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">41</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">42</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">43</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">44</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080">45</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>Area&nbsp;twoArea&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;twoBuilding.&nbsp;getLnkArea();<BR></SPAN><SPAN style="COLOR: #008080">46</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></DIV></FONT></o:p></SPAN></B>
<P></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">oneClassroom</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">与</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">twoClassroom</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">oneBuilding</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">与</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">twoBuilding</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">；</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">oneArea</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">与</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">twoArea</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由于都是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">32</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">号课程的东西，根据我们的设计意图，应该实现共享。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而实际上，它们每对的确是同一个对象的引用。因此，实现了预期的设想。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><FONT face="Times New Roman">Review</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 14pt"><o:p></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在本项目中，当第一次设计出来的时候，我们发现了某些对象恰好有共享的需要。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而更多的实际情况是，这些需要共享的“信息或状态”在设计中并不是那么恰好的表现为“一个对象”的粒度，而是要不就包含在一个对象内部，要不就跨几个对象。在这样的情况下，共享的设计更多是发生在代码重构阶段而不是第一的设计阶段。当然，为了共享对象而做出的代码重构，最重要的一步就是把需要共享的“信息或状态”设计成为新的对象。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于，“享元模式”来说，就是要把需要共享的“信息或状态”设计成“享元对象”。别的在此就不说了，因为我也不懂了，呵呵。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><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;MARCO ZHANG 2006年2月23日13:48:49<IMG height=19 src="http://www.blogjava.net/Emoticons/music.gif" width=19 border=0></SPAN></P><img src ="http://www.blogjava.net/marco/aggbug/32097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-02-23 14:14 <a href="http://www.blogjava.net/marco/archive/2006/02/23/32097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>&lt;b&gt;Java Web Application开发日志之四&lt;/b&gt;&lt;br&gt;－－“make the method become dynamic”，“洋葱”模式应用</title><link>http://www.blogjava.net/marco/archive/2006/02/18/31429.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Sat, 18 Feb 2006 15:53:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/02/18/31429.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/31429.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/02/18/31429.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/31429.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/31429.html</trackback:ping><description><![CDATA[<H3 style="MARGIN: 13pt 0cm"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=5>废话：</FONT></SPAN></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">预料中的日志</SPAN><SPAN lang=EN-US>3</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">暂时生产不出来，话说难产就好，别夭折就行，有点掉价哦，呵呵。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p><FONT size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>因为有些东西还没有想清楚。那就先搞个四吧，这个东西还是清楚那么一点的。</FONT></SPAN></P>
<H3 style="MARGIN: 13pt 0cm"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=5>一版描述：</FONT></SPAN></H3>
<TABLE class=MsoNormalTable style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR style="HEIGHT: 30.8pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e0e0e0; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 72pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 30.8pt; mso-border-alt: solid windowtext .5pt" width=96>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">项目需求</SPAN><SPAN lang=EN-US style="COLOR: navy"><o:p></o:p></SPAN></B></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 342pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 30.8pt; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=456>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使每个</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">能对用户访问权限进行检查。简单来说，就是要给每个</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">加个锁，有钥匙的用户才能访问。</SPAN></P></TD></TR></TBODY></TABLE>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而项目中用户所谓的访问权限是基于他拥有的角色。也就是说，</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对用户访问权限的检查，就是对他所拥有角色的检查。暂时，每个用户只能拥有一个角色。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">项目的角色很多，但是在</SPAN><SPAN lang=EN-US>web</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">端暂时只有如下的三种：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<TABLE class=MsoNormalTable style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR style="HEIGHT: 30.8pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e0e0e0; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 90pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 30.8pt; mso-border-alt: solid windowtext .5pt" width=120>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">项目暂时角色</SPAN><SPAN lang=EN-US style="COLOR: navy"><o:p></o:p></SPAN></B></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 324pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 30.8pt; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=432>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">游客，学生，教师</SPAN></P></TD></TR></TBODY></TABLE>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">既然这样，</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的加锁方式就有：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<TABLE class=MsoNormalTable style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR style="HEIGHT: 30.8pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e0e0e0; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 90pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 30.8pt; mso-border-alt: solid windowtext .5pt" width=120>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="COLOR: navy">servlet</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: navy; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">加锁方式</SPAN><SPAN lang=EN-US style="COLOR: navy"><o:p></o:p></SPAN></B></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 324pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 30.8pt; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" width=432>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><SPAN lang=EN-US><SPAN style="mso-spacerun: yes">&nbsp;</SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">游客，学生，教师，<BR>游客或学生，游客或教师，学生或教师，<BR>游客或学生或教师</SPAN></P></TD></TR></TBODY></TABLE>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="COLOR: #993300; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;<FONT size=4>注：上面的“游客”就是“游客角色有权访问”的意思，依此类推。</FONT></SPAN><SPAN lang=EN-US style="COLOR: #993300"><o:p></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这里只有关系“或”（</SPAN><SPAN lang=EN-US>||</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），如果一个</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的加锁方式是“学生或教师”，也就是说拥有学生或教师角色的用户都可以访问它。关系“与”（</SPAN><SPAN lang=EN-US>&amp;&amp;</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）在这里不太可能存在，因为没有需求说：某个</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一定只能由“既是学生又是教师的用户”才能访问，而且前面也说了，暂时一个用户“有且只有”一个角色。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<TABLE class=MsoNormalTable style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #ccffff; MARGIN: auto auto auto 14.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellSpacing=0 cellPadding=0 border=1>
<TBODY>
<TR style="HEIGHT: 15.75pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 396pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 15.75pt; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt" vAlign=top width=528>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US>So we can get following function</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">：<BR></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 黑体"><BR>“加锁方式数” ＝<SPAN lang=EN-US> 2</SPAN>的“角色数”次方 －<SPAN lang=EN-US> 1<BR><o:p></o:p></SPAN></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><BR>“加锁方式数”是关于“角色数”的指数函数，也就是说它是关于“角色数”成“指数级”增长的，应该说很快了吧。<BR></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><BR>3</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个角色就有</SPAN><SPAN lang=EN-US>2</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN><SPAN lang=EN-US>3</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">次方－</SPAN><SPAN lang=EN-US>1</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个，也就是</SPAN><SPAN lang=EN-US>7</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个加锁方式。</SPAN></P></TD></TR></TBODY></TABLE>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">运用</SPAN><SPAN lang=EN-US>OO</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的最基本方式，就是封装对象。既然有为</SPAN><SPAN lang=EN-US>servlet</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">“看门”的责任，那就把这个责任封装成一个对象，用个俗名：</SPAN><SPAN lang=EN-US>validator</SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p>&nbsp;</o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>接着，运用共性和个性的分析方法，既然有那么多种不同的看门方式（加锁方式），那就搞一个接口，然后让各种“不同”都实现这个接口，形成子类。那就有下面的图：</FONT><BR><BR><IMG height=511 alt=o_4-1.JPG src="http://www.blogjava.net/images/blogjava_net/marco/7574/o_4-1.JPG" width=616 border=0><BR><BR></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">可以看到，由于有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">7</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个加锁方式，那就要有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">7</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个子类。每个子类根据自己逻辑</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">override</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样，对于一个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">servlet</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，想让它上什么样的锁，只要让它拿到对应的子类的引用即可，如下图中的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">ClientServlet</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，我们规定只能有“学生或教师”才能访问它。它的部分代码便是：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><BR><IMG height=512 alt=o_4-2.JPG src="http://www.blogjava.net/images/blogjava_net/marco/7574/o_4-2.JPG" width=620 border=0></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt">&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt">&nbsp;</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: #008000">//</SPAN><SPAN style="COLOR: #008000">new对应的Validator接口的子类。<BR></SPAN><SPAN style="COLOR: #008080">2</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">这里是学生或教师可访问，因此要new&nbsp;Student_Or_Teacher_Validator</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #008080">3</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">Validator&nbsp;validator&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Student_Validator();<BR></SPAN><SPAN style="COLOR: #008080">4</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">5</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">boolean</SPAN><SPAN style="COLOR: #000000">&nbsp;ok&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;validator.validate();</SPAN></DIV></SPAN><BR>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>至此，第一个解决方案就出来了。</FONT><BR></P>
<H3 style="MARGIN: 13pt 0cm"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=5>思考：</FONT></SPAN></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt">
<TABLE class=MsoNormalTable style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 5.4pt; BORDER-LEFT: medium none; WIDTH: 441pt; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellSpacing=0 cellPadding=0 width=588 border=1>
<TBODY>
<TR style="HEIGHT: 24pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #99ccff; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 36pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 24pt; mso-border-alt: solid windowtext .5pt" width=48>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不足</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 405pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 24pt; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=540>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口的子类数目随“角色数”成“指数级”增长，数量太多；而且子类中重复逻辑的代码很多，如“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”就重复了“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”和“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”的逻辑，万一“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”的逻辑要改，只要涉及</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的子类都要跟着改，维护上不方便。</SPAN></P></TD></TR></TBODY></TABLE></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt">
<TABLE class=MsoNormalTable style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN: auto auto auto 5.4pt; BORDER-LEFT: medium none; WIDTH: 441pt; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellSpacing=0 cellPadding=0 width=588 border=1>
<TBODY>
<TR style="HEIGHT: 6.75pt; mso-yfti-irow: 0; mso-yfti-firstrow: yes; mso-yfti-lastrow: yes">
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #99ccff; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 54pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 6.75pt; mso-border-alt: solid windowtext .5pt" width=72>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align=center><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进一步改进的可能</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></P></TD>
<TD style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #ece9d8; WIDTH: 387pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 6.75pt; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" vAlign=top width=516>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类”的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法很大程度上就是“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类”的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法和“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类”的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法“或操作”出来的结果。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">因此，能不能考虑由“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法”和“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法”<B style="mso-bidi-font-weight: normal"><SPAN style="COLOR: red">动态的构造</SPAN></B>一个功能如“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法”。</SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这样，“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”就可以省略了，只剩下一些原子的“角色类”。要实现</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的验证功能，拿</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">装配一下就可以了。</SPAN></P></TD></TR></TBODY></TABLE></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">结论，需要根据实际情况，动态的改变（装配）“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Validator</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口对象”的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">validate</FONT></SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方法。</SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>第一个火花就是“装饰模式”。它可以让客户端动态的组装对象的方法。真神奇！</FONT></SPAN></P>
<H3 style="MARGIN: 13pt 0cm"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=5>第二版来啦</FONT></SPAN></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><IMG height=460 alt=o_4.JPG src="http://www.blogjava.net/images/blogjava_net/marco/7342/o_4.JPG" width=569 border=0></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="COLOR: #993300; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">注：上图中出现了</SPAN><SPAN lang=EN-US style="COLOR: #993300"><FONT face="Times New Roman">AndRelation</FONT></SPAN><SPAN style="COLOR: #993300; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US style="COLOR: #993300"><FONT face="Times New Roman">And</FONT></SPAN><SPAN style="COLOR: #993300; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的一系列角色类，可以暂时省略不看，因为前面说了，现在还没有“与”关系这个需求。只看</SPAN><SPAN lang=EN-US style="COLOR: #993300"><FONT face="Times New Roman">Or</FONT></SPAN><SPAN style="COLOR: #993300; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的就可以。</SPAN><SPAN lang=EN-US style="COLOR: #993300"><o:p></o:p></SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>我喜欢叫这个模式为洋葱模式，一层包一层，最外层对象某方法的逻辑是由内部一层一层对象的同一方法组合出来的。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">使用了这个模式，便不用如一版那样实现那么多子类，只要实现几个“角色类”即可，这里有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">3</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个（学生角色：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、教师角色：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Teacher</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、游客角色：</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Guest</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）。所有一版中<B style="mso-bidi-font-weight: normal">别的</B>子类都可以由这</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">3</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个组装出来。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如要生成一版中的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，可以用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Teacher</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">两个对象“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”出来：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN><SPAN lang=EN-US><FONT face="Times New Roman"></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">Validator&nbsp;validator&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Or_Student(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Or_Teacher(OrRelation(req)));</SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如要生成一版中的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Guest_Or_Student_Or_Teacher_Validator</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，可以用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">、</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Teacher</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">和</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or&nbsp;_Guest</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">三个对象“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">”出来：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman"></FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><FONT face="Times New Roman">&nbsp;</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">Validator&nbsp;validator&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Or_Student(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Or_Teacher(</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Or_Guest(OrRelation(req))));</SPAN></DIV>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"></FONT></SPAN>&nbsp;</P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman">&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这种一层包一层的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">new</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">方式，是不是很像洋葱？第一次看是很不习惯，看多了就觉得习惯了。</SPAN></FONT></P>
<H3 style="MARGIN: 13pt 0cm"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=5>对客户端的影响：</FONT></SPAN></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>一版中，客户端要什么样的验证类，就直接使用具体类。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">二版中，客户端要什么样的验证类，它的工作多了那么一丁点，它需要先组装一下，正如上面的例子。这种组装的方法很易于理解和使用，不会给客户端带来任何的不便。如果实在觉得客户端组装不出来（傻</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">B</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">客户端），也可以搞个工厂给它</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">supply</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">！</SPAN></FONT></P>
<H3 style="MARGIN: 13pt 0cm"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=5>优点：</FONT></SPAN></H3>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 42.75pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>相对一版最明显的优点就是类的数目少了很多。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 42.75pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 42.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一版不是说“指数级”吗？这里只是线性的了。假设某一天系统拓展到有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">10</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个角色，一版就有</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">10</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">次方那么多个，也就是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">1024</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个验证类。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 42.75pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 42.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而二版还是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">10</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个角色类，别的都可以在客户端使用的时候，动态的组装</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; tab-stops: 42.75pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">更重要的是代码结构好了，重复逻辑少了。每个逻辑都以最</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">atomic</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的大小放到最应该的地方。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">进而，维护的代价少多了。如某天“教师角色”的验证逻辑发生了变化，只要改动</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Or_Teacher</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一个地方即可。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MARCO ZHANG 2006年2月18日23:49:56<IMG height=19 src="http://www.blogjava.net/Emoticons/beer_mug.gif" width=19 border=0></FONT><BR></SPAN></P><img src ="http://www.blogjava.net/marco/aggbug/31429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-02-18 23:53 <a href="http://www.blogjava.net/marco/archive/2006/02/18/31429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>&lt;b&gt;Java Web Application开发日志之二&lt;/b&gt;&lt;br&gt;－－“Ignore how they were created”，工厂方法模式应用</title><link>http://www.blogjava.net/marco/archive/2006/02/16/30894.html</link><dc:creator>marco</dc:creator><author>marco</author><pubDate>Wed, 15 Feb 2006 19:53:00 GMT</pubDate><guid>http://www.blogjava.net/marco/archive/2006/02/16/30894.html</guid><wfw:comment>http://www.blogjava.net/marco/comments/30894.html</wfw:comment><comments>http://www.blogjava.net/marco/archive/2006/02/16/30894.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.blogjava.net/marco/comments/commentRss/30894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/marco/services/trackbacks/30894.html</trackback:ping><description><![CDATA[<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;</SPAN></SPAN>说起这个工厂模式，一时还真不知道该如何说起。反正这是我的开发日志，不提理论的东西，理论的东西那里都有，我只想把具体实践记录下来给师弟师妹们作个参考，积累点经验。所有这些文字都是集中讲一点――“在什么情况下为什么用某种模式好，为什么好，为什么在那种情况下能想起来用？”。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">研究生院项目中“明显”使用了“工厂方法模式”。其实在遇到具体问题的时候，即使我们不知道有这个模式存在，我们也肯定会造一个类似的东西出来。但是，肯定没有书上论述的那么好，那么全面。我想这就是看书的好处吧。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p><FONT size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; COLOR: #003366; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">工厂方法出现的必然（我的理解，一个很狭隘并幼稚理的人的理解）</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #003366"><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #003366"><o:p><FONT size=4>&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">刚开始使用这个东西的时候，只是感觉是单纯的一种模式，用于创建需要的对象。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">但是随着使用和思考的深入，越发发现它给我的启示不只在于单纯的对象创建，而是告诉我应该怎么理解“产品”，怎么得到“产品”，怎么消费“产品”，以至于以后怎么设计“产品”。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT size=4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>下面这个线索是我对它出现必然性的理解：</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><SPAN><STRONG><FONT size=4><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">1.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></FONT></SPAN>“针对接口编程”</FONT></STRONG></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;这是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OO</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">世界中经典的规范，不管你主动还是被动，你天天都在用这个东西。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-spacerun: yes"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口是共性的表示，在对象的世界中，共性和个性的辩证关系是最重要的关系。在万千的对象中，通过它们之间的共性和个性，可以形成最基本对象层级架构。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">假设我们的讨论域中有以下一些对象：“学生”、“大学生”、“小学生”、“中学生”；我们不用细想，学过一天</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OO</FONT></SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>的人都可以为这些耳熟能详的对象们，通过个性和共性的关系得出下面的结构图。<BR><BR></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"></SPAN><SPAN lang=EN-US><o:p><FONT size=4><IMG style="WIDTH: 356px; HEIGHT: 285px" height=285 alt=o_1.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_1.JPG" width=356 border=2></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">把这些对象之间的关系定义成这样是顺理成章的。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">下一步肯定是让客户端“使用”这个接口啦。也就是如下图：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><FONT size=4><IMG style="WIDTH: 464px; HEIGHT: 272px" height=272 alt=o_2.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_2.JPG" width=464 border=2><BR><BR></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><SPAN><STRONG><FONT size=4><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">2.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></FONT></SPAN>接口和具体类的矛盾</FONT></STRONG></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">勿庸置疑，我们只希望</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">跟接口</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打交道，让它根本就不知道</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">有哪些子类，绝对不希望直接跟它们打交道。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">但这里出现的困难是，接口都是“假”的，都是由具体类</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">upcast</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">要使用接口</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中必须会出现下面的代码：</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN lang=EN-US><FONT face="Times New Roman" size=4>Student marco = new Small_Student();</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">只要一出现这个代码，就说明</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">不只跟</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打交道了，它知道了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Small_Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类，这违反了我们预先的想法。</SPAN></FONT></P></SPAN><SPAN lang=EN-US><o:p>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><SPAN><STRONG><FONT size=4><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">3.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></FONT></SPAN>找“人”帮我去创建“接口对象”</FONT></STRONG></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp; 从上图体现出来的结构看，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">只想跟</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">打交道的目的是实现不了的了。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman" size=4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>最简单的方法就是找另外的“帮手”去帮我生成这个“接口对象”。这个帮手它知道“接口对象”的具体类型，但是它为客户端提供的却一定是“接口类型”。这就符合我们的要求了。如图：<BR><BR></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"></SPAN><SPAN lang=EN-US><o:p><FONT size=4><IMG style="WIDTH: 547px; HEIGHT: 364px" height=364 alt=o_3.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_3.JPG" width=547 border=2><BR><BR></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp; 这样，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就可以既用到了“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口对象”，又不用因为“只有具体类才能创建对象”的规则，而必须对其子类结构有完全的了解。它成功的解决了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中的矛盾。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">而“负责创建具体类对象的任务”全部都落在了这个“帮手”身上，这个“帮手”（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Factory</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">）就是工厂模式中的工厂类，更具体的说，它就是“简单工厂模式”中的“简单工厂类”。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我觉得，即使一点都不知道工厂模式，一旦我遇到了</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">2</FONT></SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>里说的矛盾，我也会用这样的方法处理。</FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><SPAN><STRONG><FONT size=4><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">4.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></FONT></SPAN>这个“帮手”不符合“开－闭原则”</FONT></STRONG></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>这个帮手的确不错了，而且一跃成为系统中最重要的对象了，所有“创建具体类的逻辑”都放进去了，也就是因为重要，万一挂了不就惨了。</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">再者，它不符合“开－闭”原则，我不能在不修改这个帮手的情况下添加任何一个产品。在这个例子中就是，如果那天我有病非要加一个“幼儿园学生”进来，那您就必须修改这个“帮手”的代码了，这个“帮手”现在就变成</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Version2</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">（如下图）了，这个二版的帮手，可以在“代码”层实现对一版（还没有添加幼儿园学生之前</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">)</FONT></SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>的通用，但这种保证在“开－闭”原则看来，还是不够的，不保险的，它要的是在类的结构上的保证。声明一下，这是我很感性的理解，不正确的可能性很高。<BR><BR><IMG style="WIDTH: 620px; HEIGHT: 391px" height=391 alt=o_4.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_4.JPG" width=620 border=2><BR><BR></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><SPAN><STRONG><FONT size=4><SPAN style="mso-list: Ignore"><FONT face="Times New Roman">5.<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></FONT></SPAN>让“帮手”也多态</FONT></STRONG></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21.75pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>这里可以尝试让“帮手”也多态一下，这样“每种学生类创建的任务”都被分派到了多态出来的类中去了。这时，再有新的学生类型加进来，添加一个对应的帮手就可以了。这样虽然类多了一些，但是符合“开－闭”原则，书上称之为“工厂方法模式”。如图：<BR><BR><IMG style="WIDTH: 636px; HEIGHT: 502px" height=502 alt=o_5.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_5.JPG" width=636 border=2><BR><BR></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp; 假如</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>现在要使用一个小学生，代码如下：<BR><BR></FONT></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"><FONT size=4><SPAN style="COLOR: #008080">1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">创建一个小学生工厂类这个帮手</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">2</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Student_Factory&nbsp;factory&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Small_Student_Factory();<BR></SPAN><SPAN style="COLOR: #008080">3</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">求助这个帮手，帮我创建一个</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">4</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Student&nbsp;primaryStudent&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;factory.produce();<BR></SPAN><SPAN style="COLOR: #008080">5</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">这时就可以使用这个小学生了，让它玩玩游戏吧</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">6</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primaryStudent.playGames();<BR></SPAN><SPAN style="COLOR: #008080">7</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></FONT></DIV></SPAN></SPAN></SPAN><SPAN lang=EN-US><o:p><BR></o:p></SPAN></SPAN>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><FONT size=4></FONT></SPAN><SPAN lang=EN-US><o:p></o:p></SPAN></P></SPAN>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>&nbsp;&nbsp;&nbsp; 在这里还是要强调两点：</FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">虽然实际上</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的确使用了一个小学生对象（</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Small_Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">），但这里</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">也认为它就是</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，这里一定要用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口来隐藏它的具体类。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><FONT size=4><SPAN lang=EN-US style="FONT-FAMILY: Wingdings; mso-bidi-font-family: Wingdings; mso-fareast-font-family: Wingdings"><SPAN style="mso-list: Ignore">n<SPAN style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">另外，却不需要用</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Factory</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">这个接口来隐藏它的具体类，因为，</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">实际就是通过“选择它的具体类”这招儿来“选择创建的学生类型”。这里的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Factory</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">更多的功能不是“隐藏”具体类，而是“规范”具体类。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; COLOR: #003366; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">项目实践</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #003366"><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #003366"><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">扯淡到此，该联系我们的项目啦。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">由于是做研究生院的项目，其中巨大的需求就是要让同学能在网上提交各种申请单，申请退学的，申请转专业的，申请复学的，申请保留学籍的，除了申请女朋友的外，应有尽有。</SPAN><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对于这些单子，用最最基本</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">OO</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">思维，根据共性个性分析方式，抽象出一个申请单接口，和若干的具体类。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">当然，除了概念上感性上吻合以外，在项目中它们也要“真”的有巨大的共性才行，如都要提交，修改，删除，审核，打印等功能。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">靠，既然都这样了，肯定就用一接口规定它了。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman" size=4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>想到这里，加上有了上面的思考，不用说了，就用工厂方法模式啦。<BR></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><FONT size=4><IMG style="WIDTH: 629px; HEIGHT: 468px" height=468 alt=o_6.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_6.JPG" width=629 border=2><BR><BR></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">&nbsp;&nbsp;&nbsp; 图中</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Ent_Shift</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就是申请单接口。等于前面分析的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口。还可以看到有很多具体类，前面例子中是代表各种学生，这里就是代表各种申请单。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman" size=4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>当然，这里还有很多工厂，也就是前面一直叫的“帮手”。<BR><BR></FONT></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt 21pt; TEXT-INDENT: -21pt; mso-list: l0 level1 lfo1; tab-stops: list 21.0pt"><FONT size=4><IMG style="WIDTH: 665px; HEIGHT: 277px" height=277 alt=o_7.JPG hspace=0 src="http://www.blogjava.net/images/blogjava_net/marco/7462/o_7.JPG" width=665 border=2><BR><BR></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bean_Shift</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">就是工厂接口，相当于前面的</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Student_Factory</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">接口。还有很多的具体类就是生产各种申请单的工厂类。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman" size=4>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>下面就是使用“申请单工厂方法模式”的一段客户端代码：<BR><BR></FONT></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"><FONT size=4><SPAN style="COLOR: #008080">&nbsp;1</SPAN><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">声明申请单接口</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">&nbsp;2</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ent_Shift&nbsp;es&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN></FONT><FONT size=4><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/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">声明申请单工厂接口</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">&nbsp;4</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bean_Shift&nbsp;bs&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">null</SPAN></FONT><FONT size=4><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>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">根据传入的申请单类型数字身成对应的申请单工厂</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">&nbsp;6</SPAN><SPAN style="COLOR: #008000"><IMG id=Codehighlighter1_137_479_Open_Image onclick="this.style.display='none'; Codehighlighter1_137_479_Open_Text.style.display='none'; Codehighlighter1_137_479_Closed_Image.style.display='inline'; Codehighlighter1_137_479_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_137_479_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_137_479_Closed_Text.style.display='none'; Codehighlighter1_137_479_Open_Image.style.display='inline'; Codehighlighter1_137_479_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">switch</SPAN><SPAN style="COLOR: #000000">&nbsp;(shiftTypeID)&nbsp;</SPAN><SPAN id=Codehighlighter1_137_479_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></FONT><SPAN id=Codehighlighter1_137_479_Open_Text><FONT size=4><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;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">case</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Bean_Shift.SHIFT_CHANGETEAAP&nbsp;:<BR></SPAN><SPAN style="COLOR: #008080">&nbsp;8</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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bs&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Bean_Shift_CHANGETEAAP();<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">break</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">;<BR></SPAN><SPAN style="COLOR: #008080">10</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;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">case</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Bean_Shift.SHIFT_RESERVEAP&nbsp;:<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bs&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Bean_Shift_RESERVEAP();<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">break</SPAN></FONT><FONT size=4><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;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">case</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Bean_Shift.SHIFT_RENEWAP&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bs&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;Bean_Shift_RENEWAP();<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">break</SPAN></FONT><FONT size=4><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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">省略了别的申请单……………………</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">17</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;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">default</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;:<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN><SPAN style="COLOR: #000000">.forwardErr(req,&nbsp;resp,&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">所选择的异动类别不存在</SPAN><SPAN style="COLOR: #000000">"</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">);<BR></SPAN><SPAN style="COLOR: #008080">19</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></FONT></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><SPAN style="COLOR: #008080"><FONT size=4>20</FONT></SPAN><FONT size=4><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR></SPAN><SPAN style="COLOR: #008080">21</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_488_546_Open_Image onclick="this.style.display='none'; Codehighlighter1_488_546_Open_Text.style.display='none'; Codehighlighter1_488_546_Closed_Image.style.display='inline'; Codehighlighter1_488_546_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_488_546_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_488_546_Closed_Text.style.display='none'; Codehighlighter1_488_546_Open_Image.style.display='inline'; Codehighlighter1_488_546_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN id=Codehighlighter1_488_546_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></FONT><SPAN id=Codehighlighter1_488_546_Open_Text><FONT size=4><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;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">调用工厂接口的生产方法</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><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;&nbsp;&nbsp;&nbsp;&nbsp;es&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;bs.getBlankShift(stuID);<BR></SPAN><SPAN style="COLOR: #008080">24</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">25</SPAN><SPAN style="COLOR: #000000"><IMG id=Codehighlighter1_568_613_Open_Image onclick="this.style.display='none'; Codehighlighter1_568_613_Open_Text.style.display='none'; Codehighlighter1_568_613_Closed_Image.style.display='inline'; Codehighlighter1_568_613_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_568_613_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_568_613_Closed_Text.style.display='none'; Codehighlighter1_568_613_Open_Image.style.display='inline'; Codehighlighter1_568_613_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></FONT></SPAN><FONT size=4><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000">&nbsp;(Exception&nbsp;e)&nbsp;</SPAN><SPAN id=Codehighlighter1_568_613_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></FONT><SPAN id=Codehighlighter1_568_613_Open_Text><FONT size=4><SPAN style="COLOR: #000000">{<BR></SPAN><SPAN style="COLOR: #008080">26</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;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">this</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">.forwardErr(req,&nbsp;resp,&nbsp;DB_ERROR);<BR></SPAN><SPAN style="COLOR: #008080">27</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></FONT></SPAN><SPAN style="COLOR: #000000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">28</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">调用单子的提交方法</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">29</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;es.submit(req);<BR></SPAN><SPAN style="COLOR: #008080">30</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR></SPAN><SPAN style="COLOR: #008080">31</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">发给页面去显示</SPAN></FONT><SPAN style="COLOR: #008000"><BR></SPAN><FONT size=4><SPAN style="COLOR: #008080">32</SPAN><SPAN style="COLOR: #008000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;es.fowrardWithSessionObject(<BR></SPAN><SPAN style="COLOR: #008080">33</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;req,<BR></SPAN><SPAN style="COLOR: #008080">34</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resp,<BR></SPAN><SPAN style="COLOR: #008080">35</SPAN></FONT><FONT size=4><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ent_Shift.nameInSessionAndRequest);<BR></SPAN><SPAN style="COLOR: #008080">36</SPAN><SPAN style="COLOR: #000000"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN></FONT></DIV></SPAN>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><SPAN lang=EN-US><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><B style="mso-bidi-font-weight: normal"><SPAN style="FONT-SIZE: 12pt; COLOR: #003366; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">升华</SPAN></B><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #003366"><o:p></o:p></SPAN></B></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><B style="mso-bidi-font-weight: normal"><SPAN lang=EN-US style="FONT-SIZE: 12pt; COLOR: #003366"><o:p><FONT face="Times New Roman" size=4>&nbsp;</FONT></o:p></SPAN></B></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">个人比较同意《</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Design Pattern Explained</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">》中作者讲的，要用好很多的模式，其中都有一个思路，就是用接口或抽象类来隐藏子类的不同。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我每当看到这时，老是会被一种思路困扰――“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">new</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">只能</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">new</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">具体类啊，这咋能隐藏呢，这隐藏还有什么用呢？”。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">作者仿佛也曾经有过我的这个傻</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">B</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">苦恼，它的解决方法就是：根本在使用对象的时候，特别是设计阶段，尽量不去想对象是在那里被</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">new</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的。他认为：反正有了工厂模式后，你总有办法把他们</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">new</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">出来的。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">所以，我用了工厂模式后更发的启发是：以后设计的时候不要想一个</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Client</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">怎么创建一个对象，尽管放心大胆的先继续想，直接使用就好了。反正最后我还有工厂模式呢。</SPAN></FONT></P>
<P class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><FONT size=4><SPAN lang=EN-US><SPAN style="mso-tab-count: 1"><FONT face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN></SPAN><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">因此俺的副标题才是“</SPAN><SPAN lang=EN-US><FONT face="Times New Roman">Ignore how they were created</FONT></SPAN></FONT><SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><FONT size=4>”，呵呵。<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;MARCO ZHANG 2006年2月16日3:52:10 </FONT></SPAN></o:p></SPAN></o:p></SPAN></o:p></SPAN></SPAN><FONT size=4><IMG height=19 src="http://www.blogjava.net/Emoticons/Pizza.gif" width=19 border=0></FONT></P><img src ="http://www.blogjava.net/marco/aggbug/30894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/marco/" target="_blank">marco</a> 2006-02-16 03:53 <a href="http://www.blogjava.net/marco/archive/2006/02/16/30894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>