﻿<?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-剑心博客-文章分类-转来好帖</title><link>http://www.blogjava.net/powerwind/category/18311.html</link><description>Just for java</description><language>zh-cn</language><lastBuildDate>Mon, 19 Mar 2007 03:09:13 GMT</lastBuildDate><pubDate>Mon, 19 Mar 2007 03:09:13 GMT</pubDate><ttl>60</ttl><item><title>设计模式之Interpreter(解释器)</title><link>http://www.blogjava.net/powerwind/articles/87031.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:54:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87031.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87031.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87031.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87031.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87031.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Interpreter(解释器)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/05</p>
		<p align="center">
				<a href="http://www.jdon.com/mybook/index.htm" target="_blank">
						<strong>
								<font color="#002c99">模式实战书籍《Java实用系统开发指南》</font>
						</strong>
				</a>
		</p>
		<p>Interpreter解释器模式定义:<br />定义语言的文法 ,并且建立一个解释器来解释该语言中的句子.</p>
		<p>Interpreter似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个语言的文法.我们还是来简单的了解一下:</p>
		<p>首先要建立一个接口,用来描述共同的操作.</p>
		<p>public interface AbstractExpression { <br />　　 void interpret( Context context ); <br />} </p>
		<p>再看看包含解释器之外的一些全局信息</p>
		<p>public interface Context { } </p>
		<p>AbstractExpression的具体实现分两种:终结符表达式和非终结符表达式:</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: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> TerminalExpression </span>
				<span style="COLOR: #0000ff">implements</span>
				<span style="COLOR: #000000"> AbstractExpression { <br />　　 </span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">void</span>
				<span style="COLOR: #000000"> interpret( Context context ) { }<br />} </span>
		</div>
		<p>对于文法中没一条规则,非终结符表达式都必须的:<br /></p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img id="Codehighlighter1_65_343_Open_Image" onclick="this.style.display='none'; Codehighlighter1_65_343_Open_Text.style.display='none'; Codehighlighter1_65_343_Closed_Image.style.display='inline'; Codehighlighter1_65_343_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" />
				<img id="Codehighlighter1_65_343_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_65_343_Closed_Text.style.display='none'; Codehighlighter1_65_343_Open_Image.style.display='inline'; Codehighlighter1_65_343_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> NonterminalExpression </span>
				<span style="COLOR: #0000ff">implements</span>
				<span style="COLOR: #000000"> AbstractExpression </span>
				<span id="Codehighlighter1_65_343_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.blogjava.net/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_65_343_Open_Text">
						<span style="COLOR: #000000">{ <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />　　 </span>
						<span style="COLOR: #0000ff">private</span>
						<span style="COLOR: #000000"> AbstractExpression successor; <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />　　<br /><img id="Codehighlighter1_173_213_Open_Image" onclick="this.style.display='none'; Codehighlighter1_173_213_Open_Text.style.display='none'; Codehighlighter1_173_213_Closed_Image.style.display='inline'; Codehighlighter1_173_213_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_173_213_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_173_213_Closed_Text.style.display='none'; Codehighlighter1_173_213_Open_Image.style.display='inline'; Codehighlighter1_173_213_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　 </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">void</span>
						<span style="COLOR: #000000"> setSuccessor( AbstractExpression successor ) </span>
						<span id="Codehighlighter1_173_213_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_173_213_Open_Text">
								<span style="COLOR: #000000">{ <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />　　　　 </span>
								<span style="COLOR: #0000ff">this</span>
								<span style="COLOR: #000000">.successor </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000"> successor; <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　 }</span>
						</span>
						<span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_261_291_Open_Image" onclick="this.style.display='none'; Codehighlighter1_261_291_Open_Text.style.display='none'; Codehighlighter1_261_291_Closed_Image.style.display='inline'; Codehighlighter1_261_291_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_261_291_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_261_291_Closed_Text.style.display='none'; Codehighlighter1_261_291_Open_Image.style.display='inline'; Codehighlighter1_261_291_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　 </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> AbstractExpression getSuccessor() </span>
						<span id="Codehighlighter1_261_291_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_261_291_Open_Text">
								<span style="COLOR: #000000">{ <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />　　　　 </span>
								<span style="COLOR: #0000ff">return</span>
								<span style="COLOR: #000000"> successor; <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />　　 }</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />
								<br />
								<img id="Codehighlighter1_338_340_Open_Image" onclick="this.style.display='none'; Codehighlighter1_338_340_Open_Text.style.display='none'; Codehighlighter1_338_340_Closed_Image.style.display='inline'; Codehighlighter1_338_340_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_338_340_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_338_340_Closed_Text.style.display='none'; Codehighlighter1_338_340_Open_Image.style.display='inline'; Codehighlighter1_338_340_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />　　 </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">void</span>
						<span style="COLOR: #000000"> interpret( Context context ) </span>
						<span id="Codehighlighter1_338_340_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_338_340_Open_Text">
								<span style="COLOR: #000000">{ }</span>
						</span>
						<span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000"> <br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span>
		</div>
<img src ="http://www.blogjava.net/powerwind/aggbug/87031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:54 <a href="http://www.blogjava.net/powerwind/articles/87031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Visitor</title><link>http://www.blogjava.net/powerwind/articles/87032.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:54:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87032.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87032.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87032.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87032.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87032.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Visitor</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/05（转载请保留）</p>
		<p align="center">
				<a href="http://www.jdon.com/mybook/index.htm" target="_blank">
						<strong>
								<font color="#002c99">模式实战书籍《Java实用系统开发指南》</font>
						</strong>
				</a>
		</p>
		<p>
				<b>Visitor访问者模式定义</b>
				<br />作用于某个对象群中各个对象的操作. 它可以使你在不改变这些对象本身的情况下,定义作用于这些对象的新操作.</p>
		<p>在Java中,Visitor模式实际上是分离了collection结构中的元素和对这些元素进行操作的行为.</p>
		<p>
				<b>为何使用Visitor?</b>
				<br />Java的Collection(包括Vector和Hashtable)是我们最经常使用的技术,可是Collection好象是个黑色大染缸,本来有各种鲜明类型特征的对象一旦放入后,再取出时,这些类型就消失了.那么我们势必要用If来判断,如:</p>
		<p>
				<br />Iterator iterator = collection.iterator()<br />while (iterator.hasNext()) {<br />　　 Object o = iterator.next();<br />　　 if (o instanceof Collection)<br />　　 　　 messyPrintCollection((Collection)o);<br />　　 else if (o instanceof String)<br />　　 　　 System.out.println("'"+o.toString()+"'");<br />　　 else if (o instanceof Float)<br />　　 　　 System.out.println(o.toString()+"f");<br />　　 else<br />　　 　　 System.out.println(o.toString());<br />}<br />在上例中,我们使用了 instanceof来判断 o的类型.</p>
		<p>很显然,这样做的缺点代码If else if 很繁琐.我们就可以使用Visitor模式解决它.</p>
		<p>
				<b>如何使用Visitor?</b>
				<br />针对上例,定义接口叫Visitable,用来定义一个Accept操作,也就是说让Collection每个元素具备可访问性.</p>
		<p>被访问者是我们Collection的每个元素Element,我们要为这些Element定义一个可以接受访问的接口(访问和被访问是互动的,只有访问者,被访问者如果表示不欢迎,访问者就不能访问),取名为Visitable，也可取名为Element。</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public interface Visitable<br />{<br />　　 public void accept(Visitor visitor);<br />}</td>
						</tr>
				</tbody>
		</table>
		<p>被访问的具体元素继承这个新的接口Visitable：</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class StringElement implements Visitable<br />{<br />　　 private String value;<br />　　 public StringElement(String string) {<br />　　 　　 value = string;<br />　　 }</p>
										<p>　　 public String getValue(){<br />　　 　　 return value;<br />　　 }</p>
										<p>
												<br />　　 //定义accept的具体内容 这里是很简单的一句调用<br />　　 public void accept(Visitor visitor) {<br />　　 　　 visitor.visitString(this);<br />　　 }<br />}</p>
										<p>
												<br />
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>上面是被访问者是字符串类型，下面再建立一个Float类型的：</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class FloatElement implements Visitable<br />{<br />　　 private Float value;<br />　　 public FloatElement(Float value) {<br />　　 　　 this.value = value;<br />　　 }</p>
										<p>　　 public Float getValue(){<br />　　 　　 return value;<br />　　 }</p>
										<p>
												<br />　　 //定义accept的具体内容 这里是很简单的一句调用<br />　　 public void accept(Visitor visitor) {<br />　　 　　 visitor.visitFloat(this);<br />　　 }<br />}</p>
										<p>
												<br />
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>我们设计一个接口visitor访问者，在这个接口中,有一些访问操作，这些访问操作是专门访问对象集合Collection中有可能的所有类，目前我们假定有三个行为：访问对象集合中的字符串类型；访问对象集合中的Float类型；访问对象集合中的对象集合类型。注意最后一个类型是集合嵌套，通过这个嵌套实现可以看出使用访问模式的一个优点。</p>
		<p>接口visitor访问者如下：</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public interface Visitor<br />{<br /><br />　　 public void visitString(StringElement stringE);<br />　　 public void visitFloat(FloatElement floatE);<br />　　 public void visitCollection(Collection collection); <br /><br />}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>访问者的实现:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class ConcreteVisitor implements Visitor<br />{<br />　　 //在本方法中,我们实现了对Collection的元素的成功访问<br />　　 public void visitCollection(Collection collection) {<br />　　 　　 Iterator iterator = collection.iterator()<br />　　 　　 while (iterator.hasNext()) {<br />　　 　　 　　 Object o = iterator.next();<br />　　 　　 　　 if (o instanceof Visitable)<br />　　 　　 　　 　　 ((Visitable)o).accept(this);<br />　　 　　 } <br />　　 ｝</p>
										<p>　　 public void visitString(StringElement stringE) {<br />　　 　　 System.out.println("'"+stringE.getValue()+"'");<br />　　 } <br />　　 public void visitFloat(FloatElement floatE){<br />　　 　　 System.out.println(floatE.getValue().toString()+"f");<br />　　 } </p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>在上面的visitCollection我们实现了对Collection每个元素访问,只使用了一个判断语句,只要判断其是否可以访问.</p>
		<p>StringElement只是一个实现，可以拓展为更多的实现，整个核心奥妙在accept方法中，在遍历Collection时，通过相应的accept方法调用具体类型的被访问者。这一步确定了被访问者类型，</p>
		<p>如果是StringElement，而StringElement则回调访问者的visiteString方法，这一步实现了行为操作方法。</p>
		<p>客户端代码：</p>
		<table cellspacing="2" cellpadding="2" width="80%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>Visitor visitor = new ConcreteVisitor();<br /><br />StringElement stringE = new StringElement("I am a String");<br />visitor.visitString(stringE);</p>
										<p>Collection list = new ArrayList();<br />list.add(new StringElement("I am a String1")); <br />list.add(new StringElement("I am a String2")); <br />list.add(new FloatElement(new Float(12))); <br />list.add(new StringElement("I am a String3")); <br />visitor.visitCollection(list);</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>客户端代码中的list对象集合中放置了多种数据类型，对对象集合中的访问不必象一开始那样，使用instance of逐个判断，而是通过访问者模式巧妙实现了。</p>
		<p>至此,我们完成了Visitor模式基本结构.</p>
		<p>
				<b>使用Visitor模式的前提</b>
				<br />使用访问者模式是对象群结构中(Collection) 中的对象类型很少改变。</p>
		<p>在两个接口Visitor和Visitable中,确保Visitable很少变化,也就是说，确保不能老有新的Element元素类型加进来，可以变化的是访问者行为或操作，也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便.</p>
		<p>如果对象集合中的对象集合经常有变化, 那么不但Visitor实现要变化，Visistable也要增加相应行为，GOF建议是,不如在这些对象类中直接逐个定义操作，无需使用访问者设计模式。</p>
		<p>但是在Java中，Java的Reflect技术解决了这个问题，因此结合reflect反射机制，可以使得访问者模式适用范围更广了。</p>
		<p>Reflect技术是在运行期间动态获取对象类型和方法的一种技术,具体实现参考Javaworld的<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip98.html" target="_blank"><font color="#002c99">英文原文</font></a>.<br /></p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:54 <a href="http://www.blogjava.net/powerwind/articles/87032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Strategy(策略)</title><link>http://www.blogjava.net/powerwind/articles/87027.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:52:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87027.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87027.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87027.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87027.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Strategy(策略)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/03/30</p>
		<p align="center">
				<a href="http://www.jdon.com/mybook/index.htm" target="_blank">
						<strong>
								<font color="#002c99">模式实战书籍《Java实用系统开发指南》</font>
						</strong>
				</a>
		</p>
		<p>Strategy策略模式是属于设计模式中 对象行为型模式,主要是定义一系列的算法,把这些算法一个个封装成单独的类.</p>
		<p>Stratrgy应用比较广泛,比如, 公司经营业务变化图, 可能有两种实现方式,一个是线条曲线,一个是框图(bar),这是两种算法,可以使用Strategy实现.</p>
		<p>这里以字符串替代为例, 有一个文件,我们需要读取后,希望替代其中相应的变量,然后输出.关于替代其中变量的方法可能有多种方法,这取决于用户的要求,所以我们要准备几套变量字符替代方案.</p>
		<p>
				<img height="323" src="http://www.jdon.com/designpatterns/images/Strategy.jpg" width="443" />
		</p>
		<p> </p>
		<p>首先,我们建立一个抽象类RepTempRule 定义一些公用变量和方法:</p>
		<table bordercolor="#cccccc" cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public abstract class RepTempRule{<br /><br />protected String oldString="";<br />public void setOldString(String oldString){<br />　　this.oldString=oldString; <br />}<br /><br />protected String newString="";<br />public String getNewString(){<br />　　return newString;<br />}<br /><br /><br /><br />public abstract void replace() throws Exception;<br /><br /><br />}</td>
						</tr>
				</tbody>
		</table>
		<p>在RepTempRule中 有一个抽象方法abstract需要继承明确,这个replace里其实是替代的具体方法.<br />我们现在有两个字符替代方案,<br />1.将文本中aaa替代成bbb;<br />2.将文本中aaa替代成ccc;<br /><br />对应的类分别是RepTempRuleOne RepTempRuleTwo</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class RepTempRuleOne extends RepTempRule{<br /><br /><br />public void replace() throws Exception{ <br /><br />　　//replaceFirst是jdk1.4新特性 <br />　　newString=oldString.replaceFirst("aaa", "bbbb") <br />　　System.out.println("this is replace one");<br />　　 <br />}<br /><br /><br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class RepTempRuleTwo extends RepTempRule{<br /><br /><br />public void replace() throws Exception{ <br /><br />　　newString=oldString.replaceFirst("aaa", "ccc") <br />　　System.out.println("this is replace Two");<br />　　 <br />}<br /><br /><br />}</td>
						</tr>
				</tbody>
		</table>
		<p>第二步：我们要建立一个算法解决类，用来提供客户端可以自由选择算法。</p>
		<table width="80%" border="1">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class RepTempRuleSolve { 
<p>　　private RepTempRule strategy;</p><p>　　public RepTempRuleSolve(RepTempRule rule){<br />　　　　this.strategy=rule;<br />　　}</p><p>　　public String getNewContext(Site site,String oldString) {<br />　　　　return strategy.replace(site,oldString);<br />　　}</p><p>　　public void changeAlgorithm(RepTempRule newAlgorithm) {<br />　　　　strategy = newAlgorithm;<br />　　}</p><p>}</p></td>
						</tr>
				</tbody>
		</table>
		<p> </p>
		<p> </p>
		<p>调用如下:</p>
		<table cellspacing="3" cellpadding="3" width="100%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class test{</p>
										<p>......</p>
										<p>　　public void testReplace(){</p>
										<p>　　//使用第一套替代方案<br />　　RepTempRuleSolve solver=new RepTempRuleSolve(new RepTempRuleSimple());<br />　　solver.getNewContext(site,context); </p>
										<p>　　//使用第二套</p>
										<p>　　solver=new RepTempRuleSolve(new RepTempRuleTwo());<br />　　solver.getNewContext(site,context); </p>
										<p>
										</p>
										<p>　　}</p>
										<p>.....</p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>我们达到了在运行期间，可以自由切换算法的目的。</p>
		<p>实际整个Strategy的核心部分就是抽象类的使用,使用Strategy模式可以在用户需要变化时,修改量很少,而且快速.</p>
		<p>Strategy和Factory有一定的类似,Strategy相对简单容易理解,并且可以在运行时刻自由切换。Factory重点是用来创建对象。</p>
		<p>Strategy适合下列场合:</p>
		<p>1.以不同的格式保存文件;</p>
		<p>2.以不同的算法压缩文件;</p>
		<p>3.以不同的算法截获图象;</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:52 <a href="http://www.blogjava.net/powerwind/articles/87027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Mediator(中介者)</title><link>http://www.blogjava.net/powerwind/articles/87028.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:52:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87028.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87028.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87028.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87028.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87028.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Mediator(中介者)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/05</p>
		<p align="center">
				<a href="http://www.jdon.com/mybook/index.htm" target="_blank">
						<strong>
								<font color="#002c99">模式实战书籍《Java实用系统开发指南》</font>
						</strong>
				</a>
		</p>
		<p>Mediator中介者模式定义:<br />用一个中介对象来封装一系列关于对象交互行为.</p>
		<p>为何使用Mediator?<br />各个对象之间的交互操作非常多;每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉及到修改很多其他对象的行为,如果使用Mediator模式,可以使各个对象间的耦合松散,只需关心和 Mediator的关系,使多对多的关系变成了一对多的关系,可以降低系统的复杂性,提高可修改扩展性.</p>
		<p>如何使用?</p>
		<p>首先 有一个接口,用来定义成员对象之间的交互联系方式:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public interface Mediator { }</td>
						</tr>
				</tbody>
		</table>
		<p>Meiator具体实现,真正实现交互操作的内容:</p>
		<table cellspacing="3" cellpadding="3" width="95%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class ConcreteMediator implements Mediator {</p>
										<p>　　 //假设当前有两个成员.<br />　　 private ConcreteColleague1 colleague1 = new ConcreteColleague1(); <br />　　 private ConcreteColleague2 colleague2 = new ConcreteColleague2(); </p>
										<p>　　 ... </p>
										<p>} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>再看看另外一个参与者:成员,因为是交互行为,都需要双方提供一些共同接口,这种要求在Visitor Observer等模式中都是相同的.</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Colleague {<br />　　 private Mediator mediator;<br />　　 public Mediator getMediator() { <br />　　 　　 return mediator;<br />　　 }<br /><br />　　 public void setMediator( Mediator mediator ) { <br />　　 　　 this.mediator = mediator; <br />　　 }<br />}</p>
										<p>public class ConcreteColleague1 { }</p>
										<p>public class ConcreteColleague2 { }</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>每个成员都必须知道Mediator,并且和 Mediator联系,而不是和其他成员联系.</p>
		<p>至此,Mediator模式框架完成,可以发现Mediator模式规定不是很多,大体框架也比较简单,但实际使用起来就非常灵活.</p>
		<p>Mediator模式在事件驱动类应用中比较多,例如界面设计GUI.;聊天,消息传递等,在聊天应用中,需要有一个MessageMediator,专门负责request/reponse之间任务的调节.</p>
		<p>MVC是J2EE的一个基本模式,View Controller是一种Mediator,它是Jsp和服务器上应用程序间的Mediator.<br /></p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87028.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:52 <a href="http://www.blogjava.net/powerwind/articles/87028.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Chain of Responsibility(职责链)</title><link>http://www.blogjava.net/powerwind/articles/87024.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:51:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87024.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87024.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87024.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87024.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Chain of Responsibility(职责链)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/04/21(转载请保留)</p>
		<p>
				<b>Chain of Responsibility定义</b>
				<br />Chain of Responsibility(CoR) 是用一系列类(classes)试图处理一个请求request,这些类之间是一个松散的耦合,唯一共同点是在他们之间传递request. 也就是说，来了一个请求，A类先处理，如果没有处理，就传递到B类处理，如果没有处理，就传递到C类处理，就这样象一个链条(chain)一样传递下去。</p>
		<p>
				<b>如何使用?</b>
				<br />虽然这一段是如何使用CoR,但是也是演示什么是CoR.</p>
		<p>有一个Handler接口:</p>
		<p>public interface Handler{<br />　　public void handleRequest();<br />}</p>
		<p>这是一个处理request的事例， 如果有多种request,比如 请求帮助 请求打印 或请求格式化：<br /><br />最先想到的解决方案是：在接口中增加多个请求：<br />public interface Handler{<br />　　public void handleHelp();<br />　　public void handlePrint();<br />　　public void handleFormat();</p>
		<p>}</p>
		<p>具体是一段实现接口Handler代码：<br />public class ConcreteHandler implements Handler{<br />　　private Handler successor;</p>
		<p>　　public ConcreteHandler(Handler successor){<br />　　this.successor=successor;<br />}</p>
		<p>　　public void handleHelp(){<br />　　　　//具体处理请求Help的代码<br />　　　　...<br />　　}</p>
		<p>　　public void handlePrint(){<br />　　　　//如果是print 转去处理Print<br />　　　　successor.handlePrint();<br />　　}<br />　　public void handleFormat(){<br />　　　　//如果是Format 转去处理format<br />　　　　successor.handleFormat();<br />　　}</p>
		<p>}<br />一共有三个这样的具体实现类，上面是处理help,还有处理Print 处理Format这大概是我们最常用的编程思路。</p>
		<p>虽然思路简单明了，但是有一个扩展问题，如果我们需要再增加一个请求request种类,需要修改接口及其每一个实现。</p>
		<p>第二方案:将每种request都变成一个接口，因此我们有以下代码 ：</p>
		<p>public interface HelpHandler{<br />　　public void handleHelp();<br />}</p>
		<p>public interface PrintHandler{<br />　　public void handlePrint();<br />}</p>
		<p>public interface FormatHandler{<br />　　public void handleFormat();<br />}</p>
		<p>public class ConcreteHandler<br />　　implements HelpHandler,PrintHandler,FormatHandlet{<br />　　private HelpHandler helpSuccessor;<br />　　private PrintHandler printSuccessor;<br />　　private FormatHandler formatSuccessor;</p>
		<p>　　public ConcreteHandler(HelpHandler helpSuccessor,PrintHandler printSuccessor,FormatHandler 　　　　　　　　　　　　formatSuccessor)<br />　　{<br />　　　　this.helpSuccessor=helpSuccessor;<br />　　　　this.printSuccessor=printSuccessor;<br />　　　　this.formatSuccessor=formatSuccessor;<br />　　}</p>
		<p>　　public void handleHelp(){<br />　　　　.......<br />　　}</p>
		<p>　　public void handlePrint(){this.printSuccessor=printSuccessor;}</p>
		<p>　　public void handleFormat(){this.formatSuccessor=formatSuccessor;}</p>
		<p>}</p>
		<p>这个办法在增加新的请求request情况下，只是节省了接口的修改量，接口实现ConcreteHandler还需要修改。而且代码显然不简单美丽。</p>
		<p>解决方案3: 在Handler接口中只使用一个参数化方法：<br />public interface Handler{<br />　　public void handleRequest(String request);<br />}<br />那么Handler实现代码如下：<br />public class ConcreteHandler implements Handler{<br />　　private Handler successor;</p>
		<p>　　public ConcreteHandler(Handler successor){<br />　　　　this.successor=successor;<br />　　}</p>
		<p>　　public void handleRequest(String request){<br />　　　　if (request.equals("Help")){<br />　　　　　　//这里是处理Help的具体代码<br />　　　　}else<br />　　　　　　//传递到下一个<br />　　　　　　successor.handle(request);</p>
		<p>　　　　}<br />　　}</p>
		<p>}<br /></p>
		<p>这里先假设request是String类型，如果不是怎么办？当然我们可以创建一个专门类Request<br /></p>
		<p>最后解决方案:接口Handler的代码如下：<br />public interface Handler{<br />　　public void handleRequest(Request request);<br />}<br />Request类的定义:<br />public class Request{<br />　　private String type;<br /><br />　　public Request(String type){this.type=type;}</p>
		<p>　　public String getType(){return type;}</p>
		<p>　　public void execute(){<br />　　　　//request真正具体行为代码<br />　　}<br />}<br />那么Handler实现代码如下：<br />public class ConcreteHandler implements Handler{<br />　　private Handler successor;</p>
		<p>　　public ConcreteHandler(Handler successor){<br />　　　　this.successor=successor;<br />　　}</p>
		<p>　　public void handleRequest(Request request){<br />　　　　if (request instanceof HelpRequest){<br />　　　　　　//这里是处理Help的具体代码<br />　　　　}else if (request instanceof PrintRequst){<br />　　　　　　request.execute();<br />　　　　}else<br />　　　　　　//传递到下一个<br />　　　　　　successor.handle(request);</p>
		<p>　　　　}<br />　　}</p>
		<p>}</p>
		<p>这个解决方案就是CoR, 在一个链上,都有相应职责的类,因此叫<b>Chain of Responsibility</b>.</p>
		<p>
				<strong>CoR的优点：</strong>
				<br />因为无法预知来自外界（客户端）的请求是属于哪种类型，每个类如果碰到它不能处理的请求只要放弃就可以。</p>
		<p>缺点是效率低，因为一个请求的完成可能要遍历到最后才可能完成，当然也可以用树的概念优化。 在Java AWT1.0中，对于鼠标按键事情的处理就是使用CoR,到Java.1.1以后，就使用Observer代替CoR</p>
		<p>扩展性差，因为在CoR中，一定要有一个统一的接口Handler.局限性就在这里。</p>
		<p>
				<strong>与Command模式区别：</strong>
		</p>
		<p>Command 模式需要事先协商客户端和服务器端的调用关系，比如 1 代表 start 2 代表 move 等，这些 都是封装在 request 中，到达服务器端再分解。</p>
		<p>CoR 模式就无需这种事先约定，服务器端可以使用 CoR 模式进行客户端请求的猜测，一个个猜测 试验。 </p>
		<p>
				<br />
		</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:51 <a href="http://www.blogjava.net/powerwind/articles/87024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Command</title><link>http://www.blogjava.net/powerwind/articles/87025.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:51:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87025.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87025.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87025.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87025.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Command</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/4/23/（转载请保留）</p>
		<p align="center">
				<a href="http://www.jdon.com/mybook/index.htm" target="_blank">
						<strong>
								<font color="#002c99">模式实战书籍《Java实用系统开发指南》</font>
						</strong>
				</a>
		</p>
		<p>Command模式是最让我疑惑的一个模式,我在阅读了很多代码后,才感觉隐约掌握其大概原理,我认为理解设计模式最主要是掌握起原理构造,这样才对自己实际编程有指导作用.Command模式实际上不是个很具体,规定很多的模式,正是这个灵活性,让人有些confuse.</p>
		<p>
				<b>Command定义</b>
				<br />n 将来自客户端的请求传入一个对象，无需了解这个请求激活的 动作或有关接受这个请求的处理细节。</p>
		<p>这是一种两台机器之间通讯联系性质的模式，类似传统过程语 言的 CallBack功能。 </p>
		<p>
				<strong>优点：<br /></strong>解耦了发送者和接受者之间联系。 发送者调用一个操作，接受者接受请求执行相应的动作，因为使用Command模式解耦，发送者无需知道接受者任何接口。</p>
		<p>不少Command模式的代码都是针对图形界面的,它实际就是菜单命令,我们在一个下拉菜单选择一个命令时,然后会执行一些动作.</p>
		<p>将这些命令封装成在一个类中,然后用户(调用者)再对这个类进行操作,这就是Command模式,换句话说,本来用户(调用者)是直接调用这些命令的,如菜单上打开文档(调用者),就直接指向打开文档的代码,使用Command模式,就是在这两者之间增加一个中间者,将这种直接关系拗断,同时两者之间都隔离,基本没有关系了.</p>
		<p>显然这样做的好处是符合封装的特性,降低耦合度,Command是将对行为进行封装的典型模式,Factory是将创建进行封装的模式,<br />从Command模式,我也发现设计模式一个"通病":好象喜欢将简单的问题复杂化, 喜欢在不同类中增加第三者,当然这样做有利于代码的健壮性 可维护性 还有复用性.</p>
		<p>
				<b>如何使用?</b>
				<br />具体的Command模式代码各式各样,因为如何封装命令,不同系统,有不同的做法.下面事例是将命令封装在一个Collection的List中,任何对象一旦加入List中,实际上装入了一个封闭的黑盒中,对象的特性消失了,只有取出时,才有可能模糊的分辨出:</p>典型的Command模式需要有一个接口.接口中有一个统一的方法,这就是"将命令/请求封装为对象":<br /><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc">public interface Command {<br />　　public abstract void execute ( );<br />}</td></tr></tbody></table><br />具体不同命令/请求代码是实现接口Command,下面有三个具体命令<br /><table cellspacing="3" cellpadding="3" width="80%" bgcolor="#cccccc" border="0"><tbody><tr><td>public class Engineer implements Command {<br /><br />　　public void execute( ) {<br />　　　　//do Engineer's command<br />　　}<br />} 
<p>public class Programmer implements Command {<br /><br />　　public void execute( ) {<br />　　　　//do programmer's command<br />　　}<br />}</p><p>public class Politician implements Command {<br /><br />　　public void execute( ) {<br />　　　　//do Politician's command<br />　　}<br />}</p></td></tr></tbody></table><br /><p>按照通常做法,我们就可以直接调用这三个Command,但是使用Command模式,我们要将他们封装起来,扔到黑盒子List里去:<br /></p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc"><p>public class producer{<br />　　public static List produceRequests() {<br />　　　　List queue = new ArrayList();<br />　　　　queue.add( new DomesticEngineer() );<br />　　　　queue.add( new Politician() );<br />　　　　queue.add( new Programmer() );<br />　　　　return queue; <br />　　}</p><p>}</p><p></p></td></tr></tbody></table><p>这三个命令进入List中后,已经失去了其外表特征,以后再取出,也可能无法分辨出谁是Engineer 谁是Programmer了,看下面客户端如何调用Command模式:<br /></p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc"><p>public class TestCommand {<br />　　public static void main(String[] args) {<br />　　　　<br />　　　　List queue = Producer.produceRequests();<br />　　　　for (Iterator it = queue.iterator(); it.hasNext(); )<br />　　　　　　<br />　//客户端直接调用execute方法，无需知道被调用者的其它更多类的方法名。<br />　　　　　　　　((Command)it.next()).execute();<br />　　</p><p>　　}<br />} </p></td></tr></tbody></table><p>由此可见,调用者基本只和接口打交道,不合具体实现交互,这也体现了一个原则,面向接口编程,这样,以后增加第四个具体命令时,就不必修改调用者TestCommand中的代码了.<br /><br />理解了上面的代码的核心原理,在使用中,就应该各人有自己方法了,特别是在如何分离调用者和具体命令上,有很多实现方法,上面的代码是使用"从List过一遍"的做法.这种做法只是为了演示.<br /></p><p>使用Command模式的一个好理由还因为它能实现Undo功能.每个具体命令都可以记住它刚刚执行的动作,并且在需要时恢复.</p><p>Command模式在界面设计中应用广泛.Java的Swing中菜单命令都是使用Command模式,由于Java在界面设计的性能上还有欠缺,因此界面设计具体代码我们就不讨论,网络上有很多这样的示例.</p><p>参考:<br /><a href="http://www.patterndepot.com/put/8/command.pdf" target="_blank"><font color="#002c99">http://www.patterndepot.com/put/8/command.pdf </font></a></p><p><a href="http://www.javaworld.com/javaworld/javatips/jw-javatip68.html" target="_blank"><font color="#002c99">http://www.javaworld.com/javaworld/javatips/jw-javatip68.html</font></a></p><p>设计模式如何在具体项目中应用见<a href="http://www.jdon.com/mybook/index.htm" target="_blank"><font color="#002c99">《Java实用系统开发指南》</font></a></p><p> </p><!-- #EndEditable --><img src ="http://www.blogjava.net/powerwind/aggbug/87025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:51 <a href="http://www.blogjava.net/powerwind/articles/87025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之State</title><link>http://www.blogjava.net/powerwind/articles/87026.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:51:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87026.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87026.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87026.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87026.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87026.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之State</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/4/6/</p>
		<p align="center">
				<a href="http://www.jdon.com/mybook/index.htm" target="_blank">
						<strong>
								<font color="#002c99">模式实战书籍《Java实用系统开发指南》</font>
						</strong>
				</a>
		</p>
		<p>
				<i>
						<b>State模式的定义</b>
				</i>: 不同的状态,不同的行为;或者说,每个状态有着相应的行为.</p>
		<p>
				<i>
						<b>何时使用</b>
				</i>?<br />State模式在实际使用中比较多,适合"状态的切换".因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了.</p>
		<p>不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在数据库系统中出现频率比较高,我们经常会在一个数据表的尾部,加上property属性含义的字段,用以标识记录中一些特殊性质的记录,这种属性的改变(切换)又是随时可能发生的,就有可能要使用State.<br /></p>
		<p>
				<i>
						<b>是否使用?</b>
				</i>
				<br />在实际使用,类似开关一样的状态切换是很多的,但有时并不是那么明显,取决于你的经验和对系统的理解深度.</p>
		<p>这里要阐述的是"开关切换状态" 和" 一般的状态判断"是有一些区别的, " 一般的状态判断"也是有 if..elseif结构,例如:</p>
		<p>　　　　if (which==1) state="hello";<br />　　　　else if (which==2) state="hi";<br />　　　　else if (which==3) state="bye";<br /></p>
		<p>这是一个 " 一般的状态判断",state值的不同是根据which变量来决定的,which和state没有关系.如果改成:</p>
		<p>　　　　if (state.euqals("bye")) state="hello";<br />　　　　else if (state.euqals("hello")) state="hi";<br />　　　　else if (state.euqals("hi")) state="bye";<br /></p>
		<p>这就是 "开关切换状态",是将state的状态从"hello"切换到"hi",再切换到""bye";在切换到"hello",好象一个旋转开关,这种状态改变就可以使用State模式了.</p>
		<p>如果单纯有上面一种将"hello"--&gt;"hi"--&gt;"bye"--&gt;"hello"这一个方向切换,也不一定需要使用State模式,因为State模式会建立很多子类,复杂化,但是如果又发生另外一个行为:将上面的切换方向反过来切换,或者需要任意切换,就需要State了.</p>
		<p>请看下例:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Context{</p>
										<p>　　private Color state=null;</p>
										<p>　　public void push(){</p>
										<p>　　　　//如果当前red状态 就切换到blue<br />　　　　if (state==Color.red) state=Color.blue;<br /><br />　　　　//如果当前blue状态 就切换到green<br />　　　　else if (state==Color.blue) state=Color.green;<br /><br />　　　　//如果当前black状态 就切换到red<br />　　　　else if (state==Color.black) state=Color.red;<br /><br />　　　　//如果当前green状态 就切换到black<br />　　　　else if (state==Color.green) state=Color.black;<br />　　　　<br />　　　　Sample sample=new Sample(state);<br />　　　　sample.operate();<br />　　}</p>
										<p>　　public void pull(){<br /><br />　　　　//与push状态切换正好相反</p>
										<p>　　　　if (state==Color.green) state=Color.blue;<br />　　　　else if (state==Color.black) state=Color.green;<br />　　　　else if (state==Color.blue) state=Color.red;<br />　　　　else if (state==Color.red) state=Color.black;<br /><br />　　　　Sample2 sample2=new Sample2(state);<br />　　　　sample2.operate(); <br />　　}</p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>在上例中,我们有两个动作push推和pull拉,这两个开关动作,改变了Context颜色,至此,我们就需要使用State模式优化它.</p>
		<p>另外注意:但就上例,state的变化,只是简单的颜色赋值,这个具体行为是很简单的,State适合巨大的具体行为,因此在,就本例,实际使用中也不一定非要使用State模式,这会增加子类的数目,简单的变复杂.</p>
		<p>例如: 银行帐户, 经常会在Open 状态和Close状态间转换.</p>
		<p>例如: 经典的TcpConnection, Tcp的状态有创建 侦听 关闭三个,并且反复转换,其创建 侦听 关闭的具体行为不是简单一两句就能完成的,适合使用State</p>
		<p>例如:信箱POP帐号, 会有四种状态, start HaveUsername Authorized quit,每个状态对应的行为应该是比较大的.适合使用State</p>
		<p>例如:在工具箱挑选不同工具,可以看成在不同工具中切换,适合使用State.如 具体绘图程序,用户可以选择不同工具绘制方框 直线 曲线,这种状态切换可以使用State.</p>
		<p>
				<i>
						<b>如何使用</b>
				</i>
				<br />State需要两种类型实体参与:</p>
		<p>1.state manager 状态管理器 ,就是开关 ,如上面例子的Context实际就是一个state manager, 在state manager中有对状态的切换动作.<br />2.用抽象类或接口实现的父类,,不同状态就是继承这个父类的不同子类.</p>
		<p>以上面的Context为例.我们要修改它,建立两个类型的实体.<br /><b>第一步: 首先建立一个父类:</b></p>
		<table cellspacing="3" cellpadding="3" width="80%" bgcolor="#ffffff" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public abstract class State{</p>
										<p>　　public abstract void handlepush(Context c);<br />　　public abstract void handlepull(Context c);<br />　　public abstract void getcolor();</p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>父类中的方法要对应state manager中的开关行为,在state manager中 本例就是Context中,有两个开关动作push推和pull拉.那么在状态父类中就要有具体处理这两个动作:handlepush() handlepull(); 同时还需要一个获取push或pull结果的方法getcolor()</p>
		<p>下面是具体子类的实现:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class BlueState extends State{</p>
										<p>　　public void handlepush(Context c){<br />　　　　 //根据push方法"如果是blue状态的切换到green" ;<br />　　　　 c.setState(new GreenState());</p>
										<p>　　}<br />　　public void handlepull(Context c){</p>
										<p>　　　　 //根据pull方法"如果是blue状态的切换到red" ;<br />　　　　c.setState(new RedState());</p>
										<p>　　}</p>
										<p>　　public abstract void getcolor(){ return (Color.blue)}</p>
										<p>}</p>
										<p> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>同样 其他状态的子类实现如blue一样.</p>
		<p>
				<b>第二步: 要重新改写State manager 也就是本例的Context:</b>
		</p>
		<table cellspacing="3" cellpadding="3" width="97%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Context{</p>
										<p>　　private Sate state=null; //我们将原来的 Color state 改成了新建的State state;</p>
										<p>　　//setState是用来改变state的状态 使用setState实现状态的切换<br />　　pulic void setState(State state){<br /><br />　　　　this.state=state;</p>
										<p>　　}</p>
										<p>　　public void push(){</p>
										<p>　　　　//状态的切换的细节部分,在本例中是颜色的变化,已经封装在子类的handlepush中实现,这里无需关心<br />　　　　state.handlepush(this);<br />　　　　<br />　　　　//因为sample要使用state中的一个切换结果,使用getColor()<br />　　　　Sample sample=new Sample(state.getColor());<br />　　　　sample.operate(); </p>
										<p>　　}</p>
										<p> </p>
										<p>　　public void pull(){</p>
										<p>　　　　state.handlepull(this);<br />　　　　<br />　　　　Sample2 sample2=new Sample2(state.getColor());<br />　　　　sample2.operate(); </p>
										<p>　　}</p>
										<p>}</p>
										<p> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>至此,我们也就实现了State的refactorying过程.</p>
		<p>以上只是相当简单的一个实例,在实际应用中,handlepush或handelpull的处理是复杂的.</p>
		<p>状态模式优点：<br />（1） 封装转换过程，也就是转换规则<br />（2） 枚举可能的状态，因此，需要事先确定状态种类。<br /></p>
		<p>状态模式可以允许客户端改变状态的转换行为，而状态机则是能够自动改变状态，状态机是一个比较独立的而且复杂的机制，具体可参考一个状态机开源项目：<a href="http://sourceforge.net/projects/smframework/" target="_blank"><font color="#002c99">http://sourceforge.net/projects/smframework/</font></a></p>
		<p>状态模式在工作流或游戏等各种系统中有大量使用，甚至是这些系统的核心功能设计，例如政府OA中，一个批文的状态有多种：未办；正在办理；正在批示；正在审核；已经完成等各种状态，使用状态机可以封装这个状态的变化规则，从而达到扩充状态时，不必涉及到状态的使用者。</p>
		<p>在网络游戏中，一个游戏活动存在开始；开玩；正在玩；输赢等各种状态，使用状态模式就可以实现游戏状态的总控，而游戏状态决定了游戏的各个方面，使用状态模式可以对整个游戏架构功能实现起到决定的主导作用。</p>
		<p>
				<strong>状态模式实质</strong>：<br />使用状态模式前，客户端外界需要介入改变状态，而状态改变的实现是琐碎或复杂的。</p>
		<p>使用状态模式后，客户端外界可以直接使用事件Event实现，根本不必关心该事件导致如何状态变化，这些是由状态机等内部实现。</p>
		<p>这是一种Event-condition-State，状态模式封装了condition-State部分。</p>
		<p>每个状态形成一个子类，每个状态只关心它的下一个可能状态，从而无形中形成了状态转换的规则。如果新的状态加入，只涉及它的前一个状态修改和定义。</p>
		<p>状态转换有几个方法实现：一个在每个状态实现next()，指定下一个状态；还有一种方法，设定一个StateOwner，在StateOwner设定stateEnter状态进入和stateExit状态退出行为。</p>
		<p>状态从一个方面说明了流程，流程是随时间而改变，状态是截取流程某个时间片。</p>
		<p>
				<br />相关文章：</p>
		<p>
				<a href="http://www.jdon.com/jive/article.jsp?forum=91&amp;thread=10981" target="_blank">
						<font color="#002c99">从工作流状态机实践中总结状态模式使用心得</font>
				</a>
				<br />
		</p>
		<p>参考资源:<br /><a href="http://www.research.umbc.edu/%7Etarr/cs491/lectures/StateStrategy.pdf" target="_blank"><font color="#002c99">the State and Stategy</font></a><br /><a href="http://www.javaworld.com/javaworld/jw-08-1997/jw-08-stated.html" target="_blank"><font color="#002c99">How to implement state-dependent behavior</font></a><br /><a href="http://www.patterndepot.com/put/8/state.pdf" target="_blank"><font color="#002c99">The state patterns</font></a></p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87026.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:51 <a href="http://www.blogjava.net/powerwind/articles/87026.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Observer</title><link>http://www.blogjava.net/powerwind/articles/87022.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:50:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87022.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87022.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87022.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Observer</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/3/16</p>
		<p>Java深入到一定程度,就不可避免的碰到设计模式(design pattern)这一概念,了解设计模式,将使自己对java中的接口或抽象类应用有更深的理解.设计模式在java的中型系统中应用广泛,遵循一定的编程模式,才能使自己的代码便于理解,易于交流,Observer(观察者)模式是比较常用的一个模式,尤其在界面设计中应用广泛,而本站所关注的是Java在电子商务系统中应用,因此想从电子商务实例中分析Observer的应用.</p>
		<p>虽然网上商店形式多样,每个站点有自己的特色,但也有其一般的共性,单就"商品的变化,以便及时通知订户"这一点,是很多网上商店共有的模式,这一模式类似Observer patern观察者模式.</p>
		<p>具体的说,如果网上商店中商品在名称 价格等方面有变化,如果系统能自动通知会员,将是网上商店区别传统商店的一大特色.这就需要在商品product中加入Observer这样角色,以便product细节发生变化时,Observer能自动观察到这种变化,并能进行及时的update或notify动作.</p>
		<p>
				<img height="323" src="http://www.jdon.com/designpatterns/images/observer1.jpg" width="443" />
		</p>
		<p>Java的API还为为我们提供现成的Observer接口Java.util.Observer.我们只要直接使用它就可以.</p>
		<p>我们必须extends Java.util.Observer才能真正使用它:<br />1.提供Add/Delete observer的方法;<br />2.提供通知(notisfy) 所有observer的方法;<br /></p>
		<table cellspacing="3" cellpadding="3" width="80%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>//产品类 可供Jsp直接使用UseBean调用 该类主要执行产品数据库插入 更新<br />public class product extends Observable{ 
<p>　　private String name;<br />　　private float price;</p><p>　　public String getName(){ return name;}<br />　　public void setName(String name){<br />　　 this.name=name;<br />　　//设置变化点 <br />　　 setChanged();<br />　　 notifyObservers(name);</p><p>　　}　　　</p><p>　　public float getPrice(){ return price;}<br />　　public void setPrice(float price){<br />　　 this.price=price;<br />　　//设置变化点<br />　　 setChanged();<br />　　 notifyObservers(new Float(price)); </p><p>　　}<br /><br />　　//以下可以是数据库更新 插入命令.<br />　　public void saveToDb(){<br />　　.....................<br /></p><p>}</p></td>
						</tr>
				</tbody>
		</table>
		<p>
				<br />我们注意到,在product类中 的setXXX方法中,我们设置了 notify(通知)方法, 当Jsp表单调用setXXX(如何调用见我的<a href="http://www.jdon.com/idea/数据库bean.htm" target="_blank"><font color="#002c99">另外一篇文章</font></a>),实际上就触发了notisfyObservers方法,这将通知相应观察者应该采取行动了.</p>
		<p>下面看看这些观察者的代码,他们究竟采取了什么行动:</p>
		<table cellspacing="3" cellpadding="3" width="99%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>//观察者NameObserver主要用来对产品名称(name)进行观察的<br />public class NameObserver implements Observer{</p>
										<p>　　private String name=null;</p>
										<p>　　public void update(Observable obj,Object arg){<br /><br />　　　　if (arg <a href="http://www-900.ibm.com/developerWorks/java/l-leditor/index.shtml" target="_blank"><font color="#002c99">instanceof</font></a> String){</p>
										<p>　　　　 name=(String)arg;<br />　　　　 //产品名称改变值在name中<br />　　　　 System.out.println("NameObserver :name changet to "+name);</p>
										<p>　　　　}<br /></p>
										<p>　　}</p>
										<p>}</p>
										<p>//观察者PriceObserver主要用来对产品价格(price)进行观察的<br />public class PriceObserver implements Observer{</p>
										<p>　　private float price=0;</p>
										<p>　　public void update(Observable obj,Object arg){<br /><br />　　　　if (arg instanceof Float){</p>
										<p>　　　　 price=((Float)arg).floatValue();<br />　　<br />　　　　 System.out.println("PriceObserver :price changet to "+price);</p>
										<p>　　　　}<br /></p>
										<p>　　}</p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<br />Jsp中我们可以来正式执行这段观察者程序:</p>
		<table cellspacing="3" cellpadding="3" width="96%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>
												<b>&lt;jsp:useBean id="product" scope="session" class="Product" /&gt;<br />&lt;jsp:setProperty name="product" property="*" /&gt;</b>
										</p>
										<p>
												<b>&lt;jsp:useBean id="nameobs" scope="session" class="NameObserver" /&gt;<br />&lt;jsp:setProperty name="product" property="*" /&gt;</b>
										</p>
										<p>
												<b>&lt;jsp:useBean id="priceobs" scope="session" class="PriceObserver" /&gt;<br />&lt;jsp:setProperty name="product" property="*" /&gt;</b>
										</p>
										<p>&lt;%<br /><br />if (request.getParameter("save")!=null)<br />{ <br />　　product.saveToDb();<br /><br /><br />　　out.println("产品数据变动 保存! 并已经自动通知客户"); </p>
										<p>}else{<br /><br />　　//加入观察者<br />　　product.addObserver(<b>nameobs</b>);<br /><br />　　product.addObserver(<b>priceobs</b>);</p>
										<p>%&gt;</p>
										<p>　　//request.getRequestURI()是产生本jsp的程序名,就是自己调用自己<br />　　&lt;form action="&lt;%=request.getRequestURI()%&gt;" method=post&gt;</p>
										<p>　　&lt;input type=hidden name="save" value="1"&gt;<br />　　产品名称:&lt;input type=text name="name" &gt;<br />　　产品价格:&lt;input type=text name="price"&gt;<br />　　&lt;input type=submit&gt;</p>
										<p>　　&lt;/form&gt;</p>
										<p>&lt;%<br /><br />} </p>
										<p>%&gt;</p>
										<p> </p>
										<p> </p>
										<p> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>执行改Jsp程序,会出现一个表单录入界面, 需要输入产品名称 产品价格, 点按Submit后,还是执行该jsp的<br />if (request.getParameter("save")!=null)之间的代码.<br /><br /><br />由于这里使用了数据javabeans的自动赋值概念,实际程序自动执行了setName setPrice语句.你会在服务器控制台中发现下面信息::<br /><b><br />NameObserver :name changet to ?????(Jsp表单中输入的产品名称)<br /><br />PriceObserver :price changet to ???(Jsp表单中输入的产品价格);</b></p>
		<p>这说明观察者已经在行动了.!!<br />同时你会在执行jsp的浏览器端得到信息:<br /><br /><b>产品数据变动 保存! 并已经自动通知客户</b><br /><br /></p>
		<p>上文由于使用jsp概念,隐含很多自动动作,现将调用观察者的Java代码写如下:</p>
		<table cellspacing="3" cellpadding="3" width="80%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p> </p>
										<p>public class Test {</p>
										<p>　　public static void main(String args[]){</p>
										<p>Product product=new Product();<br /><br />NameObserver nameobs=new NameObserver();<br />PriceObserver priceobs=new PriceObserver();</p>
										<p>//加入观察者<br />product.addObserver(nameobs);<br />product.addObserver(priceobs);</p>
										<p>product.setName("橘子红了");<br />product.setPrice(9.22f); </p>
										<p>　　}</p>
										<p>}</p>
										<p> </p>
										<p> </p>
										<p> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>你会在发现下面信息::<br /><b><br />NameObserver :name changet to 橘子红了<br /><br />PriceObserver :price changet to 9.22</b></p>
		<p>这说明观察者在行动了.!!</p>
		<p>设计模式如何在具体项目中应用见<a href="http://www.jdon.com/mybook/index.htm" target="_blank"><font color="#002c99">《Java实用系统开发指南》</font></a></p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:50 <a href="http://www.blogjava.net/powerwind/articles/87022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Template</title><link>http://www.blogjava.net/powerwind/articles/87020.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:49:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87020.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87020.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87020.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87020.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87020.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Template</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/05</p>
		<p>Template模板模式定义:<br />定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中.</p>
		<p>使用Java的抽象类时，就经常会使用到Template模式,因此Template模式使用很普遍.而且很容易理解和使用。</p>
		<p> </p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public abstract class Benchmark<br />{<br />　　/**<br />　　* 下面操作是我们希望在子类中完成<br />　　*/<br />　　public abstract void benchmark(); 
<p>　　/**<br />　　* 重复执行benchmark次数<br />　　*/<br />　　public final long repeat (int count) {<br />　　　　if (count &lt;= 0)<br />　　　　　　return 0;<br />　　　　else {<br />　　　　　　long startTime = System.currentTimeMillis();</p><p>　　　　for (int i = 0; i &lt; count; i++) <br />　　　　　　benchmark();<br /><br />　　　　long stopTime = System.currentTimeMillis();<br />　　　　return stopTime - startTime;<br />　　}<br />}<br />}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>在上例中,我们希望重复执行benchmark()操作,但是对benchmark()的具体内容没有说明,而是延迟到其子类中描述:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class MethodBenchmark extends Benchmark<br />{<br />　　/**<br />　　* 真正定义benchmark内容<br />　　*/<br />　　public void benchmark() {<br /><br />　　　　for (int i = 0; i &lt; Integer.MAX_VALUE; i++){<br />　　　 　　System.out.printtln("i="+i);　 　　<br />　　　 }<br />　　}<br />}<br /></td>
						</tr>
				</tbody>
		</table>
		<p>至此,Template模式已经完成,是不是很简单?</p>
		<p>我们称repeat方法为模板方法， 它其中的benchmark()实现被延迟到子类MethodBenchmark中实现了，</p>
		<p>看看如何使用:</p>
		<p>Benchmark operation = new MethodBenchmark();<br />long duration = operation.repeat(Integer.parseInt(args[0].trim()));<br />System.out.println("The operation took " + duration + " milliseconds");</p>
		<p> </p>
		<p>也许你以前还疑惑抽象类有什么用,现在你应该彻底明白了吧? 至于这样做的好处,很显然啊,扩展性强,以后Benchmark内容变化,我只要再做一个继承子类就可以,不必修改其他应用代码.</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87020.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:49 <a href="http://www.blogjava.net/powerwind/articles/87020.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Memento(备忘机制)</title><link>http://www.blogjava.net/powerwind/articles/87021.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:49:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87021.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87021.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87021.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87021.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87021.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Memento(备忘机制)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/05</p>
		<p>Memento备望录模式定义:<br />memento是一个保存另外一个对象内部状态拷贝的对象.这样以后就可以将该对象恢复到原先保存的状态.</p>
		<p>Memento模式相对也比较好理解,我们看下列代码:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class Originator { <br /><br />　　 private int number; 
<p>　　private File file = null;</p><p>　　public Originator(){}</p><p>　　// 创建一个Memento<br />　　public Memento getMemento(){<br />　　　　return new Memento(this);<br />　　}</p><p>　　// 恢复到原始值<br />　　public void setMemento(Memento m){<br />　　　　 number = m.number;<br />　　　　 file = m.file;<br />　　}</p><p>}</p><p> </p></td>
						</tr>
				</tbody>
		</table>
		<p>我们再看看Memento类:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>private class Memento implements java.io.Serializable{</p>
										<p>　　private int number;</p>
										<p>　　private File file = null;</p>
										<p>　　public Memento( Originator o){</p>
										<p>　　　　number = o.number;<br />　　　　file = o.file;</p>
										<p>　　}</p>
										<p>}</p>
										<p>
												<br />
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>可见 Memento中保存了Originator中的number和file的值. 通过调用Originator中number和file值改变的话,通过调用setMemento()方法可以恢复.</p>
		<p>Memento模式的缺点是耗费大,如果内部状态很多,再保存一份,无意要浪费大量内存.</p>
		<p>
				<b>Memento模式在Jsp+Javabean中的应用</b>
				<br />在Jsp应用中,我们通常有很多表单要求用户输入,比如用户注册,需要输入姓名和Email等, 如果一些表项用户没有填写或者填写错误,我们希望在用户按"提交Submit"后,通过Jsp程序检查,发现确实有未填写项目,则在该项目下红字显示警告或错误,同时,还要显示用户刚才已经输入的表项.</p>
		<p>如下图中 First Name是用户已经输入,Last Name没有输入,我们则提示红字警告.:</p>
		<p>
				<img height="500" src="http://www.jdon.com/designpatterns/images/memento.gif" width="425" />
		</p>
		<p>这种技术的实现,就是利用了Javabean的scope="request"或scope="session"特性,也就是Memento模式.</p>
		<p>具体示例和代码见 <a href="http://www.javaworld.com/javaworld/jw-03-2000/jw-0331-ssj-forms.html" target="_blank"><font color="#002c99">JavaWorld的英文原文</font></a> , Javabean表单输入特性参见我的另外<a href="http://www.jdon.com/idea/session.htm" target="_blank"><font color="#002c99">一篇文章.</font></a></p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:49 <a href="http://www.blogjava.net/powerwind/articles/87021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Bridge</title><link>http://www.blogjava.net/powerwind/articles/87018.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:48:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87018.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87018.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87018.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87018.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Bridge</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/01</p>
		<p>
				<strong>Bridge模式定义 </strong>:<br />将抽象和行为划分开来,各自独立,但能动态的结合。</p>
		<p>任何事物对象都有抽象和行为之分，例如人，人是一种抽象，人分男人和女人等；人有行为，行为也有各种具体表现，所以，“人”与“人的行为”两个概念也反映了抽象和行为之分。</p>
		<p>在面向对象设计的基本概念中，对象这个概念实际是由属性和行为两个部分组成的，属性我们可以认为是一种静止的，是一种抽象，一般情况下，行为是包含在一个对象中，但是，在有的情况下，我们需要将这些行为也进行归类，形成一个总的行为接口，这就是桥模式的用处。</p>
		<p>
				<strong>为什么使用?</strong>
				<br />不希望抽象部分和行为有一种固定的绑定关系，而是应该可以动态联系的。</p>
		<p>如果一个抽象类或接口有多个具体实现(子类、concrete subclass),这些子类之间关系可能有以下两种情况:<br />1. 这多个子类之间概念是并列的,如前面举例,打桩,有两个concrete class:方形桩和圆形桩;这两个形状上的桩是并列的,没有概念上的重复。<br /><br />2.这多个子类之中有内容概念上重叠.那么需要我们把抽象共同部分和行为共同部分各自独立开来,原来是准备放在一个接口里,现在需要设计两个接口：抽象接口和行为接口，分别放置抽象和行为.<br /><br />例如,一杯咖啡为例,子类实现类为四个：中杯加奶、大杯加奶、 中杯不加奶、大杯不加奶。</p>
		<p>但是，我们注意到：上面四个子类中有概念重叠，可从另外一个角度进行考虑，这四个类实际是两个角色的组合：抽象 和行为，其中抽象为：中杯和大杯；行为为：加奶 不加奶（如加橙汁 加苹果汁）. </p>
		<p>实现四个子类在抽象和行为之间发生了固定的绑定关系，如果以后动态增加加葡萄汁的行为，就必须再增加两个类：中杯加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。</p>
		<p>那我们从分离抽象和行为的角度，使用Bridge模式来实现。</p>
		<p>
				<strong>如何实现?</strong>
				<br />以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.</p>
		<p>先看看抽象部分的接口代码:<br /></p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public abstract class Coffee<br />{<br />　　CoffeeImp coffeeImp;<br /><br />　　public void setCoffeeImp() {<br />　　　　this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();<br />　　}<br /><br />　　public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}<br /><br />　　public abstract void pourCoffee();<br />}<br /></td>
						</tr>
				</tbody>
		</table>
		<p>其中CoffeeImp 是加不加奶的行为接口,看其代码如下:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public abstract class CoffeeImp<br />{<br />　　public abstract void pourCoffeeImp();<br />}<br /></td>
						</tr>
				</tbody>
		</table>
		<p>现在我们有了两个抽象类,下面我们分别对其进行继承,实现concrete class:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>//中杯<br />public class MediumCoffee extends Coffee<br />{<br />　　public MediumCoffee() {setCoffeeImp();}<br /><br />　　public void pourCoffee()<br />　　{<br />　　　　CoffeeImp coffeeImp = this.getCoffeeImp();<br />　　　　//我们以重复次数来说明是冲中杯还是大杯 ,重复2次是中杯<br />　　　　for (int i = 0; i &lt; 2; i++)<br />　　　　{<br /><br />　　　　　　coffeeImp.pourCoffeeImp();<br />　　　　}<br />　　<br />　　}<br />}<br /></p>
										<p>//大杯<br />public class SuperSizeCoffee extends Coffee<br />{<br />　　public SuperSizeCoffee() {setCoffeeImp();}<br /><br />　　public void pourCoffee()<br />　　{<br />　　　　CoffeeImp coffeeImp = this.getCoffeeImp();<br />　　　　//我们以重复次数来说明是冲中杯还是大杯 ,重复5次是大杯<br />　　　　for (int i = 0; i &lt; 5; i++)<br />　　　　{<br /><br />　　　　　　coffeeImp.pourCoffeeImp();<br />　　　　}<br />　　<br />　　}<br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>上面分别是中杯和大杯的具体实现.下面再对行为CoffeeImp进行继承:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>//加奶<br />public class MilkCoffeeImp extends CoffeeImp<br />{<br />　　MilkCoffeeImp() {}<br /><br />　　public void pourCoffeeImp()<br />　　{<br />　　　　System.out.println("加了美味的牛奶");<br />　　}<br />}<br /></p>
										<p>//不加奶<br />public class FragrantCoffeeImp extends CoffeeImp<br />{<br />　　FragrantCoffeeImp() {}<br /><br />　　public void pourCoffeeImp()<br />　　{<br />　　　　System.out.println("什么也没加,清香");<br />　　}<br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>Bridge模式的基本框架我们已经搭好了,别忘记定义中还有一句:动态结合,我们现在可以喝到至少四种咖啡:<br />1.中杯加奶<br />2.中杯不加奶<br />3.大杯加奶<br />4.大杯不加奶</p>
		<p>看看是如何动态结合的,在使用之前,我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class CoffeeImpSingleton<br />{<br />　　private static CoffeeImp coffeeImp;<br /><br />　　public CoffeeImpSingleton(CoffeeImp coffeeImpIn)<br />　　 {this.coffeeImp = coffeeImpIn;}<br /><br />　　public static CoffeeImp getTheCoffeeImp()<br />　　{<br />　　　　return coffeeImp;<br />　　}<br />}<br /></td>
						</tr>
				</tbody>
		</table>
		<p>看看中杯加奶 和大杯加奶 是怎么出来的:</p>
		<p>//拿出牛奶<br />CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp());<br /><br />//中杯加奶<br />MediumCoffee mediumCoffee = new MediumCoffee();<br />mediumCoffee.pourCoffee();<br /><br />//大杯加奶<br />SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();<br />superSizeCoffee.pourCoffee();</p>
		<p>注意: Bridge模式的执行类如CoffeeImp和Coffee是一对一的关系, 正确创建CoffeeImp是该模式的关键,</p>
		<p align="left">Bridge模式在EJB中的应用<br />EJB中有一个Data Access Object (DAO)模式,这是将商业逻辑和具体数据资源分开的,因为不同的数据库有不同的数据库操作.将操作不同数据库的行为独立抽象成一个行为接口DAO.如下:</p>
		<p>1.Business Object (类似Coffee)</p>
		<p>实现一些抽象的商业操作:如寻找一个用户下所有的订单</p>
		<p>涉及数据库操作都使用DAOImplementor.</p>
		<p>2.Data Access Object (类似CoffeeImp)</p>
		<p>一些抽象的对数据库资源操作</p>
		<p>3.DAOImplementor 如OrderDAOCS, OrderDAOOracle, OrderDAOSybase(类似MilkCoffeeImp FragrantCoffeeImp)</p>
		<p>具体的数据库操作,如"INSERT INTO "等语句,OrderDAOOracle是Oracle OrderDAOSybase是Sybase数据库.</p>
		<p>4.数据库 (Cloudscape, Oracle, or Sybase database via JDBC API)</p>
		<p>
				<br />
		</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:48 <a href="http://www.blogjava.net/powerwind/articles/87018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Flyweight(享元) FlyWeight模式</title><link>http://www.blogjava.net/powerwind/articles/87019.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:48:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87019.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87019.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87019.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87019.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87019.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Flyweight(享元) FlyWeight模式</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/02</p>
		<p>
				<b>Flyweight模式定义:</b>
				<br />避免大量拥有相同内容的小类的开销(如耗费内存),使大家共享一个类(元类).</p>
		<p>
				<b>为什么使用?</b>
				<br />面向对象语言的原则就是一切都是对象,但是如果真正使用起来,有时对象数可能显得很庞大,比如,字处理软件,如果以每个文字都作为一个对象,几千个字,对象数就是几千,无疑耗费内存,那么我们还是要"求同存异",找出这些对象群的共同点,设计一个元类,封装可以被共享的类,另外,还有一些特性是取决于应用(context),是不可共享的,这也Flyweight中两个重要概念内部状态intrinsic和外部状态extrinsic之分.</p>
		<p>说白点,就是先捏一个的原始模型,然后随着不同场合和环境,再产生各具特征的具体模型,很显然,在这里需要产生不同的新对象,所以Flyweight模式中常出现Factory模式.Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个Flyweight pool(模式池)来存放内部状态的对象.</p>
		<p>Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度.应用场合很多:比如你要从一个数据库中读取一系列字符串,这些字符串中有许多是重复的,那么我们可以将这些字符串储存在Flyweight池(pool)中.</p>
		<p>
				<b>如何使用?</b>
				<br />
		</p>
		<p>我们先从Flyweight抽象接口开始:<br /></p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public interface Flyweight <br />{<br />　　public void operation( ExtrinsicState state );<br />}</p>
										<p>//用于本模式的抽象数据类型(自行设计)<br />public interface ExtrinsicState { }</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>下面是接口的具体实现(ConcreteFlyweight) ,并为内部状态增加内存空间, ConcreteFlyweight必须是可共享的,它保存的任何状态都必须是内部(intrinsic),也就是说,ConcreteFlyweight必须和它的应用环境场合无关.</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class ConcreteFlyweight implements Flyweight {<br />　　private IntrinsicState state; <br />　　<br />　　public void operation( ExtrinsicState state ) <br />　　{ <br />　　　　　　//具体操作<br />　　} 
<p>} </p></td>
						</tr>
				</tbody>
		</table>
		<p>当然,并不是所有的Flyweight具体实现子类都需要被共享的,所以还有另外一种不共享的ConcreteFlyweight:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class UnsharedConcreteFlyweight implements Flyweight {</p>
										<p>　　public void operation( ExtrinsicState state ) { }</p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>Flyweight factory负责维护一个Flyweight池(存放内部状态),当客户端请求一个共享Flyweight时,这个factory首先搜索池中是否已经有可适用的,如果有,factory只是简单返回送出这个对象,否则,创建一个新的对象,加入到池中,再返回送出这个对象.池</p>
		<p>
		</p>
		<table cellspacing="3" cellpadding="3" width="80%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>
										<p>public class FlyweightFactory { <br />　　//Flyweight pool<br />　　private Hashtable flyweights = new Hashtable(); <br /><br />　　public Flyweight getFlyweight( Object key ) { <br /></p>
										<p>　　　　Flyweight flyweight = (Flyweight) flyweights.get(key); <br /></p>
										<p>　　　　if( flyweight == null ) {<br />　　　　　　//产生新的ConcreteFlyweight<br />　　　　　　flyweight = new ConcreteFlyweight(); <br />　　　　　　flyweights.put( key, flyweight ); <br />　　　　} <br /></p>
										<p>　　　　return flyweight; <br />　　} <br />} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>至此,Flyweight模式的基本框架已经就绪,我们看看如何调用:</p>
		<p>FlyweightFactory factory = new FlyweightFactory(); <br />Flyweight fly1 = factory.getFlyweight( "Fred" ); <br />Flyweight fly2 = factory.getFlyweight( "Wilma" );<br />......<br /></p>
		<p>从调用上看,好象是个纯粹的Factory使用,但奥妙就在于Factory的内部设计上.</p>
		<p>
				<b>Flyweight模式在XML等数据源中应用</b>
				<br />我们上面已经提到,当大量从数据源中读取字符串,其中肯定有重复的,那么我们使用Flyweight模式可以提高效率,以唱片CD为例,在一个XML文件中,存放了多个CD的资料.</p>
		<p>每个CD有三个字段:<br />1.出片日期(year)<br />2.歌唱者姓名等信息(artist)<br />3.唱片曲目 (title)</p>
		<p>其中,歌唱者姓名有可能重复,也就是说,可能有同一个演唱者的多个不同时期 不同曲目的CD.我们将"歌唱者姓名"作为可共享的ConcreteFlyweight.其他两个字段作为UnsharedConcreteFlyweight.</p>
		<p>首先看看数据源XML文件的内容:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>
												<br />&lt;?xml version="1.0"?&gt;<br />&lt;collection&gt;<br /></p>
										<p>&lt;cd&gt;<br />&lt;title&gt;Another Green World&lt;/title&gt;<br />&lt;year&gt;1978&lt;/year&gt;<br />&lt;artist&gt;Eno, Brian&lt;/artist&gt;<br />&lt;/cd&gt;<br /></p>
										<p>&lt;cd&gt;<br />&lt;title&gt;Greatest Hits&lt;/title&gt;<br />&lt;year&gt;1950&lt;/year&gt;<br />&lt;artist&gt;Holiday, Billie&lt;/artist&gt;<br />&lt;/cd&gt;<br /></p>
										<p>&lt;cd&gt;<br />&lt;title&gt;Taking Tiger Mountain (by strategy)&lt;/title&gt;<br />&lt;year&gt;1977&lt;/year&gt;<br />&lt;artist&gt;Eno, Brian&lt;/artist&gt;<br />&lt;/cd&gt;<br /></p>
										<p>....... </p>
										<p>&lt;/collection&gt;<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<br />虽然上面举例CD只有3张,CD可看成是大量重复的小类,因为其中成分只有三个字段,而且有重复的(歌唱者姓名).</p>
		<p>CD就是类似上面接口 Flyweight:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>
												<br />public class CD {</p>
										<p>　　private String title;<br />　　private int year;<br />　　private Artist artist;<br /><br />　　public String getTitle() {　　return title;　}<br />　　public int getYear() {　　　　return year;　　}<br />　　public Artist getArtist() {　　　　return artist;　　}<br /><br />　　public void setTitle(String t){　　　　title = t;}<br />　　public void setYear(int y){year = y;}<br />　　public void setArtist(Artist a){artist = a;}<br /><br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>将"歌唱者姓名"作为可共享的ConcreteFlyweight:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Artist {<br /></p>
										<p>　　//内部状态<br />　　private String name; </p>
										<p>　　// note that Artist is immutable.<br />　　String getName(){return name;}<br /></p>
										<p>　　Artist(String n){<br />　　　　name = n;<br />　　} <br /><br />}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>再看看Flyweight factory,专门用来制造上面的可共享的ConcreteFlyweight:Artist</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class ArtistFactory {</p>
										<p>　　Hashtable pool = new Hashtable();<br /><br />　　Artist getArtist(String key){<br /></p>
										<p>　　　　Artist result;<br />　　　　result = (Artist)pool.get(key);<br />　　　　////产生新的Artist<br />　　　　if(result == null) {<br />　　　　　　result = new Artist(key);<br />　　　　　　pool.put(key,result);<br />　　　　　　<br />　　　　}<br />　　　 return result;<br />　 }<br /><br />}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>当你有几千张甚至更多CD时,Flyweight模式将节省更多空间,共享的flyweight越多,空间节省也就越大.</p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:48 <a href="http://www.blogjava.net/powerwind/articles/87019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Composite(组合)</title><link>http://www.blogjava.net/powerwind/articles/87015.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:47:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87015.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87015.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87015.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87015.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87015.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Composite(组合)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/04/27（转载请保留）</p>
		<p>
				<b>Composite模式定义</b>:<br />将对象以树形结构组织起来,以达成“部分－整体” 的层次结构，使得客户端对单个对象和组合对象的使用具有一致性.</p>
		<p>Composite比较容易理解，想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时，Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。</p>
		<p>所以Composite模式使用到Iterator模式，和Chain of Responsibility模式类似。</p>
		<p>
				<b>Composite好处</b>:<br />1.使客户端调用简单，客户端可以一致的使用组合结构或其中单个对象，用户就不必关系自己处理的是单个对象还是整个组合结构，这就简化了客户端代码。<br />2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。</p>
		<p>
				<b>如何使用Composite?</b>
				<br />首先定义一个接口或抽象类，这是设计模式通用方式了，其他设计模式对接口内部定义限制不多，Composite却有个规定，那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们（或称部件Component）.</p>
		<p>下面的代码是以抽象类定义，一般尽量用接口interface,</p>
		<p>
		</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public abstract class Equipment<br />{<br />　　private String name; <br />　　//实价<br />　　public abstract double netPrice();<br />　　//折扣价格<br />　　public abstract double discountPrice();<br />　　//增加部件方法　　<br />　　public boolean add(Equipment equipment) { return false; }<br />　　//删除部件方法<br />　　public boolean remove(Equipment equipment) { return false; }<br />　　//注意这里，这里就提供一种用于访问组合体类的部件方法。<br />　　public Iterator iter() { return null; }<br />　　<br />　　public Equipment(final String name) { this.name=name; }<br />} </td>
						</tr>
				</tbody>
		</table>
		<p>抽象类Equipment就是Component定义，代表着组合体类的对象们,Equipment中定义几个共同的方法。</p>
		<p>
		</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class Disk extends Equipment<br />{<br />　　public Disk(String name) { super(name); }<br />　　//定义Disk实价为1<br />　　public double netPrice() { return 1.; }<br />　　//定义了disk折扣价格是0.5 对折。<br />　　public double discountPrice() { return .5; }<br />}</td>
						</tr>
				</tbody>
		</table>
		<p>Disk是组合体内的一个对象，或称一个部件，这个部件是个单独元素( Primitive)。<br />还有一种可能是，一个部件也是一个组合体，就是说这个部件下面还有'儿子'，这是树形结构中通常的情况，应该比较容易理解。现在我们先要定义这个组合体：</p>
		<p>
		</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>abstract class CompositeEquipment extends Equipment<br />{<br />　　private int i=0; <br />　　//定义一个Vector 用来存放'儿子'<br />　　private Lsit equipment=new ArrayList();<br /><br />　　public CompositeEquipment(String name) { super(name); }<br /><br />　　public boolean add(Equipment equipment) { <br />　　　　 this.equipment.add(equipment); <br />　　　　 return true; <br />　　 }<br /><br />　　public double netPrice() <br />　　{<br />　　　　double netPrice=0.;<br />　　　　Iterator iter=equipment.iterator();<br />　　　　for(iter.hasNext())<br />　　　　　　netPrice+=((Equipment)iter.next()).netPrice();<br />　　　　return netPrice;<br />　　}<br /><br />　　public double discountPrice() <br />　　{<br />　　　　double discountPrice=0.;<br />　　　　Iterator iter=equipment.iterator();<br />　　　　for(iter.hasNext())<br />　　　　　　discountPrice+=((Equipment)iter.next()).discountPrice();<br />　　　　return discountPrice;<br />　　}<br />　　<br /></p>
										<p>　　//注意这里，这里就提供用于访问自己组合体内的部件方法。<br />　　//上面dIsk 之所以没有，是因为Disk是个单独(Primitive)的元素.<br />　　public Iterator iter()<br />　　{<br />　　　　return equipment.iterator() ;<br />　　{<br />　　//重载Iterator方法<br />　　 public boolean hasNext() { return i&lt;equipment.size(); }<br />　　//重载Iterator方法<br />　　 public Object next()<br />　　 {<br />　　　　if(hasNext())<br />　　　　　　 return equipment.elementAt(i++);<br />　　　　else <br />　　 　　 　 throw new NoSuchElementException();<br />　　 }<br />　　<br /><br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口，是Iterator模式的实现.</p>
		<p>我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet，箱子里面可以放很多东西，如底板，电源盒，硬盘盒等；盘盒里面可以放一些小设备，如硬盘 软驱等。无疑这两个都是属于组合体性质的。</p>
		<p>
		</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class Chassis extends CompositeEquipment<br />{<br />　　 public Chassis(String name) { super(name); }<br />　　 public double netPrice() { return 1.+super.netPrice(); }<br />　　 public double discountPrice() { return .5+super.discountPrice(); }<br />} 
<p>public class Cabinet extends CompositeEquipment<br />{<br />　　 public Cabinet(String name) { super(name); }<br />　　 public double netPrice() { return 1.+super.netPrice(); }<br />　　 public double discountPrice() { return .5+super.discountPrice(); }<br />}</p></td>
						</tr>
				</tbody>
		</table>
		<p>至此我们完成了整个Composite模式的架构。</p>
		<p>我们可以看看客户端调用Composote代码:<br /><br />Cabinet cabinet=new Cabinet("Tower");<br /><br />Chassis chassis=new Chassis("PC Chassis");<br />//将PC Chassis装到Tower中 (将盘盒装到箱子里)<br />cabinet.add(chassis);<br />//将一个10GB的硬盘装到 PC Chassis (将硬盘装到盘盒里)<br />chassis.add(new Disk("10 GB"));<br /><br />//调用 netPrice()方法;<br />System.out.println("netPrice="+cabinet.netPrice());<br />System.out.println("discountPrice="+cabinet.discountPrice());<br /><br /></p>
		<p>上面调用的方法netPrice()或discountPrice()，实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.</p>
		<p>Composite是个很巧妙体现智慧的模式，在实际应用中，如果碰到树形结构，我们就可以尝试是否可以使用这个模式。</p>
		<p>以论坛为例，一个版(forum)中有很多帖子(message),这些帖子有原始贴，有对原始贴的回应贴，是个典型的树形结构，那么当然可以使用Composite模式，那么我们进入Jive中看看，是如何实现的.</p>
		<p>
				<b>Jive解剖</b>
				<br />在Jive中 ForumThread是ForumMessages的容器container(组合体).也就是说，ForumThread类似我们上例中的 CompositeEquipment.它和messages的关系如图：<br />[thread]<br />　　 |- [message]<br />　　 |- [message]<br />　　 　　 |- [message]<br />　　 　　 |- [message]<br />　　 　　 　　 |- [message] </p>
		<p>我们在ForumThread看到如下代码：<br /></p>
		<p>
		</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public interface ForumThread {<br />　　 .... <br />　　 public void addMessage(ForumMessage parentMessage, ForumMessage newMessage)<br />　　 　　 　　 throws UnauthorizedException; 
<p>　　 public void deleteMessage(ForumMessage message)<br />　　 　　 　　 throws UnauthorizedException;</p><p>　　<br />　　 public Iterator messages();<br />　　 　　 .... </p><p>}</p></td>
						</tr>
				</tbody>
		</table>
		<p>类似CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历.</p>
		<p>结合我的其他模式中对Jive的分析，我们已经基本大体理解了Jive论坛体系的框架，如果你之前不理解设计模式，而直接去看Jive源代码，你肯定无法看懂。</p>
		<p>参考文章：</p>
		<p>
				<a href="http://www.jdon.com/jive/article.jsp?forum=91&amp;thread=23857">
						<font color="#002c99">Composite模式和树形结构的讨论</font>
				</a>
		</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:47 <a href="http://www.blogjava.net/powerwind/articles/87015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Decorator(油漆工)</title><link>http://www.blogjava.net/powerwind/articles/87017.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:47:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87017.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87017.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87017.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87017.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87017.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Decorator(油漆工)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/04/28</p>
		<p>装饰模式:Decorator常被翻译成"装饰",我觉得翻译成"油漆工"更形象点,油漆工(decorator)是用来刷油漆的,那么被刷油漆的对象我们称decoratee.这两种实体在Decorator模式中是必须的.</p>
		<p>
		</p>
		<p>
				<b>Decorator定义</b>:<br />动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活.<br /></p>
		<p>
				<b>为什么使用Decorator</b>?<br />我们通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的.</p>
		<p>使用Decorator的理由是:这些功能需要由用户动态决定加入的方式和时机.Decorator提供了"即插即用"的方法,在运行期间决定何时增加何种功能.</p>
		<p>
				<b>如何使用</b>?<br />举Adapter中的打桩示例,在Adapter中有两种类:方形桩 圆形桩,Adapter模式展示如何综合使用这两个类,在Decorator模式中,我们是要在打桩时增加一些额外功能,比如,挖坑 在桩上钉木板等,不关心如何使用两个不相关的类.</p>
		<p>我们先建立一个接口:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public interface Work<br />{ <br />　　public void insert();</p>
										<p>}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>接口Work有一个具体实现:插入方形桩或圆形桩,这两个区别对Decorator是无所谓.我们以插入方形桩为例:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class SquarePeg implements Work{<br />　　public void insert(){<br />　　　　System.out.println("方形桩插入");<br />　　} 
<p>}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>现在有一个应用:需要在桩打入前,挖坑,在打入后,在桩上钉木板,这些额外的功能是动态,可能随意增加调整修改,比如,可能又需要在打桩之后钉架子(只是比喻).</p>
		<p>那么我们使用Decorator模式,这里方形桩SquarePeg是decoratee(被刷油漆者),我们需要在decoratee上刷些"油漆",这些油漆就是那些额外的功能.</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Decorator implements Work{</p>
										<p>　　private Work work;<br />　　//额外增加的功能被打包在这个List中<br />　　private ArrayList others = new ArrayList(); </p>
										<p>　　//在构造器中使用组合new方式,引入Work对象;<br />　　public Decorator(Work work)<br />　　{<br />　　　　this.work=work;<br />　　 <br />　　　　others.add("挖坑");</p>
										<p>　　　　others.add("钉木板");<br />　　}</p>
										<p>　　public void insert(){</p>　　　　newMethod();<br />　　} 
<p><br />　　<br />　　//在新方法中,我们在insert之前增加其他方法,这里次序先后是用户灵活指定的 　　 <br />　　public void newMethod()<br />　　{<br />　　　　otherMethod();<br />　　　　work.insert();<br /><br /><br />　　} <br /></p><p>　　public void otherMethod()<br />　　{<br />　　　　ListIterator listIterator = others.listIterator();<br />　　　　while (listIterator.hasNext())<br />　　　　{<br />　　　　　　System.out.println(((String)(listIterator.next())) + " 正在进行");<br />　　　　}<br /><br />　　} <br /></p><p>}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>在上例中,我们把挖坑和钉木板都排在了打桩insert前面,这里只是举例说明额外功能次序可以任意安排.</p>
		<p>好了,Decorator模式出来了,我们看如何调用:</p>
		<p>Work squarePeg = new SquarePeg(); <br />Work decorator = new Decorator(squarePeg);<br />decorator.insert(); </p>
		<p>
		</p>
		<p>Decorator模式至此完成.</p>
		<p>如果你细心,会发现,上面调用类似我们读取文件时的调用:</p>
		<p>FileReader fr = new FileReader(filename);<br />BufferedReader br = new BufferedReader(fr);</p>
		<p>实际上Java 的I/O API就是使用<a href="http://www-900.ibm.com/developerWorks/java/l-jdkdp/part3/index.shtml#2" target="_blank"><font color="#002c99">Decorator实现的</font></a>,I/O变种很多,如果都采取继承方法,将会产生很多子类,显然相当繁琐.</p>
		<p>
				<b>Jive中的Decorator实现</b>
				<br />在论坛系统中,有些特别的字是不能出现在论坛中如"打倒XXX",我们需要过滤这些"反动"的字体.不让他们出现或者高亮度显示.</p>
		<p>在IBM Java专栏中专门<a href="http://www-900.ibm.com/developerWorks/java/l-jivesrc/index.shtml#5" target="_blank"><font color="#002c99">谈Jive的文章</font></a>中,有谈及Jive中ForumMessageFilter.java使用了Decorator模式,其实,该程序并没有真正使用Decorator,而是提示说:针对特别论坛可以设计额外增加的过滤功能,那么就可以重组ForumMessageFilter作为Decorator模式了.</p>
		<p>所以,我们在分辨是否真正是Decorator模式,以及会真正使用Decorator模式,一定要把握好Decorator模式的定义,以及其中参与的角色(Decoratee 和Decorator).</p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:47 <a href="http://www.blogjava.net/powerwind/articles/87017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Adapter(适配器)</title><link>http://www.blogjava.net/powerwind/articles/87014.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:46:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87014.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87014.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87014.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87014.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Adapter(适配器)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/04/21</p>
		<p>
				<b>适配器模式定义:</b>
				<br />将两个不兼容的类纠合在一起使用，属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份.</p>
		<p>
				<b>为何使用?</b>
				<br />我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是：修改各自类的接口，但是如果我们没有源代码，或者，我们不愿意为了一个应用而修改各自的接口。 怎么办? </p>
		<p>使用Adapter，在这两种接口之间创建一个混合接口(混血儿).</p>
		<p>
				<b>如何使用?</b>
				<br />实现Adapter方式,其实"think in Java"的"类再生"一节中已经提到,有两种方式：组合(composition)和继承(inheritance).</p>
		<p>
				<br />假设我们要打桩，有两种类：方形桩 圆形桩.<br />public class SquarePeg{<br />　　public void insert(String str){<br />　　　　System.out.println("SquarePeg insert():"+str);<br />　　}</p>
		<p>}</p>
		<p>public class RoundPeg{<br />　　public void insertIntohole(String msg){<br />　　　　System.out.println("RoundPeg insertIntoHole():"+msg);<br />}<br />}</p>
		<p>现在有一个应用,需要既打方形桩,又打圆形桩.那么我们需要将这两个没有关系的类综合应用.假设RoundPeg我们没有源代码,或源代码我们不想修改,那么我们使用Adapter来实现这个应用:</p>
		<p>public class PegAdapter extends SquarePeg{<br /><br />　　private RoundPeg roundPeg;</p>
		<p>　　public PegAdapter(RoundPeg peg)(this.roundPeg=peg;)</p>
		<p>　　public void insert(String str){ roundPeg.insertIntoHole(str);}</p>
		<p>}</p>
		<p>在上面代码中,RoundPeg属于Adaptee,是被适配者.PegAdapter是Adapter,将Adaptee(被适配者RoundPeg)和Target(目标SquarePeg)进行适配.实际上这是将组合方法(composition)和继承(inheritance)方法综合运用.</p>
		<p>PegAdapter首先继承SquarePeg，然后使用new的组合生成对象方式，生成RoundPeg的对象roundPeg，再重载父类insert()方法。从这里,你也了解使用new生成对象和使用extends继承生成对象的不同,前者无需对原来的类修改,甚至无需要知道其内部结构和源代码.</p>
		<p>如果你有些Java使用的经验，已经发现，这种模式经常使用。</p>
		<p>
				<b>进一步使用</b>
				<br />上面的PegAdapter是继承了SquarePeg,如果我们需要两边继承，即继承SquarePeg 又继承RoundPeg,因为Java中不允许多继承，但是我们可以实现(implements)两个接口(interface)</p>
		<p>public interface IRoundPeg{<br />　　public void insertIntoHole(String msg);<br /><br />}</p>
		<p>public interface ISquarePeg{<br />　　public void insert(String str);</p>
		<p>}</p>
		<p>下面是新的RoundPeg 和SquarePeg, 除了实现接口这一区别，和上面的没什么区别。<br />public class SquarePeg implements ISquarePeg{<br />　　public void insert(String str){<br />　　　　System.out.println("SquarePeg insert():"+str);<br />　　}</p>
		<p>}</p>
		<p>public class RoundPeg implements IRoundPeg{<br />　　public void insertIntohole(String msg){<br />　　　　System.out.println("RoundPeg insertIntoHole():"+msg);<br />　　}<br />}</p>
		<p>下面是新的PegAdapter,叫做two-way adapter:</p>
		<p>public class PegAdapter implements IRoundPeg,ISquarePeg{<br /><br />　　private RoundPeg roundPeg;<br />　　private SquarePeg squarePeg;<br /><br />　　// 构造方法<br />　　public PegAdapter(RoundPeg peg){this.roundPeg=peg;}<br />　　// 构造方法<br />　　public PegAdapter(SquarePeg peg)(this.squarePeg=peg;)</p>
		<p>　　public void insert(String str){ roundPeg.insertIntoHole(str);}</p>
		<p>}</p>
		<p>还有一种叫Pluggable Adapters,可以动态的获取几个adapters中一个。使用Reflection技术，可以动态的发现类中的Public方法。<br /></p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:46 <a href="http://www.blogjava.net/powerwind/articles/87014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Proxy(代理)</title><link>http://www.blogjava.net/powerwind/articles/87013.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:45:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87013.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87013.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87013.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87013.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Proxy(代理)</h3>
		<p align="center">板桥里人banq http://www.jdon.com 2002/04/21/</p>
		<p>理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣.</p>
		<p>代理模式是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理.</p>
		<p>
				<b>设计模式中定义</b>: 为其他对象提供一种代理以控制对这个对象的访问.</p>
		<p>
				<b>为什么要使用Proxy?</b>
				<br />1.授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive中就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限.</p>
		<p>2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.<br />举例两个具体情况: <br />(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy来代替真正的图片.<br /><br />(2)如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.<br /></p>
		<p>总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存. 所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系.</p>
		<p>
				<b>如何使用Proxy?</b>
				<br />以<a href="http://www.jdon.com/dl/jive.zip">Jive论坛系统</a>为例,访问论坛系统的用户有多种类型:注册普通用户 论坛管理者 系统管理者 游客,注册普通用户才能发言;论坛管理者可以管理他被授权的论坛;系统管理者可以管理所有事务等,这些权限划分和管理是使用Proxy完成的.</p>
		<p>Forum是Jive的核心接口,在Forum中陈列了有关论坛操作的主要行为,如论坛名称 论坛描述的获取和修改,帖子发表删除编辑等.</p>
		<p>在ForumPermissions中定义了各种级别权限的用户:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class ForumPermissions implements Cacheable { 
<p>/**<br />* Permission to read object.<br />*/<br />public static final int READ = 0;</p><p>/**<br />* Permission to administer the entire sytem.<br />*/<br />public static final int SYSTEM_ADMIN = 1;</p><p>/**<br />* Permission to administer a particular forum.<br />*/<br />public static final int FORUM_ADMIN = 2;</p><p>/**<br />* Permission to administer a particular user.<br />*/<br />public static final int USER_ADMIN = 3;</p><p>/**<br />* Permission to administer a particular group.<br />*/<br />public static final int GROUP_ADMIN = 4;</p><p>/**<br />* Permission to moderate threads.<br />*/<br />public static final int MODERATE_THREADS = 5;</p><p>/**<br />* Permission to create a new thread.<br />*/<br />public static final int CREATE_THREAD = 6;</p><p>/**<br />* Permission to create a new message.<br />*/<br />public static final int CREATE_MESSAGE = 7;</p><p>/**<br />* Permission to moderate messages.<br />*/<br />public static final int MODERATE_MESSAGES = 8;</p><p>.....</p><p>public boolean isSystemOrForumAdmin() {<br />　　return (values[FORUM_ADMIN] || values[SYSTEM_ADMIN]);<br />}</p><p>.....</p><p>}</p></td>
						</tr>
				</tbody>
		</table>
		<p>因此,Forum中各种操作权限是和ForumPermissions定义的用户级别有关系的,作为接口Forum的实现:ForumProxy正是将这种对应关系联系起来.比如,修改Forum的名称,只有论坛管理者或系统管理者可以修改,代码如下:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class ForumProxy implements Forum {</p>
										<p>private ForumPermissions permissions;<br />private Forum forum; <br />this.authorization = authorization; <br /><br />public ForumProxy(Forum forum, Authorization authorization,<br />ForumPermissions permissions)<br />{<br />this.forum = forum;<br />this.authorization = authorization;<br />this.permissions = permissions;<br />}<br /><br />.....</p>
										<p>public void setName(String name) throws UnauthorizedException,<br />ForumAlreadyExistsException<br />{<br />　　//只有是系统或论坛管理者才可以修改名称<br />　　if (permissions.isSystemOrForumAdmin()) {<br />　　　　forum.setName(name);<br />　　}<br />　　else {<br />　　　　throw new UnauthorizedException();<br />　　}<br />}</p>
										<p>...</p>
										<p>}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>而DbForum才是接口Forum的真正实现,以修改论坛名称为例:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class DbForum implements Forum, Cacheable {<br />...</p>
										<p>public void setName(String name) throws ForumAlreadyExistsException {<br /><br />　　....<br /><br />　　this.name = name;<br />　　//这里真正将新名称保存到数据库中 <br />　　saveToDb();</p>
										<p>　　....<br />}<br /></p>
										<p>
												<br />... </p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样事情,ForumProxy是个名副其实的"网关","安全代理系统".</p>
		<p>在平时应用中,无可避免总要涉及到系统的授权或安全体系,不管你有无意识的使用Proxy,实际你已经在使用Proxy了.</p>
		<p>我们继续结合Jive谈入深一点,下面要涉及到工厂模式了,如果你不了解工厂模式,请看我的另外一篇文章:<a href="http://www.jdon.com/designpatterns/designpattern_factory.htm" target="_blank">设计模式之Factory</a></p>
		<p>我们已经知道,使用Forum需要通过ForumProxy,Jive中创建一个Forum是使用Factory模式,有一个总的抽象类ForumFactory,在这个抽象类中,调用ForumFactory是通过getInstance()方法实现,这里使用了Singleton(也是设计模式之一,由于介绍文章很多,我就不写了,<a href="http://www-900.ibm.com/developerWorks/java/designpattern/singleton/index.shtml" target="_blank">看这里</a>),getInstance()返回的是ForumFactoryProxy.</p>
		<p>为什么不返回ForumFactory,而返回ForumFactory的实现ForumFactoryProxy?<br />原因是明显的,需要通过代理确定是否有权限创建forum.</p>
		<p>在ForumFactoryProxy中我们看到代码如下:</p>
		<table cellspacing="3" cellpadding="3" width="98%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class ForumFactoryProxy extends ForumFactory { 
<p>　　protected ForumFactory factory;<br />　　protected Authorization authorization;<br />　　protected ForumPermissions permissions;</p><p>　　public ForumFactoryProxy(Authorization authorization, ForumFactory factory,<br />　　ForumPermissions permissions)<br />　　{<br />　　　　this.factory = factory;<br />　　　　this.authorization = authorization;<br />　　　　this.permissions = permissions;<br />　　}</p><p>　　public Forum createForum(String name, String description)<br />　　　　　　throws UnauthorizedException, ForumAlreadyExistsException<br />　　{<br />　　　　//只有系统管理者才可以创建forum <br />　　　　if (permissions.get(ForumPermissions.SYSTEM_ADMIN)) {<br />　　　　　　Forum newForum = factory.createForum(name, description);<br />　　　　　　return new ForumProxy(newForum, authorization, permissions);<br />　　　　}<br />　　　　else {<br />　　　　　　throw new UnauthorizedException();<br />　　}<br />}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>方法createForum返回的也是ForumProxy, Proxy就象一道墙,其他程序只能和Proxy交互操作.</p>
		<p>注意到这里有两个Proxy:ForumProxy和ForumFactoryProxy. 代表两个不同的职责:使用Forum和创建Forum;<br />至于为什么将使用对象和创建对象分开,这也是为什么使用Factory模式的原因所在:是为了"封装" "分派";换句话说,尽可能功能单一化,方便维护修改.</p>
		<p>Jive论坛系统中其他如帖子的创建和使用,都是按照Forum这个思路而来的.</p>
		<p>以上我们讨论了如何使用Proxy进行授权机制的访问,Proxy还可以对用户隐藏另外一种称为copy-on-write的优化方式.拷贝一个庞大而复杂的对象是一个开销很大的操作,如果拷贝过程中,没有对原来的对象有所修改,那么这样的拷贝开销就没有必要.用代理延迟这一拷贝过程.</p>
		<p>比如:我们有一个很大的Collection,具体如hashtable,有很多客户端会并发同时访问它.其中一个特别的客户端要进行连续的数据获取,此时要求其他客户端不能再向hashtable中增加或删除 东东.</p>
		<p>最直接的解决方案是:使用collection的lock,让这特别的客户端获得这个lock,进行连续的数据获取,然后再释放lock.<br />public void foFetches(Hashtable ht){<br />　　synchronized(ht){<br />　　　　//具体的连续数据获取动作.. <br />　　} </p>
		<p>}<br /></p>
		<p>但是这一办法可能锁住Collection会很长时间,这段时间,其他客户端就不能访问该Collection了.</p>
		<p>第二个解决方案是clone这个Collection,然后让连续的数据获取针对clone出来的那个Collection操作.这个方案前提是,这个Collection是可clone的,而且必须有提供深度clone的方法.Hashtable就提供了对自己的clone方法,但不是Key和value对象的clone,关于Clone含义可以参考<a href="http://www-900.ibm.com/developerWorks/java/l-jpointer/index.shtml" target="_blank">专门文章</a>.<br />public void foFetches(Hashtable ht){<br /></p>
		<p>　　Hashttable newht=(Hashtable)ht.clone();</p>
		<p>}</p>
		<p>问题又来了,由于是针对clone出来的对象操作,如果原来的母体被其他客户端操作修改了, 那么对clone出来的对象操作就没有意义了.</p>
		<p>最后解决方案:我们可以等其他客户端修改完成后再进行clone,也就是说,这个特别的客户端先通过调用一个叫clone的方法来进行一系列数据获取操作.但实际上没有真正的进行对象拷贝,直至有其他客户端修改了这个对象Collection.</p>
		<p>使用Proxy实现这个方案.这就是copy-on-write操作.</p>
		<p>Proxy应用范围很广,现在流行的分布计算方式RMI和Corba等都是Proxy模式的应用.</p>
		<p>更多Proxy应用,见<a href="http://www.research.umbc.edu/%7Etarr/cs491/lectures/Proxy.pdf" target="_blank">http://www.research.umbc.edu/~tarr/cs491/lectures/Proxy.pdf</a></p>
		<p>Sun公司的 <a href="http://developer.java.sun.com/developer/technicalArticles/DataTypes/proxy/" target="_blank">Explore the Dynamic Proxy API</a><a href="http://java.sun.com/j2se/1.4/docs/guide/reflection/proxy.html" target="_blank">Dynamic Proxy Classes</a></p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:45 <a href="http://www.blogjava.net/powerwind/articles/87013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Facade(外观 总管　Manager)</title><link>http://www.blogjava.net/powerwind/articles/87011.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:44:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87011.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87011.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87011.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87011.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Facade(外观 总管　Manager)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">板桥里人</a> http://www.jdon.com 2002/4/6/（转载请保留）</p>
		<p>
				<i>
						<b>Facade模式的定义</b>
				</i>: 为子系统中的一组接口提供一个一致的界面.</p>
		<p>Facade一个典型应用就是数据库JDBC的应用,如下例对数据库的操作:</p>
		<table cellspacing="3" cellpadding="3" width="95%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class DBCompare {<br /></p>
										<p>　　Connection conn = null;<br />　　PreparedStatement prep = null;<br />　　ResultSet rset = null; <br />　　try {<br />　　 　　Class.forName( "&lt;driver&gt;" ).newInstance();<br />　　　　 conn = DriverManager.getConnection( "&lt;database&gt;" );<br />　　　　<br />　　　　 String sql = "SELECT * FROM &lt;table&gt; WHERE &lt;column name&gt; = ?";<br />　　　　 prep = conn.prepareStatement( sql );<br />　　　　 prep.setString( 1, "&lt;column value&gt;" );<br />　　　　 rset = prep.executeQuery();<br />　　　　 if( rset.next() ) {<br />　　　　　　　　System.out.println( rset.getString( "&lt;column name" ) );<br />　　　　　}<br />　　} catch( SException e ) {<br />　　　　 e.printStackTrace();<br />　　} finally {<br />　　　　 rset.close();<br />　　　　 prep.close();<br />　　　　 conn.close();<br />　　}<br />}<br /></p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>上例是Jsp中最通常的对数据库操作办法. </p>
		<p>在应用中,经常需要对数据库操作,每次都写上述一段代码肯定比较麻烦,需要将其中不变的部分提炼出来,做成一个接口,这就引入了facade外观对象.如果以后我们更换Class.forName中的&lt;driver&gt;也非常方便,比如从Mysql数据库换到Oracle数据库,只要更换facade接口中的driver就可以.</p>
		<p>我们做成了一个<a href="http://www.jdon.com/idea/java/%CA%FD%BE%DD%BF%E2.htm" target="_blank">Facade接口</a>,使用该接口,上例中的程序就可以更改如下:</p>
		<table cellspacing="3" cellpadding="3" width="98%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class DBCompare {<br /><br />　 String sql = "SELECT * FROM &lt;table&gt; WHERE &lt;column name&gt; = ?";　　<br /><br />　　try {<br />　　 　　Mysql msql=new mysql(sql);<br />　　　　 prep.setString( 1, "&lt;column value&gt;" );<br />　　　　 rset = prep.executeQuery();<br />　　　　 if( rset.next() ) {<br />　　　　　　　　System.out.println( rset.getString( "&lt;column name" ) );<br />　　　　　}<br />　　} catch( SException e ) {<br />　　　　 e.printStackTrace();<br />　　} finally {<br />　　　　 mysql.close();<br />　　　　 mysql=null;<br />　　}<br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>可见非常简单,所有程序对数据库访问都是使用改接口,降低系统的复杂性,增加了灵活性.</p>
		<p>如果我们要使用连接池,也只要针对facade接口修改就可以.</p>
		<p> </p>
		<p>
				<img height="232" src="http://www.jdon.com/designpatterns/images/facade.jpg" width="500" />
		</p>
		<p>由上图可以看出, facade实际上是个理顺系统间关系,降低系统间耦合度的一个常用的办法,也许你已经不知不觉在使用,尽管不知道它就是facade.</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:44 <a href="http://www.blogjava.net/powerwind/articles/87011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Singleton(单态)</title><link>http://www.blogjava.net/powerwind/articles/87010.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87010.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87010.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87010.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87010.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Singleton(单态)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">
						<font color="#002c99">板桥里人</font>
				</a> http://www.jdon.com 2002/05/07</p>
		<p>
				<strong>单态定义</strong>:<br />Singleton模式主要作用是保证在Java应用程序中，一个类Class只有一个实例存在。 </p>
		<p>在很多操作中，比如建立目录 数据库连接都需要这样的单线程操作。</p>
		<p>还有, singleton能够被状态化; 这样，多个单态类在一起就可以作为一个状态仓库一样向外提供服务，比如，你要论坛中的帖子计数器，每次浏览一次需要计数，单态类能否保持住这个计数，并且能synchronize的安全自动加1，如果你要把这个数字永久保存到数据库，你可以在不修改单态接口的情况下方便的做到。</p>
		<p>另外方面，Singleton也能够被无状态化。提供工具性质的功能，<br /><br />Singleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存，因为它限制了实例的个数，有利于Java垃圾回收（garbage collection）。<br /><br />我们常常看到工厂模式中类装入器(class loader)中也用Singleton模式实现的,因为被装入的类实际也属于资源。<br /></p>
		<p>
				<strong>如何使用?</strong>
				<br />一般Singleton模式通常有几种形式:</p>
		<table cellspacing="3" cellpadding="3" width="100%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Singleton {</p>
										<p>　　private Singleton(){}</p>
										<p>　　//在自己内部定义自己一个实例，是不是很奇怪？<br />　　//注意这是private 只供内部调用</p>
										<p>　　private static Singleton instance = new Singleton();</p>
										<p>　　//这里提供了一个供外部访问本class的静态方法，可以直接访问　　<br />　　public static Singleton getInstance() {<br />　　　　return instance; 　　<br />　　 } <br />} </p>
										<p> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>第二种形式:</p>
		<table cellspacing="3" cellpadding="3" width="100%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public class Singleton { 
<p>　　private static Singleton instance = null;<br /><br />　　public static synchronized Singleton getInstance() {<br /><br />　　//这个方法比上面有所改进，不用每次都进行生成对象，只是第一次　　　 　<br />　　//使用时生成实例，提高了效率！<br />　　if (instance==null)<br />　　　　instance＝new Singleton();<br />　　return instance; 　　} </p><p>} </p><p> </p></td>
						</tr>
				</tbody>
		</table>
		<p>使用Singleton.getInstance()可以访问单态类。</p>
		<p>上面第二中形式是lazy initialization，也就是说第一次调用时初始Singleton，以后就不用再生成了。</p>
		<p>注意到lazy initialization形式中的synchronized，这个synchronized很重要，如果没有synchronized，那么使用getInstance()是有可能得到多个Singleton实例。关于lazy initialization的Singleton有很多涉及double-checked locking (DCL)的讨论，有兴趣者进一步研究。</p>
		<p>一般认为第一种形式要更加安全些。<br /></p>
		<p>
				<strong>使用Singleton注意事项</strong>：<br />有时在某些情况下，使用Singleton并不能达到Singleton的目的，如有多个Singleton对象同时被不同的类装入器装载；在EJB这样的分布式系统中使用也要注意这种情况，因为EJB是跨服务器，跨JVM的。</p>
		<p>我们以SUN公司的宠物店源码(Pet Store 1.3.1)的ServiceLocator为例稍微分析一下：<br /><br />在Pet Store中ServiceLocator有两种，一个是EJB目录下；一个是WEB目录下，我们检查这两个ServiceLocator会发现内容差不多，都是提供EJB的查询定位服务，可是为什么要分开呢？仔细研究对这两种ServiceLocator才发现区别：在WEB中的ServiceLocator的采取Singleton模式，ServiceLocator属于资源定位，理所当然应该使用Singleton模式。但是在EJB中，Singleton模式已经失去作用，所以ServiceLocator才分成两种，一种面向WEB服务的，一种是面向EJB服务的。</p>
		<p>Singleton模式看起来简单，使用方法也很方便，但是真正用好，是非常不容易，需要对Java的类 线程 内存等概念有相当的了解。</p>
		<p>总之：如果你的应用基于容器，那么Singleton模式少用或者不用，可以使用相关替代技术。</p>
		<p>
		</p>
		<p>进一步深入可参考：</p>
		<p>
				<a href="http://www-106.ibm.com/developerworks/java/library/j-dcl.html?dwzone=java" target="_blank">
						<font color="#002c99">Double-checked locking and the Singleton pattern</font>
				</a>
		</p>
		<p>
				<a href="http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton-p3.html#resources" target="_blank">
						<font color="#002c99">When is a singleton not a singleton?</font>
				</a>
		</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:43 <a href="http://www.blogjava.net/powerwind/articles/87010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Builder</title><link>http://www.blogjava.net/powerwind/articles/87009.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:42:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87009.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87009.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87009.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Builder</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">板桥里人</a> http://www.jdon.com 2002/05/07</p>
		<p>
				<b>Builder模式定义</b>:<br />将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.</p>
		<p>Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知道内部的具体构建细节.Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到.</p>
		<p>
				<b>为何使用?</b>
				<br />是为了将构建复杂对象的<b><i>过程</i></b>和它的<i><b>部件</b></i>解耦.注意: 是解耦<b><i>过程</i></b>和<i><b>部件</b></i>.</p>
		<p>因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开.<br /></p>
		<p>
				<b>如何使用?</b>
				<br />首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部件的创建分别开来,分别用Builder类和Director类来表示.<br /></p>
		<p>首先,需要一个接口,它定义如何创建复杂对象的各个部件:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public interface Builder { </p>
										<p>　　//创建部件A　　比如创建汽车车轮<br />　　void buildPartA(); <br />　　//创建部件B 比如创建汽车方向盘<br />　　void buildPartB(); <br />　　//创建部件C 比如创建汽车发动机<br />　　void buildPartC(); <br /><br />　　//返回最后组装成品结果 (返回最后装配好的汽车)<br />　　//成品的组装过程不在这里进行,而是转移到下面的Director类中进行.<br />　　//从而实现了解耦<b><i>过程</i></b>和<i><b>部件</b></i><br />　　Product getResult(); </p>
										<p>} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>用Director构建最后的复杂对象,而在上面Builder接口中封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就是说Director的内容是如何将部件最后组装成成品:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class Director {</p>
										<p>　　private Builder builder; </p>
										<p>　　public Director( Builder builder ) { <br />　　　　this.builder = builder; <br />　　} <br />　　// 将部件partA partB partC最后组成复杂对象<br />　　//这里是将车轮 方向盘和发动机组装成汽车的过程<br />　　public void construct() { <br />　　　　builder.buildPartA();<br />　　　　builder.buildPartB();<br />　　　　builder.buildPartC(); </p>
										<p>　　} </p>
										<p>} </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>Builder的具体实现ConcreteBuilder:<br />通过具体完成接口Builder来构建或装配产品的部件;<br />定义并明确它所要创建的是什么具体东西;<br />提供一个可以重新获取产品的接口:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class ConcreteBuilder implements Builder { </p>
										<p>　　Part partA, partB, partC; <br />　　public void buildPartA() {<br />　　　　//这里是具体如何构建partA的代码<br /><br />　　}; <br />　　public void buildPartB() { <br />　　　　//这里是具体如何构建partB的代码<br />　　}; <br />　　 public void buildPartC() { <br />　　　　//这里是具体如何构建partB的代码<br />　　}; <br />　　 public Product getResult() { <br />　　　　//返回最后组装成品结果<br />　　}; <br /></p>
										<p>}</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>复杂对象:产品Product:<br /></p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public interface Product { } </td>
						</tr>
				</tbody>
		</table>
		<p>复杂对象的部件:</p>
		<table cellspacing="3" cellpadding="3" width="80%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public interface Part { }</td>
						</tr>
				</tbody>
		</table>
		<p>
				<br />我们看看如何调用Builder模式:<br />ConcreteBuilder builder = new ConcreteBuilder();<br />Director director = new Director( builder ); <br /><br />director.construct(); <br />Product product = builder.getResult(); </p>
		<p>
				<b>Builder模式的应用<br /></b>在Java实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池.</p>
		<p>"池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能.修改Builder模式中Director类使之能诊断"断肢"断在哪个部件上,再修复这个部件.</p>
		<p>具体英文文章见:<a href="http://www.javaworld.com/javaworld/javatips/jw-javatip78-p2.html#resources" target="_blank">Recycle broken objects in resource pools<br /></a></p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:42 <a href="http://www.blogjava.net/powerwind/articles/87009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Prototype(原型)</title><link>http://www.blogjava.net/powerwind/articles/87007.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:41:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/87007.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/87007.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/87007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/87007.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/87007.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之Prototype(原型)</h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">板桥里人</a> http://www.jdon.com 2002/05/07</p>
		<p>原型模式定义:<br />用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.</p>
		<p>Prototype模式允许一个对象再创建另外一个可定制的对象，根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象，这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。</p>
		<p>如何使用?<br />因为Java中的提供clone()方法来实现对象的克隆,所以Prototype模式实现一下子变得很简单.</p>
		<p>以勺子为例：</p>
		<table cellspacing="3" cellpadding="3" width="96%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">public abstract class AbstractSpoon implements Cloneable<br />{ <br />　　String spoonName; <br /><br />　　public void setSpoonName(String spoonName) {this.spoonName = spoonName;}<br />　　public String getSpoonName() {return this.spoonName;}<br /><br />　　public Object clone() <br />　　{<br />　　　　Object object = null;<br />　　　　try {<br />　　　　　　object = super.clone();<br />　　　　} catch (CloneNotSupportedException exception) {<br />　　　　　　System.err.println("AbstractSpoon is not Cloneable");<br />　　　　}<br />　　　　return object;<br />　　}<br />}<br /></td>
						</tr>
				</tbody>
		</table>
		<p>有个具体实现(ConcretePrototype):</p>
		<table cellspacing="3" cellpadding="3" width="92%" border="0">
				<tbody>
						<tr>
								<td bgcolor="#cccccc">
										<p>public class SoupSpoon extends AbstractSpoon<br />{ <br />　　public SoupSpoon()<br />　　{<br />　　　　setSpoonName("Soup Spoon"); <br />　　}<br />}<br /></p>
										<p>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>调用Prototype模式很简单:</p>
		<p>AbstractSpoon spoon = new SoupSpoon();<br />AbstractSpoon spoon2 = spoon.clone(); </p>
		<p>当然也可以结合工厂模式来创建AbstractSpoon实例。</p>
		<p>在Java中Prototype模式变成clone()方法的使用，由于Java的纯洁的面向对象特性，使得在Java中使用设计模式变得很自然，两者已经几乎是浑然一体了。这反映在很多模式上，如Interator遍历模式。</p>
<img src ="http://www.blogjava.net/powerwind/aggbug/87007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:41 <a href="http://www.blogjava.net/powerwind/articles/87007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式之Factory</title><link>http://www.blogjava.net/powerwind/articles/86992.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Mon, 11 Dec 2006 11:28:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/86992.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/86992.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/86992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/86992.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/86992.html</trackback:ping><description><![CDATA[
		<h3 align="center">设计模式之<span lang="EN-US">Factory</span></h3>
		<p align="center">
				<a href="http://www.jdon.com/aboutme.htm">板桥里人</a> http://www.jdon.com 2002/10/07（转载请保留）</p>
		<p>
				<b>
						<i>工厂模式定义<span lang="EN-US">:提供创建对象的接口.</span></i>
				</b>
		</p>
		<p>
				<b>
						<i>为何使用<span lang="EN-US">?</span></i>
				</b>
				<span lang="EN-US">
						<br />工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式，工厂模式在Java程序系统可以说是随处可见。</span>
		</p>
		<p>为什么工厂模式是如此常用？因为工厂模式就相当于创建实例对象的<span lang="EN-US">new，我们经常要根据类Class生成实例对象，如A a=new A() 工厂模式也是用来创建实例对象的，所以以后new时就要多个心眼，是否可以考虑实用工厂模式，虽然这样做，可能多做一些工作，但会给你系统带来更大的可扩展性和尽量少的修改量。</span></p>
		<p>我们以类<span lang="EN-US">Sample为例， 如果我们要创建Sample的实例对象:</span></p>
		<p>
				<span lang="EN-US">Sample sample=new Sample();</span>
		</p>
		<p>可是，实际情况是，通常我们都要在创建<span lang="EN-US">sample实例时做点初始化的工作,比如赋值 查询数据库等。</span></p>
		<p>首先，我们想到的是，可以使用<span lang="EN-US">Sample的构造函数，这样生成实例就写成:</span></p>
		<p>
				<span lang="EN-US">Sample sample=new Sample(参数);</span>
		</p>
		<p>但是，如果创建<span lang="EN-US">sample实例时所做的初始化工作不是象赋值这样简单的事，可能是很长一段代码，如果也写入构造函数中，那你的代码很难看了（就需要Refactor重整）。</span></p>
		<p>为什么说代码很难看，初学者可能没有这种感觉，我们分析如下，初始化工作如果是很长一段代码，说明要做的工作很多，将很多工作装入一个方法中，相当于将很多鸡蛋放在一个篮子里，是很危险的，这也是有背于<span lang="EN-US">Java面向对象的原则，面向对象的封装(Encapsulation)和分派(Delegation)告诉我们，尽量将长的代码分派“切割”成每段，将每段再“封装”起来(减少段和段之间偶合联系性)，这样，就会将风险分散，以后如果需要修改，只要更改每段，不会再发生牵一动百的事情。</span></p>
		<p>在本例中，首先，我们需要将创建实例的工作与使用实例的工作分开<span lang="EN-US">, 也就是说，让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。</span></p>
		<p>这时我们就需要<span lang="EN-US">Factory工厂模式来生成对象了，不能再用上面简单new Sample(参数)。</span>还有<span lang="EN-US">,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.</span>现在<span lang="EN-US">Sample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:</span></p>
		<p>
				<span lang="EN-US">Sample mysample=new MySample();<br />Sample hissample=new HisSample();</span>
		</p>
		<p>随着项目的深入<span lang="EN-US">,Sample可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.</span></p>
		<p>但如果你一开始就有意识使用了工厂模式<span lang="EN-US">,这些麻烦就没有了.</span></p>
		<p>
				<strong>工厂方法<br /></strong>你会建立一个专门生产<span lang="EN-US">Sample实例的工厂:</span></p>
		<table style="WIDTH: 80%; mso-cellspacing: 2.2pt; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt" cellspacing="3" cellpadding="0" width="80%" border="0">
				<tbody>
						<tr>
								<td style="PADDING-RIGHT: 2.25pt; PADDING-LEFT: 2.25pt; BACKGROUND: #cccccc; PADDING-BOTTOM: 2.25pt; PADDING-TOP: 2.25pt">
										<p>
												<span lang="EN-US">public class Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public static Sample creator(int which){</span></p>
										<p>　　//getClass <span lang="EN-US">产生Sample 一般可使用动态类装载装入类。<br />　　if (which==1)<br />　　　　return new SampleA();<br />　　else if (which==2)<br />　　　　return new SampleB();</span></p>
										<p>　　<span lang="EN-US">}</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>那么在你的程序中<span lang="EN-US">,如果要实例化Sample时.就使用</span></p>
		<p>
				<span lang="EN-US">Sample sampleA=Factory.creator(1);</span>
		</p>
		<p>这样<span lang="EN-US">,在整个就不涉及到Sample的具体子类,达到封装效果,也就减少错误修改的机会,这个原理可以用很通俗的话来比喻:就是具体事情做得越多,越容易范错误.这每个做过具体工作的人都深有体会,相反,官做得越高,说出的话越抽象越笼统,范错误可能性就越少.好象我们从编程序中也能悟出人生道理?呵呵.</span></p>
		<p>使用工厂方法 要注意几个角色，首先你要定义产品接口，如上面的Sample,产品接口下有Sample接口的实现类,如SampleA,其次要有一个factory类，用来生成产品Sample，如下图，最右边是生产的对象Sample：</p>
		<p>
				<img height="178" src="http://www.jdon.com/designpatterns/images/factory.jpg" width="526" />
		</p>
		<p>进一步稍微复杂一点，就是在工厂类上进行拓展，工厂类也有继承它的实现类concreteFactory了<b><i>。</i></b></p>
		<p>
				<span lang="EN-US">
						<strong>抽象工厂</strong>
						<br />工厂模式中有: 工厂方法(Factory Method) 抽象工厂(Abstract Factory).</span>
		</p>
		<p style="MARGIN-BOTTOM: 12pt">
				<span lang="EN-US">这两个模式区别在于需要创建对象的复杂程度上。如果我们创建对象的方法变得复杂了,如上面工厂方法中是创建一个对象Sample,如果我们还有新的产品接口Sample2.</span>
		</p>
		<p style="MARGIN-BOTTOM: 12pt">这里假设：Sample有两个concrete类SampleA和SamleB，而Sample2也有两个concrete类Sample2A和SampleB2</p>
		<p style="MARGIN-BOTTOM: 12pt">
				<span lang="EN-US">那么，我们就将上例中Factory变成抽象类,将共同部分封装在抽象类中,不同部分使用子类实现，下面就是将上例中的Factory拓展成抽象工厂:</span>
		</p>
		<table style="WIDTH: 80%; mso-cellspacing: 2.2pt; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt" cellspacing="3" cellpadding="0" width="100%" border="0">
				<tbody>
						<tr>
								<td style="PADDING-RIGHT: 2.25pt; PADDING-LEFT: 2.25pt; BACKGROUND: #cccccc; PADDING-BOTTOM: 2.25pt; PADDING-TOP: 2.25pt">
										<p>
												<span lang="EN-US">public abstract class Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public abstract Sample creator();</span></p>
										<p>　　<span lang="EN-US">public abstract Sample2 creator(String name); </span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">public class SimpleFactory extends Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public Sample creator(){<br />　　　　.........<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new SampleA</span><span lang="EN-US"><br />　　}</span></p>
										<p>　　<span lang="EN-US">public Sample2 creator(String name){<br />　　　　.........<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new Sample2A</span><span lang="EN-US"></span><span lang="EN-US"><br />　　}</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">public class BombFactory extends Factory{</span>
										</p>
										<p>　　<span lang="EN-US">public Sample creator(){<br />　　　　......<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new SampleB</span><span lang="EN-US"></span><span lang="EN-US"><br />　　}</span></p>
										<p>　　<span lang="EN-US">public Sample2 creator(String name){<br />　　　　......<br />　　<span lang="EN-US"></span>　　<span lang="EN-US"></span>return new Sample2B<br />　　}</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">
												</span> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
				<span lang="EN-US">从上面看到两个工厂各自生产出一套Sample和Sample2,也许你会疑问，为什么我不可以使用两个工厂方法来分别生产Sample和Sample2? </span>
		</p>
		<p>
				<span lang="EN-US">抽象工厂还有另外一个关键要点，是因为 SimpleFactory内，生产Sample和生产Sample2的方法之间有一定联系，所以才要将这两个方法捆绑在一个类中，这个工厂类有其本身特征，也许制造过程是统一的，比如：制造工艺比较简单，所以名称叫SimpleFactory。</span>
				<span lang="EN-US">
						<br />
				</span>
		</p>
		<p>在实际应用中，工厂方法用得比较多一些，而且是和动态类装入器组合在一起应用，</p>
		<p>
				<span lang="EN-US">
						<strong>举例</strong>
						<?XML:NAMESPACE PREFIX = O /?>
						<o:p>
						</o:p>
				</span>
		</p>
		<p>我们以<span lang="EN-US">Jive的ForumFactory为例，这个例子在前面的Singleton模式中我们讨论过，现在再讨论其工厂模式:</span></p>
		<table style="WIDTH: 97%; mso-cellspacing: 2.2pt; mso-padding-alt: 2.25pt 2.25pt 2.25pt 2.25pt" cellspacing="3" cellpadding="0" width="97%" border="0">
				<tbody>
						<tr>
								<td style="PADDING-RIGHT: 2.25pt; PADDING-LEFT: 2.25pt; BACKGROUND: #cccccc; PADDING-BOTTOM: 2.25pt; PADDING-TOP: 2.25pt">
										<p>
												<span lang="EN-US">public abstract class ForumFactory {</span>
										</p>
										<p>　　<span lang="EN-US">private static Object initLock = new Object();<br />　　private static String className = "com.jivesoftware.forum.database.DbForumFactory";<br />　　private static ForumFactory factory = null; </span></p>
										<p>　　<span lang="EN-US">public static ForumFactory getInstance(Authorization authorization) {<br />　　　　//If no valid authorization passed in, return null.<br />　　　　if (authorization == null) {<br />　　　　　　return null;<br />　　　　}<br />　　　　//以下使用了Singleton 单态模式<br />　　　　if (factory == null) {<br />　　　　　　synchronized(initLock) {<br />　　　　　　　　if (factory == null) {<br />　　　　　　　　　　　　...... </span></p>
										<p>　　　　　　　　　　<span lang="EN-US">try {<br />　　　　　　　　　　　　　　//动态转载类<br />　　　　　　　　　　　　　　Class c = Class.forName(className);<br />　　　　　　　　　　　　　　factory = (ForumFactory)c.newInstance();<br />　　　　　　　　　　}<br />　　　　　　　　　　catch (Exception e) {<br />　　　　　　　　　　　　　　return null;<br />　　　　　　　　　　}<br />　　　　　　　　}<br />　　　　　　}<br />　　　　}</span></p>
										<p>　　　　<span lang="EN-US">//Now, 返回 proxy.用来限制授权对forum的访问<br />　　　　return new ForumFactoryProxy(authorization, factory,<br />　　　　　　　　　　　　　　　　　　　　factory.getPermissions(authorization));<br />　　}</span></p>
										<p>　　<span lang="EN-US">//真正创建forum的方法由继承forumfactory的子类去完成.<br />　　public abstract Forum createForum(String name, String description)<br />　　throws UnauthorizedException, ForumAlreadyExistsException;</span></p>
										<p>　　<span lang="EN-US">....</span></p>
										<p>
												<span lang="EN-US">}</span>
										</p>
										<p>
												<span lang="EN-US">
												</span> </p>
										<p>
												<span lang="EN-US">
												</span> </p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>因为现在的<span lang="EN-US">Jive是通过数据库系统存放论坛帖子等内容数据,如果希望更改为通过文件系统实现,这个工厂方法ForumFactory就提供了提供动态接口:</span></p>
		<p>
				<span lang="EN-US">private static String className = "com.jivesoftware.forum.database.DbForumFactory";</span>
		</p>
		<p>你可以使用自己开发的创建<span lang="EN-US">forum的方法代替com.jivesoftware.forum.database.DbForumFactory就可以.</span></p>
		<p>在上面的一段代码中一共用了三种模式<span lang="EN-US">,除了工厂模式外,还有Singleton单态模式,以及proxy模式,proxy模式主要用来授权用户对forum的访问,因为访问forum有两种人:一个是注册用户 一个是游客guest,那么那么相应的权限就不一样,而且这个权限是贯穿整个系统的,因此建立一个proxy,类似网关的概念,可以很好的达到这个效果.  </span></p>
		<p>看看<span lang="EN-US">Java宠物店中的CatalogDAOFactory:</span></p>
		<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#cccccc" border="0">
				<tbody>
						<tr>
								<td>public class CatalogDAOFactory { 
<p></p><p>　　/**</p><p>　　* 本方法制定一个特别的子类来实现DAO模式。<br />　　* 具体子类定义是在J2EE的部署描述器中。<br />　　*/</p><p>　　public static CatalogDAO getDAO() throws CatalogDAOSysException {</p><p>　　　　CatalogDAO catDao = null;</p><p>　　　　try {</p><p>　　　　　　InitialContext ic = new InitialContext();<br />　　　　　　//动态装入CATALOG_DAO_CLASS<br />　　　　　　//可以定义自己的CATALOG_DAO_CLASS，从而在无需变更太多代码<br />　　　　　　//的前提下，完成系统的巨大变更。</p><p>　　　　　　String className =(String) ic.lookup(JNDINames.CATALOG_DAO_CLASS);</p><p>　　　　　　catDao = (CatalogDAO) Class.forName(className).newInstance();</p><p>　　　　} catch (NamingException ne) {</p><p>　　　　　　throw new CatalogDAOSysException("<br />　　　　　　　　CatalogDAOFactory.getDAO: NamingException while <br />　　　　　　　　　　getting DAO type : \n" + ne.getMessage());</p><p>　　　　} catch (Exception se) {</p><p>　　　　　　throw new CatalogDAOSysException("<br />　　　　　　　　CatalogDAOFactory.getDAO: Exception while getting <br />　　　　　　　　　　DAO type : \n" + se.getMessage());</p><p>　　　　}</p><p>　　　　return catDao;</p><p>　　}</p><p>}<br /></p></td>
						</tr>
				</tbody>
		</table>
		<p>
				<br style="mso-ignore: vglayout" clear="all" />
		</p>
		<p>
				<span lang="EN-US">CatalogDAOFactory是典型的工厂方法，catDao是通过动态类装入器className获得CatalogDAOFactory具体实现子类，这个实现子类在Java宠物店是用来操作catalog数据库，用户可以根据数据库的类型不同，定制自己的具体实现子类，将自己的子类名给与CATALOG_DAO_CLASS变量就可以。</span>
		</p>
		<p>由此可见，工厂方法确实为系统结构提供了非常灵活强大的动态扩展机制，只要我们更换一下具体的工厂方法，系统其他地方无需一点变换，就有可能将系统功能进行改头换面的变化。</p>
		<p>设计模式如何在具体项目中应用见<a href="http://www.jdon.com/mybook/index.htm" target="_blank">《Java实用系统开发指南》</a></p>
		<p> </p>
<img src ="http://www.blogjava.net/powerwind/aggbug/86992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-12-11 19:28 <a href="http://www.blogjava.net/powerwind/articles/86992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[导入]在Struts 2.0中实现表单数据校验（Validation）</title><link>http://www.blogjava.net/powerwind/articles/104477.html</link><dc:creator>powerwind</dc:creator><author>powerwind</author><pubDate>Tue, 14 Nov 2006 05:38:00 GMT</pubDate><guid>http://www.blogjava.net/powerwind/articles/104477.html</guid><wfw:comment>http://www.blogjava.net/powerwind/comments/104477.html</wfw:comment><comments>http://www.blogjava.net/powerwind/articles/104477.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/powerwind/comments/commentRss/104477.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/powerwind/services/trackbacks/104477.html</trackback:ping><description><![CDATA[     摘要: All Input Is Evil! -Writing secure code 在写前几篇文章的时候，有些朋友建议我的写一篇关于表单数据校验的文章。 正如文章的开头所引用的《Writing Secure Code》的名言：“所有的输入都是罪恶的”，所以我们应该对所有的外部...  <a href="/max/archive/2006/11/14/81106.html">阅读全文</a><img height="1" src="/max/aggbug/81106.html" width="1" /><br /><br /><div align="right"><a style="TEXT-DECORATION: none" href="/max/" target="_blank">Max</a> 2006-11-14 13:38 <a style="TEXT-DECORATION: none" href="/max/archive/2006/11/14/81106.html#Feedback" target="_blank">发表评论</a></div><br />文章来源:<a href="/max/archive/2006/11/14/81106.html">http://www.blogjava.net/max/archive/2006/11/14/81106.html</a><img src ="http://www.blogjava.net/powerwind/aggbug/104477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/powerwind/" target="_blank">powerwind</a> 2006-11-14 13:38 <a href="http://www.blogjava.net/powerwind/articles/104477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>