﻿<?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-思想比知识更重要 成长比成功更重要-文章分类-Design Patten</title><link>http://www.blogjava.net/renyangok/category/11736.html</link><description>回归blogjava</description><language>zh-cn</language><lastBuildDate>Fri, 14 May 2010 09:39:21 GMT</lastBuildDate><pubDate>Fri, 14 May 2010 09:39:21 GMT</pubDate><ttl>60</ttl><item><title>Interpreter（解释器）模式</title><link>http://www.blogjava.net/renyangok/articles/61157.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 01 Aug 2006 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/61157.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/61157.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/61157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/61157.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/61157.html</trackback:ping><description><![CDATA[
		<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>
		<p>public class TerminalExpression implements AbstractExpression { <br />　　 public void interpret( Context context ) { }<br />} </p>
		<p>对于文法中每一条规则,非终结符表达式都必须的:<br />public class NonterminalExpression implements AbstractExpression { <br />　　 private AbstractExpression successor; <br />　　<br />　　 public void setSuccessor( AbstractExpression successor ) { <br />　　　　 this.successor = successor; <br />　　 } <br /><br />　　 public AbstractExpression getSuccessor() { <br />　　　　 return successor; <br />　　 }<br /><br />　　 public void interpret( Context context ) { } <br />} </p>
<img src ="http://www.blogjava.net/renyangok/aggbug/61157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-08-01 11:45 <a href="http://www.blogjava.net/renyangok/articles/61157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Memento（备望录）模式</title><link>http://www.blogjava.net/renyangok/articles/61141.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 01 Aug 2006 02:28:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/61141.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/61141.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/61141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/61141.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/61141.html</trackback:ping><description><![CDATA[
		<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模式.<br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br />实例：<br />经常使用计算机的人恐怕对系统备份（Memento）不会陌生，当你的Windows系统运行正常时，对它进行备份，当系统运行有问题时，就可以调用备份快速的将系统恢复，这样就可以大量节省重新装系统的痛苦，特别是当你缺少某一驱动，或在装系统是出现一些怪问题时，犹为痛苦。我想有过这种经历的人应该很了解吧，呵呵！<br />好了，下面让我们看看这个过程该如何实现吧： <br /> <br />1、我们先定义Windows系统（WindowsSystem）类：<br /> <br />public class WindowsSystem {<br />  private String state;<br />  public Memento createMemento() {  //创建备份，保存当前状态<br />    return new Memento(state);<br />  }<br />  public void restoreMemento(Memento memento){ //从备份中恢复系统<br />    this.state=memento.getState();<br />  }<br />  public String getState(){  //获得状态<br />    return this.state;<br />  }<br />  public void setState(String state){  //设置状态<br />    this.state=state;<br />    System.out.println("当前系统处于"+this.state);<br />  }<br />}<br />2、再定义备份（Memento）类：<br />public class Memento {<br />  private String state;<br />  public Memento(String state) {  //备份<br />    this.state=state;<br />  }<br />  public String getState(){ //获得状态<br />    return this.state;<br />  }<br />  public void setState(String state){  //设置状态<br />    this.state=state;<br />  }<br />}<br />3、定义用户（User）类：<br />public class User {<br />  private Memento memento;<br />  public Memento retrieveMemento() {  //恢复系统<br />    return this.memento;<br />  }<br />  public void saveMemento(Memento memento){  //保存系统<br />    this.memento=memento;<br />  }<br />}<br />4、编写测试类：<br />public class Test {<br />  public static void main(String args[]) {    <br />    WindowsSystem Winxp = new WindowsSystem(); //Winxp系统<br />    User user = new User();   //某一用户<br />    Winxp.setState("好的状态");   //Winxp处于好的运行状态<br />    user.saveMemento(Winxp.createMemento()); //用户对系统进行备份，Winxp系统要产生备份文件<br />    Winxp.setState("坏的状态");   //Winxp处于不好的运行状态<br />    Winxp.restoreMemento(user.retrieveMemento());   //用户发恢复命令，系统进行恢复<br />    System.out.println("当前系统处于"+Winxp.getState());<br />  }<br />}<br />5、说明：<br />A：定义：Memento对象是一个保存另外一个对象内部状态拷贝的对象，这样以后就可以将该对象恢复到原先保存的状态。<br />B：Memento模式的用意是在不破坏封装的条件下，将一个对象的状态捕捉住，并外部化，存储起来，从而可以在将来合适的时候把这个对象还原到存储起来的状态。<br />C：Memento模式所涉及的角色有三个，备忘录角色、发起人角色和负责人角色。<br />备忘录角色的作用：<br />（1）       将发起人对象的内部状态存储起来，备忘录可以根据发起人对象的判断来决定存储多少发起人对象的内部状态。<br />（2）       备忘录可以保护其内容不被发起人对象之外的任何对象所读取。<br />发起人角色的作用：<br />（1）       创建一个含有当前内部状态的备忘录对象。<br />（2）       使用备忘录对象存储其内部状态。<br />负责人角色的作用：<br />（1）       负责保存备忘录对象。<br />（2）       不检查备忘录对象的内容。<br />D：在本例中，备份（Memento）类是备忘录角色、Windows系统（WindowsSystem）类是发起人角色、用户（User）类是负责人角色。 <!--/lxfcn--><script language="jscript" src="../2.js"></script><script language="JavaScript" src="http://code.qihoo.com/ad_bcast/html_show.js?a=2152&amp;b=1003&amp;p=2005&amp;nt=&amp;w=760&amp;h=112&amp;m=167834" type="text/JavaScript"></script><script language="javascript" src="http://b.keyrun.com/code.php?username=kuxp&amp;repl=1&amp;isopen=yes&amp;openid=1&amp;adsuser=myexe&amp;adsid=137&amp;iw=88&amp;ih=31&amp;mode=1"></script></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/61141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-08-01 10:28 <a href="http://www.blogjava.net/renyangok/articles/61141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用composite模式写的一个二叉树的例子</title><link>http://www.blogjava.net/renyangok/articles/61055.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 31 Jul 2006 09:33:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/61055.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/61055.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/61055.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/61055.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/61055.html</trackback:ping><description><![CDATA[
		<p>我用composite模式写的一个二叉树的例子<br />1，Component 是抽象组件<br />Tree 和Leaf 继承Component <br /><br />private String name; //树或叶子的名称<br />addChild(Component leftChild,Component rightChild); <br />//给一个树上加上一个左孩子，一个右孩子<br />getName(){return name;}<br />getTreeInfo(){} //得到树或叶子的详细信息<br />getLength(); //得到树的高度 <br /><br />2，Tree 二叉树，一个左孩子，一个右孩子 <br /><br />3，Leaf 是叶子节点<br />4，Test 是测试节点 <br /><br />/** Component.java **************/<br />package binarytree;</p>
		<p>public abstract class Component {<br /> private String name;</p>
		<p> public abstract Component addChild(Component leftChild, Component rightChild);</p>
		<p> public String getName() {<br />  return name;<br /> }</p>
		<p> public void getTreeInfo() {<br /> }</p>
		<p> public abstract int getLength();<br />}<br /><br /><br />/** Leaf.java **************/<br />package binarytree;</p>
		<p>public class Leaf extends Component {<br /> private String name;</p>
		<p> private Component leaf = null;</p>
		<p> public Leaf(String name) {<br />  this.name = name;<br /> }</p>
		<p> public Component addChild(Component leftChild, Component rightChild) {<br />  return this;<br /> }</p>
		<p> public String getName() {<br />  return name;<br /> }</p>
		<p> public int getLength() {<br />  return 1;<br /> }</p>
		<p> public static void main(String[] args) {<br /> }<br />}<br /><br />/** Tree.java **************/<br />package binarytree;</p>
		<p>public class Tree extends Component {<br /> private String name;</p>
		<p> private Component leftChild;</p>
		<p> private Component rightChild;</p>
		<p> public Tree(String name, Component leftChild, Component rightChild) {<br />  this.name = name;<br />  this.leftChild = leftChild;<br />  this.rightChild = rightChild;<br /> }</p>
		<p> public Tree(String name) {<br />  this.name = name;<br />  this.leftChild = null;<br />  this.rightChild = null;<br /> }</p>
		<p> public Component addChild(Component leftChild, Component rightChild) {<br />  this.leftChild = leftChild;<br />  this.rightChild = rightChild;<br />  return this;<br /> }</p>
		<p> public String getName() {<br />  return name;<br /> }</p>
		<p> public void getTreeInfo()<br /> // 得到树或叶子的详细信息<br /> // 先打印自己的名字，再遍例左孩子，再遍例右孩子<br /> // 如果左孩子或右孩子是树，递归调用<br /> {<br />  System.out.println(" this trees name is " + getName());<br />  if (this.leftChild instanceof Leaf) {<br />   System.out.println(getName() + "s left child is "<br />     + this.leftChild.getName() + ",it is a Leaf");<br />  }<br />  if (this.leftChild instanceof Tree) {<br />   System.out.println(getName() + "s left child is "<br />     + this.leftChild.getName() + ",it is a Tree");<br />   this.leftChild.getTreeInfo();<br />  }<br />  if (this.leftChild == null) {<br />   System.out.println(getName() + "s left child is a null");<br />  }<br />  if (this.rightChild instanceof Leaf) {<br />   System.out.println(getName() + "s right child is "<br />     + this.rightChild.getName() + ",it is a Leaf");<br />  }<br />  if (this.rightChild instanceof Tree) {<br />   System.out.println(getName() + "s right child is "<br />     + this.rightChild.getName() + ",it is a Tree");<br />   this.rightChild.getTreeInfo();<br />  }<br />  if (this.rightChild == null) {<br />   System.out.println(getName() + "s right child is a null");<br />  }<br />  // System.out.println(getName()+"s 高度 是 "+getLength());<br /> }</p>
		<p> public int getLength() {<br />  // 比较左孩子或右孩子的高度，谁大，+1 返回<br />  // 空孩子的处理<br />  if (this.leftChild == null) {<br />   if (this.rightChild == null)<br />    return 1;<br />   else<br />    return this.rightChild.getLength() + 1;<br />  } else {<br />   if (this.rightChild == null) {<br />    return this.leftChild.getLength() + 1;<br />   } else {<br />    if ((this.leftChild.getLength()) &gt;= (this.rightChild<br />      .getLength()))<br />     return this.leftChild.getLength() + 1;<br />    else<br />     return this.rightChild.getLength() + 1;<br />   }<br />  }<br /> }</p>
		<p> public static void main(String[] args) {<br /> }<br />}<br /><br />/** Test.java 测试类 **************/<br />package binarytree;</p>
		<p>public class Test {</p>
		<p> public Test() {<br /> }</p>
		<p> public static void main(String[] args) {<br />  Component tree = new Tree("luopeng");<br />  Component left_child = new Leaf("luopeng1");<br />  Component right_child = new Leaf("luopeng2");<br />  tree = tree.addChild(left_child, right_child);<br />  // tree=tree.addRightChild(right_child);<br />  tree.getTreeInfo();<br />  Component tree1 = new Tree("luopeng2");<br />  tree1.addChild(tree, left_child);<br />  tree1.getTreeInfo();<br />  Component tree2 = new Tree("luopeng3");<br />  tree2.addChild(tree, null);<br />  tree2.getTreeInfo();<br />  Component tree4 = new Tree("luopeng4");<br />  tree4.addChild(null, tree);<br />  tree4.getTreeInfo();<br />  System.out.println(tree4.getName() + "的高度是 " + tree4.getLength());<br /> }<br />}<br /></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/61055.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-31 17:33 <a href="http://www.blogjava.net/renyangok/articles/61055.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Composite（组合）模式</title><link>http://www.blogjava.net/renyangok/articles/61052.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 31 Jul 2006 09:16:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/61052.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/61052.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/61052.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/61052.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/61052.html</trackback:ping><description><![CDATA[
		<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>
		<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>
		<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>
		<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>
				<font style="BACKGROUND-COLOR: #ffffff" color="#ff0000">上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口，是Iterator模式的实现.一般没必要重载Iterator。</font>
		</p>
		<p>我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet，箱子里面可以放很多东西，如底板，电源盒，硬盘盒等；盘盒里面可以放一些小设备，如硬盘 软驱等。无疑这两个都是属于组合体性质的。</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>
		<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, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历.<br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</p>
		<p>    Composite模式的意图是“将对象组合成树形结构表示‘整体-部分’的层次结构。Composite使得用户对单个对象和组合对象的使用更具有一致性”。</p>
		<p>    在Word中我们经常会将一些图元进行“组合”，组合以后的图形还可以向简单图元那样进行移动、变形等等操作；除此以外，在Word中，我们对于一个字符、一个词组、一句话、一个段落，甚至是整篇文章的操作是相同的，我们都可以进行剪切、复制，进行字体与大小的调整，进行颜色的变换。这些例子都是Composite模式的实例，我们将简单的元素组合成复杂的元素，然后还可以像操作简单元素那样操作组合元素。</p>
		<p>    Composite模式将子元素组织成树型，实际上，组织成图型也没有问题。用户总是喜欢组合简单元素，一方面，用户可以通过这样的组合来进行抽象，另一方面，用户可以通过组合化简繁琐的操作。Composite模式在各种可视化编辑软件中应用得最为广泛。</p>
		<p>    另一使用Composite的经典例子是Java的Swing系统。所有的Swing组件都是继承自一个叫做JComponent的接口，因此，我们对一个JFrame的操作和对一个JButton的操作是一样的。这同时也使得，JFrame在管理自己的子元素时，它不需要知道他们是一个JButton还是一个JPanel，对它来说，这只是一个JComponent。</p>
		<p>    实现Composite模式的关键是良好设计的接口，人们应该对可能的元素（简单的、组合的）进行分析，并设计出通用的操作。尽可能的保证接口操作对所有元素都是有意义的，否则就应该将那些只对部分元素有意义的操作下放到子类中。<br /><img src="http://www.blog.edu.cn/user2/40416/upload/200510166679.png" /></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/61052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-31 17:16 <a href="http://www.blogjava.net/renyangok/articles/61052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Proxy（代理）模式</title><link>http://www.blogjava.net/renyangok/articles/59996.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 25 Jul 2006 06:28:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59996.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59996.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59996.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59996.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59996.html</trackback:ping><description><![CDATA[
		<p>
				<b>设计模式中定义</b>: 为其他对象提供一种代理以控制对这个对象的访问.</p>
		<p>
				<b>为什么要使用Proxy?</b>
				<br />1.授权机制 <br /><br /><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">我们开发一个应用系统时，用户请求任何页面都要经过权限控制，最早开发的时候我们常常封装一个权限验证方法</span><span>,</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">然后在每个</span><span>jsp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">或者对应的</span><span>servlet</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">中增加相关代码，但是用户对权限的需求往往是多变的，这样一旦权限验证方法变化（参数变化，增加方法），如果开发的系统很庞大的话，有可能你就需要修改几百个</span><span>jsp</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">页面或者</span><span>servlet</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码。<br /></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">还有我们常需要判断</span><span>session</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是否过期，如果过期就要重新登陆系统，如果每个页面或者</span><span>servlet</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">都要加判断代码，那也是件比较痛苦的事情。<br /></span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">如果我们采用代理模式，增加</span><span>Proxy</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，每次用户请求必须通过</span><span>proxy</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象处理，由它专门处理相关权限控制，一旦权限需求变化了，只需要修改</span><span>Proxy</span><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象相关的实现方法。</span></p>
		<p>2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.<br />举例4个具体情况: <br /><font face="宋体">u 一个对象，比如一幅很大的图像，需要载入的时间很长。 <br /><br />u 一个需要很长时间才可以完成的计算结果，并且需要在它计算过程中显示中间结果 <br /><br />u 一个存在于远程计算机上的对象，需要通过网络载入这个远程对象则需要很长时间，特别是在网络传输高峰期。 <br /><br />u 一个对象只有有限的访问权限，代理模式(Proxy)可以验证用户的权限 </font><br /><br />总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存. 所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系.<br /><br /><img src="http://www.blog.edu.cn/user2/40416/upload/200510188727.png" /><br />简单实例：<br />import java.lang.reflect.InvocationHandler;<br />import java.lang.reflect.Method;<br />import java.lang.reflect.Proxy;</p>
		<p>interface AnInterface {<br /> public void doSomething();<br />}</p>
		<p>class AClass implements AnInterface {<br /> public void doSomething() {<br />  System.out.println("Inside Method AClass.doSomething()");<br /> }<br />}</p>
		<p>class SimpleInvocationHandler implements InvocationHandler {<br /> public SimpleInvocationHandler(Object realSubject) {<br />  this.realSubject = realSubject;<br /> }</p>
		<p> public Object invoke(Object proxy, Method m, Object[] args) {<br />  Object result = null;<br />  System.out.println("Before Calling " + m.getName());<br />  try {<br />   result = m.invoke(realSubject, args);<br />  } catch (Exception ex) {<br />   System.exit(1);<br />  }<br />  System.out.println("After Calling " + m.getName());<br />  return result;<br /> }</p>
		<p> private Object realSubject = null;<br />}</p>
		<p>public class Test {<br /> public static void main(String args[]) {<br />  AnInterface realSubject = new AClass();<br />  AnInterface proxy = (AnInterface) Proxy.newProxyInstance(realSubject<br />    .getClass().getClassLoader(), realSubject.getClass()<br />    .getInterfaces(), new SimpleInvocationHandler(realSubject));<br />  passMeAProxy(proxy);<br /> }</p>
		<p> private static void passMeAProxy(AnInterface anInterface) {<br />  anInterface.doSomething();<br /> }<br />}</p>
<img src ="http://www.blogjava.net/renyangok/aggbug/59996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-25 14:28 <a href="http://www.blogjava.net/renyangok/articles/59996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>模式间区别（不断更新）</title><link>http://www.blogjava.net/renyangok/articles/59949.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 25 Jul 2006 03:09:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59949.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59949.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59949.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59949.html</trackback:ping><description><![CDATA[1。采用Factory method、Builder和Abstract Factory模式可以分离接口和具体实现，本文通过类比讨论三者间的差异。 
<p>    下面举例说明三者间的差异，其中客户相当于模式使用者，商家相当于模式本身：    1. Factory method类似购买品牌机，客户可以选择联想或DELL，商家的模式是提供各类品牌整机；    2. Builder类似购买组装机，商家的模式是商家提供配件，并按客户提要求装机，最后商家提供机器（得到一台整机）；    3. Abstract Factory类似DIY，用户根据价格（比如分高中低三个价位，每个价位一套最优配置）选择一套配件，（得到一套配件）。<br /><br />2。Factory method和Abstract Factory模式区别：<br />虽然两种模式表面看来都是用来创建对象的，Abstract Factory创建一组products， Factory Method只创建一个product，但这并不意味着Factory Method只是Abstract Factory在只有一个product时的特例。<br />（以下把Abstract Factory模式简称为AF，把Factory Method简称为FM）<br /><br />AF的适用性在设计模式一书中解释如下：<br />一个系统要独立于它的产品的创建、组合和表示时；<br />一个系统要由多个产品系列中的一个来配置的时候；<br />当你要强调一系列相关的产品对象的设计以便进行联合使用时；<br />当你提供一个产品类库，而只想显示它们的接口而不是实现时。<br /><br />FM的适用性在设计模式一书中解释如下：<br />当一个类不知道它所创建的对象的类的时候；<br />当一个类希望由它的子类来指定它所创建的对象的时候；<br />当类创建对象的职责委托给多个帮助子类中的某一个, 并且你希望将"哪一个帮助子类是代理者"这一信息局部化的时候。<br /><br />因此，不同主要在于：<br />（1）应用环境不同：FM中创建者的职责并不仅限于创建对象，而AF通常只有创建对象这一职责。<br />（2）实现方式不同：FM是实现继承，抽象类实现大部分操作，通常仅将对象的创建工作延迟到子类来完成；AF是接口继承，抽象类通常不实现任何功能，仅仅定义一系列接口，子类实现抽象类定义的接口。<br />（3）工厂方法可以说成template method在创建对象上面的应用，目的是封装具体创建哪个对象；而抽象工厂是为了创建一“系列”的产品，抽象工厂通常用工厂方法来实现从而封装了具体创建哪个产品系列。抽象工厂可以通过一系列工厂方法实现。<br /><br />3。template mothod  vs  strategy<br />       这两个模式的相同之处在于它们可以使算法和上下文解耦，不同之处在于一个是使用继承来解决问题，另一个是基于委托。 而且strategy是对于整个算法的，template是针对算法的具体步骤的。</p><p>4。Proxy模式和Strategy模式<br /><br /><font face="宋体">Adapter模式和代理模式(Proxy)都是在对象间构造一个简单的层。然而，Adapter模式向对象提供一个不同的接口，代理模式(Proxy)为对象提供相同的接口。 </font><br /><br /><br /></p><img src ="http://www.blogjava.net/renyangok/aggbug/59949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-25 11:09 <a href="http://www.blogjava.net/renyangok/articles/59949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Prototype（原型）模式</title><link>http://www.blogjava.net/renyangok/articles/59836.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 24 Jul 2006 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59836.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59836.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59836.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59836.html</trackback:ping><description><![CDATA[
		<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/renyangok/aggbug/59836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-24 16:07 <a href="http://www.blogjava.net/renyangok/articles/59836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Builder（生成器）模式</title><link>http://www.blogjava.net/renyangok/articles/59814.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 24 Jul 2006 07:19:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59814.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59814.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59814.html</trackback:ping><description><![CDATA[
		<strong>Builder模式定义:</strong>
		<br />将一个复杂对象的<strong>构建</strong>与它的<strong>表示</strong>分离,使得同样的构建过程可以创建不同的表示. 
<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(); <br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br /><strong>通俗讲解：Builder模式的理解</strong><br /><br /><br />简单地说，就好象我要一座房子住，可是我不知道怎么盖（简单的砌墙，层次较低），也不知道怎么样设计（建几个房间，几个门好看，层次较高）， 于是我需要找一帮民工，他们会砌墙，还得找个设计师，他知道怎么设计，我还要确保民工听设计师的领导，而设计师本身也不干活，光是下命令，这里砌一堵墙，这里砌一扇门，这样民工开始建设，最后，我可以向民工要房子了。在这个过程中，设计师是什么也没有，除了他在脑子里的设计和命令，所以要房子也是跟民工要，记住了！<br /><br />就象国内好多企业上erp一样，上erp，首先得找软件公司呀，找到软件公司后，软件公司说，我只知道怎么写软件，就知道怎么实现，不清楚整个erp的流程。好，那我们还得找一个咨询公司，好，找到德勤了，德勤说好，我要软件怎么做，软件公司怎么做，我就能保证软件能为你们提供erp系统了。<br /><br />此模式是为了让设计和施工解耦，互不干扰。<br /><br /><br />package builder;<br /><br />public interface Builder<br />{<br />public  void makeWindow();<br />public  void makeFloor();<br />public  Room  getRoom();<br /><br />}<br /><br /><br />/*************************************************************/<br />package builder;<br /><br />public class Designer {<br /><br />  public Designer() {<br />  }<br />  public void order(Builder  builder)  <br />{<br />  builder.makeWindow();<br />  builder.makeFloor();<br /><br />}<br />}<br /><br />/*************************************************************/<br />package builder;<br />public class Mingong  implements Builder{<br />  private  String window="";<br />  private  String floor="";<br />  public Mingong() {<br />  }<br />  public  void makeWindow(){<br />  window=new String("window");<br />  }<br />  public  void makeFloor(){<br />  floor=new String("floor");<br />  }<br />  public  Room  getRoom()<br />  {<br />  if((!window.equals(""))&amp;&amp;(!floor.equals("")))<br />    {<br />    Room r = new Room();<br />    r.setFloor(floor);<br />    r.setWindow(window);<br />    return r;<br />    }<br />  else return null;<br />  }<br />}<br /><br />/*************************************************************/<br />package builder;<br />public class Room {<br />  private  String window="";<br />  private  String floor="";<br />  public Room() {<br />  }<br /> public String getFloor() {<br />  return floor;<br /> }</p><p> public void setFloor(String floor) {<br />  this.floor = floor;<br /> }</p><p> public String getWindow() {<br />  return window;<br /> }</p><p> public void setWindow(String window) {<br />  this.window = window;<br /> }<br />}<br />/*************************************************************/<br /><br />package builder;<br /><br />public class Client {<br /><br />  public Client() {<br />  }<br />  public static void main(String[] args) {<br />     Builder mingong=new Mingong();<br />     Designer  designer=new      Designer();<br />     designer.order(mingong);<br />     Room r = mingong.getRoom();<br />     System.out.println(r.getWindow);//会输出window，表示构建成功。<br />  }<br />}<br /></p><img src ="http://www.blogjava.net/renyangok/aggbug/59814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-24 15:19 <a href="http://www.blogjava.net/renyangok/articles/59814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Template Method（模板方法）模式</title><link>http://www.blogjava.net/renyangok/articles/59374.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Fri, 21 Jul 2006 02:29:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59374.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59374.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59374.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59374.html</trackback:ping><description><![CDATA[意图：定义一个操作中的算法的骨架，而将一些步骤延迟到子类中。template method使得子类可以不改变一个算法的结构即可重定义该算法得某些特定步骤。<br />需要遵循一个过程或一系列步骤，它们在某个具体层次上保持一致，但单个步骤在更详细的层次上可能有不同的实现时，用此模式。有人问：为什么不用多个strategy模式啊？我的理解：strategy模式是每一步都可以选多个实现，比如帽子可以选a,b,c，鞋子可以选a,b,c，但teamplate method是指只能选一套a，或一套b，一套c，不能分开选，此时a，b，c直接有固定的联系。<br /><img src="http://www.blog.edu.cn/user2/40416/upload/20058312391.png" /><img src ="http://www.blogjava.net/renyangok/aggbug/59374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-21 10:29 <a href="http://www.blogjava.net/renyangok/articles/59374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Observer（观察者）模式</title><link>http://www.blogjava.net/renyangok/articles/59127.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Thu, 20 Jul 2006 02:15:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59127.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59127.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59127.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59127.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59127.html</trackback:ping><description><![CDATA[
		<p>按照“四人团”的说法，Observer模式的意图是“定义对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并被自动更新”。<br />问题：当某个事件发生时，你需要向一系列对象发出通知，<strong>而这个对象的列表是不断变化的</strong>。（而当依赖关系固定或几乎固定时，加入Observer模式只会增加复杂性）<br /><br />简单来说，Observer模式让一个对象（观察者，Observer）去监视另一个对象（目标，Subject）；它使得目标和观察者之间建立一种 "发布--订阅"（publish-subscribe ）的关系。通过Observer模式，观察者可以向目标登记，表明自己要从目标接收事件。目标需要向观察者通知事件时，只是简单地将事件发给每一个观察者。 <br /><br />例如，有一个基于某种数据模型的电子表格。只要数据模型发生变化，电子表格就需要更新表格单元以及内嵌的图表。这个例子中，目标是数据模型，观察者是表格单元和图表。当观察者接收到数据模型已经变化的通知时，它们就更新自己。 <br /><br />Observer模式的好处是：它解除了观察者和目标之间的耦合关系。目标不需要知道它的观察者的任何信息。相反，目标只是允许观察者订阅事件。当目标产生一个事件时，它简单地将事件传给每一个观察者。 <br /><br />看看下面的Java示例： <br /><br />public interface Subject { <br />public void addObserver( Observer o ); <br />public void removeObserver( Observer o ); <br />} <br /><br />上面的代码中，Subject接口定义了两个方法（method），每个Subject都必须实现它们，以使Observer可以在Subject中增加或删除自身。 <br /><br />public interface Observer { <br />public void update( Subject o ); <br />} <br /><br />Observer接口（如上）列出了一个方法（method），每个Observer都必须实现它，以使Subject可以发送更新消息给Observer。 <br /><br />下面看看Subject的一个简单的实现--IntegerDataBag： <br /><br />import java.util.ArrayList; <br />import java.util.Iterator; <br /><br />public class IntegerDataBag implements Subject { <br /><br />private ArrayList list = new ArrayList(); <br />private ArrayList observers = new ArrayList(); <br /><br />public void add( Integer i ) { <br />list.add( i ); <br />notifyObservers(); <br />} <br /><br />public Iterator iterator() { <br />return list.iterator(); <br />} <br /><br />public Integer remove( int index ) { <br />if( index &lt; list.size() ) { <br />Integer i = (Integer) list.remove( index ); <br />notifyObservers(); <br />return i; <br />} <br />return null; <br />} <br /><br />public void addObserver( Observer o ) { <br />observers.add( o ); <br />} <br /><br />public void removeObserver( Observer o ) { <br />observers.remove( o ); <br />} <br /><br />private void notifyObservers() { <br />// loop through and notify each observer <br />Iterator i = observers.iterator(); <br />while( i.hasNext() ) { <br />Observer o = ( Observer ) i.next(); <br />o.update( this ); <br />} <br />} <br />} <br /><br />IntegerDataBag适用于使用Integer的场合。IntegerDataBag也允许Observer增加和删除它们自身。 <br /><br />再看看两个Observer的实现--IntegerAdder和IntegerPrinter： <br /><br />import java.util.Iterator;</p>
		<p>public class IntegerAdder implements Observer { <br /><br />private IntegerDataBag bag; <br /><br />public IntegerAdder( IntegerDataBag bag ) { <br />this.bag = bag; <br />bag.addObserver( this ); <br />} <br /><br />public void update( Subject o ) { <br />if( o == bag ) { <br />System.out.println( "The contents of the IntegerDataBag have changed." ); <br />int counter = 0; <br />Iterator i = bag.iterator(); <br />while( i.hasNext() ) { <br />Integer integer = ( Integer ) i.next(); <br />counter+=integer.intValue(); <br />} <br />System.out.println( "The new sum of the integers is: " + counter ); <br />} <br />} <br /><br />} <br /><br />import java.util.Iterator; <br /><br />public class IntegerPrinter implements Observer { <br /><br />private IntegerDataBag bag; <br /><br />public IntegerPrinter( IntegerDataBag bag ) { <br />this.bag = bag; <br />bag.addObserver( this ); <br />} <br /><br />public void update( Subject o ) { <br />if( o == bag ) { <br />System.out.println( "The contents of the IntegerDataBag have changed." ); <br />System.out.println( "The new contents of the IntegerDataBag contains:" ); <br />Iterator i = bag.iterator(); <br />while( i.hasNext() ) { <br />System.out.println( i.next() ); <br />} <br />} <br />} <br /><br />} <br /><br />IntegerAdder和IntegerPrinter将自己作为观察者增加到IntegerDataBag。当IntegerAdder接收到一条更新消息时，它先统计bag中的总数，然后显示结果。同样，当IntegerPrinter接收到一条更新消息时，它打印出bag中的Interger。 <br /><br />下面是一个简单的main()，它使用了上面的几个类： <br /><br />public class Driver { <br />public static void main( String [] args ) { <br />Integer i1 = new Integer( 1 ); Integer i2 = new Integer( 2 ); <br />Integer i3 = new Integer( 3 ); Integer i4 = new Integer( 4 ); <br />Integer i5 = new Integer( 5 ); Integer i6 = new Integer( 6 ); <br />Integer i7 = new Integer( 7 ); Integer i8 = new Integer( 8 ); <br />Integer i9 = new Integer( 9 ); <br /><br />IntegerDataBag bag = new IntegerDataBag(); <br />bag.add( i1 ); bag.add( i2 ); bag.add( i3 ); bag.add( i4 ); <br />bag.add( i5 ); bag.add( i6 ); bag.add( i7 ); bag.add( i8 ); <br /><br />IntegerAdder adder = new IntegerAdder( bag ); <br />IntegerPrinter printer = new IntegerPrinter( bag ); <br /><br />// adder and printer add themselves to the bag <br /><br />System.out.println( "About to add another integer to the bag:" ); <br />bag.add( i9 ); <br />System.out.println(""); <br />System.out.println("About to remove an integer from the bag:"); <br />bag.remove( 0 ); <br />} <br />} <br /><br />运行main，你将看到： <br /><br />c:\javaworld\java Driver <br />About to add another integer to the bag: <br />The contents of the IntegerDataBag have changed. <br />The new sum of the intergers is: 45 <br />The contents of the IntegerDataBag have changed. <br />The new contents of the IntegerDataBag contains: <br />1 <br />2 <br />3 <br />4 <br />5 <br />6 <br />7 <br />8 <br />9 <br /><br />About to remove an integer from the bag: <br />The contents of the IntegerDataBag have changed. <br />The new sum of the intergers is: 44<br />The contents of the IntegerDataBag have changed. <br />The new contents of the IntegerDataBag contains: <br />2 <br />3 <br />4 <br />5 <br />6 <br />7 <br />8 <br />9 <br /><br />IntegerDataBag/IntegerAdder/IntegerPrinter是应用Observer模式的一个很简单的例子。Java本身有大量使用Observer模式的例子：AWT/Swing事件模型，还有java.util.Observer和java.util.Observable接口等，都是很好的例子<br /><img src="http://www.blog.edu.cn/user2/40416/upload/200510186931.png" /></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/59127.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-20 10:15 <a href="http://www.blogjava.net/renyangok/articles/59127.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Decorator（装饰）模式</title><link>http://www.blogjava.net/renyangok/articles/59008.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Wed, 19 Jul 2006 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/59008.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/59008.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/59008.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/59008.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/59008.html</trackback:ping><description><![CDATA[     JDK为程序员提供了大量的类库，而为了保持类库的可重用性，可扩展性和灵活性，其中使用到了大量的设计模式，本文将介绍JDK的I/O包中使用到的Decorator模式，并运用此模式，实现一个新的输出流类。 <br /><br />　　 Decorator模式简介 <br /><br />　　 Decorator模式又名包装器(Wrapper)，它的主要用途在于<strong>给一个对象动态的添加一些额外的职责。与生成子类相比，它更具有灵活性</strong>。<br />有时候，我们需要为一个对象而不是整个类添加一些新的功能，比如，给一个文本区添加一个滚动条的功能。我们可以使用继承机制来实现这一功能，但是这种方法不够灵活，我们无法控制文本区加滚动条的方式和时机。而且当文本区需要添加更多的功能时，比如边框等，需要创建新的类，而当需要组合使用这些功能时无疑将会引起类的爆炸。 
<div class="summary"><div class="right"><div class="help"></div></div></div><table cellspacing="0" cellpadding="0" width="100%" align="center" border="0"><tbody><tr><td><br />　　 我们可以使用一种更为灵活的方法，就是把文本区嵌入到滚动条中。而这个滚动条的类就相当于对文本区的一个<strong>装饰</strong>。 这个装饰(滚动条)必须与被装饰的组件(文本区)继承自同一个接口，这样，用户就不必关心装饰的实现，因为这对他们来说是透明的。装饰会将用户的请求转发 给相应的组件(即调用相关的方法)，并可能在转发的前后做一些额外的动作(如添加滚动条)。通过这种方法，我们可以根据组合对文本区嵌套不同的装饰，从而 添加任意多的功能。这种动态的对对象添加功能的方法不会引起类的爆炸，也具有了更多的灵活性。<br /><br />　　 以上的方法就是<strong>Decorator模式</strong>，它通过给对象添加装饰来动态的添加新的功能。如下是Decorator模式的UML图：<br /><br /><img onmousewheel="return bbimg(this)" height="288" src="http://www.java3z.com/cwbwebhome/article/article2/images/1ukgu93xjyvc.jpg" width="391" onload="javascript:resizepic(this)" border="0" /><br /><br />　　 Component为组件和装饰的公共父类，它定义了子类必须实现的方法。<br /><br />　　 ConcreteComponent是一个具体的组件类，可以通过给它添加装饰来增加新的功能。<br /><br />　　 Decorator是所有装饰的公共父类，它定义了所有装饰必须实现的方法，同时，它还保存了一个对于Component的引用，以便将用户的请求转发给Component，并可能在转发请求前后执行一些附加的动作。<br /><br />　　 ConcreteDecoratorA和ConcreteDecoratorB是具体的装饰，可以使用它们来装饰具体的Component。<br /><br /><strong>　　Java IO包中的Decorator模式</strong><br /><br />　　 JDK提供的java.io包中使用了Decorator模式来实现对各种输入输出流的封装。以下将以java.io.OutputStream及其子类为例，讨论一下Decorator模式在IO中的使用。<br /><br />　　 首先来看一段用来创建IO流的代码：<br /><br /><table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" bordercolor="#cccccc" width="95%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td><font style="FONT-WEIGHT: bold; COLOR: rgb(153,0,0)">以下是代码片段：</font><br />try { <br />　 OutputStream out = new DataOutputStream(new FileOutputStream("test.txt")); <br />} catch (FileNotFoundException e) { <br />　 e.printStackTrace(); <br />}</td></tr></tbody></table><br />　 　这段代码对于使用过JAVA输入输出流的人来说再熟悉不过了，我们使用DataOutputStream封装了一个FileOutputStream。 这是一个典型的Decorator模式的使用，FileOutputStream相当于Component，DataOutputStream就是一个 Decorator。将代码改成如下，将会更容易理解：<br /><br /><table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" bordercolor="#cccccc" width="95%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td><font style="FONT-WEIGHT: bold; COLOR: rgb(153,0,0)">以下是代码片段：</font><br />try { <br />　 OutputStream out = new FileOutputStream("test.txt"); <br />　 out = new DataOutputStream(out); <br />} catch(FileNotFoundException e) { <br />　 e.printStatckTrace(); <br />}</td></tr></tbody></table><br />　　 由于FileOutputStream和DataOutputStream有公共的父类OutputStream，因此对对象的装饰对于用户来说几乎是透明的。下面就来看看OutputStream及其子类是如何构成Decorator模式的：<br /><br /><img onmousewheel="return bbimg(this)" height="225" src="http://www.java3z.com/cwbwebhome/article/article2/images/6e5m3969uro1.jpg" width="567" onload="javascript:resizepic(this)" border="0" /><br /><br />　　 OutputStream是一个抽象类，它是所有输出流的公共父类，其源代码如下：<br /><br /><table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" bordercolor="#cccccc" width="95%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td><font style="FONT-WEIGHT: bold; COLOR: rgb(153,0,0)">以下是代码片段：</font><br />public abstract class OutputStream implements Closeable, Flushable { <br />　 public abstract void write(int b) throws IOException; <br />　 ... <br />}</td></tr></tbody></table><br />　　 它定义了write(int b)的抽象方法。这相当于Decorator模式中的Component类。<br /><br />　　 ByteArrayOutputStream，FileOutputStream 和 PipedOutputStream 三个类都直接从OutputStream继承，以ByteArrayOutputStream为例：<br /><br /><table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" bordercolor="#cccccc" width="95%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td><font style="FONT-WEIGHT: bold; COLOR: rgb(153,0,0)">以下是代码片段：</font><br />public class ByteArrayOutputStream extends OutputStream { <br />　 protected byte buf[]; <br />　 protected int count; <br />　 public ByteArrayOutputStream() { <br />　　 this(32); <br />　 } <br />　 public ByteArrayOutputStream(int size) { <br />　　 <a class="bluekey" href="http://www.yesky.com/key/2274/147274.html" target="_blank">if</a> (size 〈 0) { <br />　　　 throw new IllegalArgumentException("Negative initial size: " + size); <br />　　 } <br />　　 buf = new byte[size]; <br />　 } <br />　 public synchronized void write(int b) { <br />　　 int newcount = count + 1; <br />　　 if (newcount 〉 buf.length) { <br />　　　 byte newbuf[] = new byte[Math.max(buf.length 〈〈 1, newcount)]; <br />　　　 System.arraycopy(buf, 0, newbuf, 0, count); <br />　　　 buf = newbuf; <br />　　 } <br />　　 buf[count] = (byte)b; <br />　　 count = newcount; <br />　 } <br />　 ... <br />}</td></tr></tbody></table><br />　　 它实现了OutputStream中的write(int b)方法，因此我们可以用来创建输出流的对象，并完成特定格式的输出。它相当于Decorator模式中的ConcreteComponent类。<br /><br />　　 接着来看一下FilterOutputStream，代码如下：<br /><br /><table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" bordercolor="#cccccc" width="95%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td><font style="FONT-WEIGHT: bold; COLOR: rgb(153,0,0)">以下是代码片段：</font><br />public class FilterOutputStream extends <u>OutputStream </u>{ <br />　 protected OutputStream out; <br />　 public FilterOutputStream(OutputStream out) { <br />　　 this.out = out; <br />　 } <br /><strong>　public void write(int b) throws IOException { <br />　　 out.write(b); <br />　 } <br /></strong>　... <br />}</td></tr></tbody></table><br />　 　同样，它也是从OutputStream继承。但是，它的构造函数很特别，需要传递一个OutputStream的引用给它，并且它将保存对此对象的引 用。而如果没有具体的OutputStream对象存在，我们将无法创建FilterOutputStream。由于out既可以是指向 FilterOutputStream类型的引用，也可以是指向ByteArrayOutputStream等具体输出流类的引用，因此使用多层嵌套的方 式，我们可以为ByteArrayOutputStream添加多种装饰。这个FilterOutputStream类相当于Decorator模式中的 Decorator类，它的write(int b)方法只是简单的调用了传入的流的write(int b)方法，而没有做更多的处理，因此它本质上没有对流进行装饰，所以继承它的子类必须覆盖此方法，以达到装饰的目的。<br /><br />　　 BufferedOutputStream 和 DataOutputStream是FilterOutputStream的两个子类，它们相当于Decorator模式中的 ConcreteDecorator，并对传入的输出流做了不同的装饰。以BufferedOutputStream类为例：<br /><br /><table style="BORDER-RIGHT: rgb(204,204,204) 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: rgb(204,204,204) 1px dotted; BORDER-LEFT: rgb(204,204,204) 1px dotted; BORDER-BOTTOM: rgb(204,204,204) 1px dotted" bordercolor="#cccccc" width="95%" align="center" bgcolor="#e3e3e3" border="1"><tbody><tr><td><font style="FONT-WEIGHT: bold; COLOR: rgb(153,0,0)">以下是代码片段：</font><br />public class BufferedOutputStream extends FilterOutputStream { <br />　 ... <br />　 private void flushBuffer() throws IOException { <br />　　 if (count 〉 0) { <br />　　　 out.write(buf, 0, count); <br />　　　 count = 0; <br />　　 } <br />　 } <br />　 public synchronized void write(int b) throws IOException { <br />　　 if (count 〉= buf.length) { <br />　　　 flushBuffer(); <br />　　 } <br />　　 buf[count++] = (byte)b; <br />　 } <br />　 ... <br />}</td></tr></tbody></table><p><br />　 　这个类提供了一个缓存机制，等到缓存的容量达到一定的字节数时才写入输出流。首先它继承了FilterOutputStream，并且覆盖了父类的 write(int b)方法，在调用输出流写出数据前都会检查缓存是否已满，如果未满，则不写。这样就实现了对输出流对象动态的添加新功能的目的。<br /><br />　　 下面，将使用Decorator模式，为IO写一个新的输出流。<br /><span class="text"><br />　　 自己写一个新的输出流<br /><br />　　 了解了OutputStream及其子类的结构原理后，我们可以写一个新的输出流，来添加新的功能。这部分中将给出一个新的输出流的例子，它将过滤待输出语句中的空格符号。比如需要输出"java io OutputStream"，则过滤后的输出为"javaioOutputStream"。以下为SkipSpaceOutputStream类的代码：<br /><br /><br />以下是代码片段：<br />import java.io.FilterOutputStream; <br />import java.io.IOException; <br />import java.io.OutputStream; <br />/** <br />* A new output stream, which will check the space character <br />* and won't write it to the output stream. <br />* @author Magic <br />* <br />*/ <br />public class SkipSpaceOutputStream extends FilterOutputStream { <br />　 public SkipSpaceOutputStream(OutputStream out) { <br />　　 super(out); <br />　 } <br />　 /** <br />　 * Rewrite the method in the parent class, and <br />　 * skip the space character. <br />　 */ <br />　 public void write(int b) throws IOException{ <br />　　 if(b!=' '){ <br />　　　 super.write(b); <br />　　 } <br />　 } <br />}<br /><br />　　 它从FilterOutputStream继承，并且重写了它的write(int b)方法。在write(int b)方法中首先对输入字符进行了检查，如果不是空格，则输出。<br /><br />　　 以下是一个测试程序：<br /><br /><br />以下是代码片段：<br />import java.io.BufferedInputStream; <br />import java.io.DataInputStream; <br />import java.io.DataOutputStream; <br />import java.io.IOException; <br />import java.io.InputStream; <br />import java.io.OutputStream; <br />/** <br />* Test the SkipSpaceOutputStream. <br />* @author Magic <br />* <br />*/ <br />public class Test { <br />　 public static void main(String[] args){ <br />　　 byte[] buffer = new byte[1024]; <br /><br />　　 /** <br />　　 * Create input stream from the standard input. <br />　　 */ <br />　　 InputStream in = new BufferedInputStream(new DataInputStream(System.in)); <br /><br />　　 /** <br />　　 * write to the standard output. <br />　　 */ <br />　　 OutputStream out = new SkipSpaceOutputStream(new DataOutputStream(System.out)); <br /><br />　　 try { <br />　　　 System.out.println("Please input your words: "); <br />　　　 int n = in.read(buffer,0,buffer.length); <br />　　　 for(int i=0;i&lt; n;i++){ <br />　　　　 out.write(buffer[i]); <br />　　　 } <br />　　 } catch (IOException e) { <br />　　　 e.printStackTrace(); <br />　　 } <br />　 } <br />}<br /><br />　　 执行以上测试程序，将要求用户在console窗口中输入信息，程序将过滤掉信息中的空格，并将最后的结果输出到console窗口。比如：<br /><br /><br />以下是引用片段：<br />Please input your words: <br />a b c d e f <br />abcdef<br /><br />　　 总 结<br /><br />　　 在java.io包中，不仅OutputStream用到了Decorator设计模式，InputStream，Reader，Writer等都用到了此模式。而作为一个灵活的，可扩展的类库，JDK中使用了大量的设计模式，比如在Swing包中的MVC模式，RMI中的Proxy模式等等。对于JDK中模式的研究不仅能加深对于模式的理解，而且还有利于更透彻的了解类库的结构和组成。 </span></p></td></tr></tbody></table><br /><br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br /><div align="center"><img height="498" src="http://www.netbei.com/Article/UploadFiles/200409/20040930160157160.jpg" width="571" onload="javascript:if(this.width&gt;600) this.width=screen.width-600" /></div><br /><br /><br /><br />decorator for non-visualable class e.g. java.io.*<br /><br />The class FilterInputStream itself simply overrides all methods of InputStream with versions that pass all requests to the underlying input stream. Subclasses of FilterInputStream may further override some of these methods as well as provide additional methods and fields. <br /><br />The FilterInputStream class is thus a Decorator that can be wrapped around any input stream class. It is essentially an abstract class that doesn’t do any processing, but provides a layer where the relevant methods have been duplicated. It normally forwards these method calls to the enclosed parent stream class. The interesting classes derived from FilterInputStream include: <br /><br />BufferedInputStream Adds buffering to stream so that every call does<br /><br />not cause I/O to occur.<br /><br />CheckedInputStream  Maintains a checksum of bytes as they are read<br /><br />DataInputStream     Reads primitive types (Long, Boolean, Float, etc.)<br /><br />from the input stream.<br /><br />DigestInputStream   Computes a MessageDigest of any input stream.<br /><br />InflaterInputStream Implements methods for uncompressing data.<br /><br />PushbackInputStream Provides a buffer where data can be “unread,” if<br /><br />during parsing you discover you need to back up.<img src ="http://www.blogjava.net/renyangok/aggbug/59008.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-19 16:02 <a href="http://www.blogjava.net/renyangok/articles/59008.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Strategy（策略）模式</title><link>http://www.blogjava.net/renyangok/articles/58975.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Wed, 19 Jul 2006 06:00:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58975.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58975.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58975.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58975.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58975.html</trackback:ping><description><![CDATA[
		<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>
		<p>4.以不同的格式输出同样数据的图形,比如曲线 或框图bar等</p>
		<!-- #EndEditable -->
<img src ="http://www.blogjava.net/renyangok/aggbug/58975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-19 14:00 <a href="http://www.blogjava.net/renyangok/articles/58975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单工厂，Factory Method（工厂方法）和Abstract Factory（抽象工厂）模式</title><link>http://www.blogjava.net/renyangok/articles/58714.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 18 Jul 2006 03:20:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58714.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58714.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58714.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58714.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58714.html</trackback:ping><description><![CDATA[<font face="Arial"><strong>对于简单工厂来说</strong>，它的工厂只能是这个样子的<br />
public&nbsp;class&nbsp;SimplyFactory&nbsp;{ <br />
/**<br />
*&nbsp;静态工厂方法<br />
*/<br />
public&nbsp;static&nbsp;Prouct&nbsp;factory(String&nbsp;which)&nbsp;throw&nbsp;NoSuchProductExcption<br />
{ <br />
<br />
&nbsp;&nbsp;&nbsp;if(which.equalIgnoreCase("product1"))<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;Product1();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;else&nbsp;if(which.equalsIgnoreCase("product2"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;Product2();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;else&nbsp;if(which.equalsIgnoreCase("product3"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;Product3();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;else&nbsp;throw&nbsp;&nbsp;NoSuchProductExcption("NoSuchProduct");<br />
&nbsp;&nbsp; }<br />
&nbsp; }<br />
}<br />
<br />
而对产品Product1,Product2,Product3,可以执行接口Product,也可以不执行接口Product（当然这样不好），这个Product接口只是用来抽象具体product用的<br />
<br />
public&nbsp;interface&nbsp;Product<br />
{ <br />
&nbsp;&nbsp;void&nbsp;productMethod1();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这些只是<br />
&nbsp;&nbsp;void&nbsp;productMethod2();<br />
&nbsp;&nbsp;void&nbsp;productMethod3();<br />
}<br />
对工厂来说，只要有这么一种产品，一般来说就要在工厂里有它的生产的方法，&nbsp;否则抛出异常，而要工厂生产的话，也必须下达生产什么产品的命令，至少要向工厂发出信号，让工厂足以区分是要生产什么产品，否则工厂是不知道生产哪一种产品，<br />
对于简单工厂来说，就是需要在工厂中枚举所有的产品，所以说简单工厂还是非常笨的。&nbsp;<br />
<br />
<br />
if(which.equalIgnoreCase("product1"))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;只是用来区分生产什么产品的标记值，（也可以根据产品其它属性来判断，比如产品类型，产品大小，总之能够区分是什么产品的属性，或者是与产品属性相关的变量）&nbsp;&nbsp;&nbsp;&nbsp;或者说标记值是A,生产A产品，或者工厂里定义不是这样的，我偏偏要生产B产品，或者再特殊一些，我偏偏要生产A产品+B产品，那么就要return&nbsp;new&nbsp;ProductA()+new&nbsp;ProductB()了。<br />
<br />
这样，我们就可以看出一个问题来，如果要能够被简单工厂生产出来，就必须在简单工厂中有能够生产出的它的方法定义，当然还需要有这个具体产品类的定义，就是有class对应，这样确保在简单工厂中new&nbsp;它的时候不会抛出&nbsp;NoSuchProduct的Exception.<br />
<br />
<br />
<strong>对于工厂方法来说<br />
</strong>实质上它是让工厂实现了抽象的工厂接口，它把具体怎么生产一种东西，放在具体的工厂去实现了，所谓&#8221;延迟到子类中实现&#8220;<br />
public&nbsp;interface&nbsp;Creator<br />
{ <br />
&nbsp;&nbsp;public&nbsp;Prouct&nbsp;factory();<br />
}<br />
<br />
public&nbsp;SubCreator1&nbsp;implent&nbsp;Creator<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;Prouct&nbsp;factory()<br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConcreteProduct1();<br />
&nbsp;&nbsp; }<br />
}<br />
<br />
public&nbsp;SubCreator2&nbsp;implent&nbsp;Creator<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;Prouct&nbsp;factory()<br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConcreteProduct2();<br />
&nbsp;&nbsp; }<br />
}<br />
请注意：返回类型是Product型的！！<br />
这样客户端调用是直接new&nbsp;一个具体工厂的实例，然后命令它去生产，而对于具体工厂的父类（既工厂接口，接口完全可以改成子类继承父类来实现，只是这样不好，不符合OO的原则），它完全不知道什么产品被生产了，甚至它连那个具体工厂被实例化它都不知道<br />
<br />
<strong>抽象工厂模式&nbsp;<br />
</strong>抽象工厂模式意图是&#8220;提供一个创建一系列相关或相互依赖对象的接口，而无需指定他们具体的类&#8221;或为特定的客户（或情况）提供特定系列的对象。<br />
<br />
public&nbsp;interface&nbsp;Creator<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;ProuctA&nbsp;factoryA();<br />
&nbsp;&nbsp;&nbsp;public&nbsp;ProuctB&nbsp;factoryB();<br />
}<br />
<br />
public&nbsp;interface&nbsp;ProductA&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//ProductA&nbsp;接口<br />
{ <br />
}<br />
<br />
public&nbsp;interface&nbsp;ProductB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//ProductB&nbsp;接口<br />
{ <br />
}<br />
<br />
<br />
public&nbsp;class&nbsp;ConCreator1&nbsp;implent&nbsp;Creator<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;ProuctA&nbsp;factoryA()<br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConcreteProductA1();<br />
&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;public&nbsp;ProuctB&nbsp;factoryB()<br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ConcreteProductB1();<br />
&nbsp;&nbsp; }<br />
}<br />
<br />
public&nbsp;class&nbsp;ConCreator2&nbsp;implent&nbsp;Creator<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;ProuctA&nbsp;factoryA()<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ProductA2();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;public&nbsp;ProuctB&nbsp;factoryB()<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;ProductB2();<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
<br />
public&nbsp;class&nbsp;ProductA1&nbsp;implements&nbsp;&nbsp;ProductA<br />
{ <br />
&nbsp;public&nbsp;&nbsp;ProductA1()<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
public&nbsp;class&nbsp;ProductA2&nbsp;implements&nbsp;&nbsp;ProductA<br />
{ <br />
&nbsp;public&nbsp;&nbsp;ProductA2()<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
public&nbsp;class&nbsp;ProductB1&nbsp;implements&nbsp;&nbsp;ProductB<br />
{ <br />
&nbsp;public&nbsp;&nbsp;ProductB1()<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
public&nbsp;class&nbsp;ProductB2&nbsp;implements&nbsp;&nbsp;ProductB<br />
{ <br />
&nbsp;public&nbsp;&nbsp;ProductB2()<br />
&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
实际上是这样的<br />
1，两个工厂类ConCreator1，ConCreator2都实现了Creator接口<br />
2，ProuctA1,ProductA2都实现了ProductA接口<br />
3，ProuctB1,ProductB2都实现了ProductB接口<br />
4，ConCreator1负责生产ProductA类型的产品(包括ProductA1，ProductB1)<br />
5，ConCreator2负责生产ProductB类型的产品(包括ProductA2，ProductB2)<br />
6，工厂方法也有这样的特征，也就是说Creator不知道什么被生产出来，甚至不知道ConCreator1还是ConCreator2被实例化了，因为client高兴调那一个工厂，就调那一个工厂，就是说工厂能生产什么，对客户端是可见的。甚至还有一种情况，客户端高兴起来就生产了ProductA1,我就不生产ProductA2,因为上面的例子中它们还都是松散的，没有绑定在一起<br />
<br />
<br />
<br />
<br />
于是提出另外一个例子，也是老提起的电脑类型的例子<br />
<br />
1，电脑生产商是接口，<br />
2，CUP是接口，<br />
3，硬盘是接口，<br />
4，IBM工厂是制造IBM品牌的电脑的工厂<br />
5，DELL工厂是制造DEll品牌的电脑的工厂<br />
为讨论方便，就认为电脑=CUP+硬盘；<br />
6，所以呀CUP有IBM的CPU和DELL的CPU<br />
7，同样硬盘也是有IBM的硬盘和DELL的硬盘<br />
8，IBM工厂生产IBM的CPU和IBM的硬盘，绝对不生产DELL的CPU，也不生产DELL的硬盘<br />
9，同样DELL工厂也是一样<br />
<br />
<br />
public&nbsp;interface&nbsp;&nbsp;电脑生产商<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;CPU&nbsp;制造CPU();<br />
&nbsp;&nbsp;&nbsp;public&nbsp;硬盘&nbsp;制造硬盘();<br />
}<br />
<br />
public&nbsp;interface&nbsp;CPU<br />
{ <br />
}<br />
<br />
public&nbsp;interface&nbsp;硬盘<br />
{ <br />
}<br />
<br />
public&nbsp;class&nbsp;IBM的CPU&nbsp;implements&nbsp;CPU<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IBM的CPU();<br />
}<br />
<br />
public&nbsp;class&nbsp;IBM的硬盘&nbsp;implements&nbsp;硬盘<br />
{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IBM的硬盘();<br />
}<br />
<br />
public&nbsp;class&nbsp;DELL的CPU&nbsp;implements&nbsp;CPU<br />
{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DELL的CPU();<br />
}<br />
<br />
public&nbsp;class&nbsp;DELL的硬盘&nbsp;implements&nbsp;硬盘<br />
{ <br />
&nbsp;&nbsp;&nbsp;public&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DELL的硬盘();<br />
}<br />
<br />
//下面是IBM工厂<br />
public&nbsp;class&nbsp;&nbsp;IBM工厂<br />
{ <br />
&nbsp;&nbsp;&nbsp;private&nbsp;CPU&nbsp;IBM的CPU私有变量=null;<br />
&nbsp;&nbsp;&nbsp;private&nbsp;硬盘&nbsp;IBM的硬盘私有变量=null;<br />
&nbsp;&nbsp;&nbsp;private&nbsp;CPU&nbsp;制造IBMCPU()<br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;new&nbsp;IBM的CPU();<br />
&nbsp;&nbsp; }<br />
&nbsp;private&nbsp;硬盘&nbsp;制造IBM硬盘()<br />
&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;&nbsp;new&nbsp;IBM的CPU();<br />
&nbsp; }<br />
&nbsp;public&nbsp;电脑&nbsp;&nbsp;制造IBM电脑()<br />
&nbsp;{ <br />
&nbsp;&nbsp;try{ <br />
&nbsp;&nbsp;IBM的CPU私有变量=制造IBMCPU();<br />
&nbsp;&nbsp;IBM的硬盘私有变量=制造IBM硬盘();<br />
&nbsp;&nbsp;if(IBM的CPU私有变量!=null&amp;&amp;IBM的硬盘私有变量!=null)<br />
&nbsp;&nbsp;retrun&nbsp;&nbsp;(IBM的CPU私有变量+IBM的硬盘私有变量);<br />
&nbsp;&nbsp;&nbsp;&nbsp;//组装成IBM电脑<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp;catch(Exception&nbsp;e)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("制造IBM电脑失败！");<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp; }<br />
}<br />
<br />
这样，客户端无法通过命令单生产出一个CPU来，这样抽象才真正成为一个完整产品的工厂，只要向工厂发出生产的命令，一台完整的电脑就生产出来了，而工厂怎么生产的，生产了哪些部件，外界就看不见了，外界就知道这个工厂是生产IBM电脑整机的工厂！<br />
<br />
DELL电脑工厂一样 <br />
<br />
----------------------------总结----------------------------<br />
<br />
工厂方法模式：<br />
一个抽象产品类，可以派生出多个具体产品类。&nbsp;&nbsp; <br />
一个抽象工厂类，可以派生出多个具体工厂类。&nbsp;&nbsp; <br />
每个具体工厂类只能创建一个具体产品类的实例。<br />
<br />
抽象工厂模式：<br />
多个抽象产品类，每个抽象产品类可以派生出多个具体产品类。&nbsp;&nbsp; <br />
一个抽象工厂类，可以派生出多个具体工厂类。&nbsp;&nbsp; <br />
每个具体工厂类可以创建多个具体产品类的实例。&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
区别：<br />
工厂方法模式只有一个抽象产品类，而抽象工厂模式有多个。&nbsp;&nbsp; <br />
工厂方法模式的具体工厂类只能创建一个具体产品类的实例，而抽象工厂模式可以创建多个。</font>
<img src ="http://www.blogjava.net/renyangok/aggbug/58714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-18 11:20 <a href="http://www.blogjava.net/renyangok/articles/58714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Singleton（单态）模式 和 Double-Checked Locking（双重检查锁定）模式</title><link>http://www.blogjava.net/renyangok/articles/58706.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 18 Jul 2006 02:56:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58706.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58706.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58706.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58706.html</trackback:ping><description><![CDATA[确保一个特定的类只有一个对象被实例化。<br /><br /><font class="java-bracket">Singleton：用于单线程应用程序<br /><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></td></tr></tbody></table><p>Double-Checked Locking：用于多线程应用程序</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></td></tr></tbody></table><p><br /></p></font><br />Double-Checked Locking在java实际上无法得到预期的效果，不能保证singleton的正确性。<br />参考：（英文）<br /><a href="http://gee.cs.oswego.edu/dl/cpj/jmm.html">http://gee.cs.oswego.edu/dl/cpj/jmm.html</a><br /><a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html</a><br /><br /><span class="javascript" id="text3940"><pre> </pre></span><img src ="http://www.blogjava.net/renyangok/aggbug/58706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-18 10:56 <a href="http://www.blogjava.net/renyangok/articles/58706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>设计模式的原则和策略</title><link>http://www.blogjava.net/renyangok/articles/58695.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 18 Jul 2006 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/58695.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/58695.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/58695.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/58695.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/58695.html</trackback:ping><description><![CDATA[1、发现、分离并封装变化点。<br />2、优先使用对象组合，而不是类继承。<br />3、针对接口设计而不是实现设计。<br />4、开放－封闭原则：模块、类和方法应该对扩展是开放的，而对更改是封闭的。<img src ="http://www.blogjava.net/renyangok/aggbug/58695.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-18 10:08 <a href="http://www.blogjava.net/renyangok/articles/58695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Adapter（适配器）模式</title><link>http://www.blogjava.net/renyangok/articles/57591.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Tue, 11 Jul 2006 00:52:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/57591.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/57591.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/57591.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/57591.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/57591.html</trackback:ping><description><![CDATA[将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 <br /><p>    有时，为复用而设计的工具箱类不能够被复用的原因仅仅是因为它的接口与专业应用领域所需要的接口不匹配。<br />    适配器模式有类的适配器模式和对象的适配器模式两种不同的形式。<br /><br />一、类的适配器模式<br />    类的适配器模式把适配的类的API转换成目标类的API。<br /><br /></p><ul><br /><li>目标(Target)角色：这就是所期待得到的接口。 <br /></li><li>源(Adaptee)角色：现有需要适配的接口。 <br /></li><li>适配器(Adapter)角色：适配器类是本模式的核心。适配器把源接口转换成目标接口。显然这一角色不可以是接口，而必须是具体类。</li></ul>/**<br /> * 定义Client使用的与特定领域相关的接口<br /> */<br />public interface Target {<br />    void sampleOperation1();<br />    void sampleOperation2();<br />}<br />/**<br /> * 定义一个已经存在的接口，这个接口需要适配<br /> */<br />public class Adaptee {<br />    public void sampleOperation1() {<br />        // ......<br />    }<br />}<br />/**<br /> * 对Adaptee与Target接口进行适配<br /> */<br />public class Adapter extends Adaptee implements Target {<br />    public void sampleOperation2() {<br />        // ......<br />    }<br />}<br /><br />二、对象适配器<br />    与类的适配器模式一样，对象适配器模式把适配的类的API转换成为目标类的API，与类的适配器模式不同的是，对象的适配器模式不是使用继承关系连接到Adaptee类，而是使用委派关系连接到Adaptee类。示意代码如下：<br />/**<br /> * 定义Client使用的与特定领域相关的接口<br /> */<br />public interface Target {<br />    void sampleOperation1();<br />    void sampleOperation2();<br />}<br />/**<br /> * 定义一个已经存在的接口，这个接口需要适配<br /> */<br />public class Adaptee {<br />    public void sampleOperation1() {<br />        // ......<br />    }<br />}<br />/**<br /> * 对Adaptee与Target接口进行适配<br /> */<br />public class Adapter implements Target {<br />    private Adaptee adaptee;<br />    public Adapter(Adaptee adaptee) {<br />        super();<br />        this.adaptee = adaptee;<br />    }<br />    public void sampleOperation1() {<br />        adaptee.sampleOperation1();<br />    }<br />    public void sampleOperation2() {<br />        // ......<br />    }<br />}<br /><br />类适配器模式和对象适配器模式的异同：Target接口和Adaptee类都相同，不同的是类适配器的Adapter继承Adaptee实现Target，对象适配器的Adapter实现Target聚集Adaptee。<br /><br />适配器模式的用意是将接口不同而功能相同或者相近的两个接口加以转换。<br /><br />三、JDBC驱动软件与适配器模式<br />    JDBC给出一个客户端通用的界面，每个数据库引擎的JDBC驱动软件都是一个介于JDBC接口和数据库引擎接口之间的适配器软件。<br /><img src ="http://www.blogjava.net/renyangok/aggbug/57591.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-11 08:52 <a href="http://www.blogjava.net/renyangok/articles/57591.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Facade（外观）模式</title><link>http://www.blogjava.net/renyangok/articles/57541.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 10 Jul 2006 09:15:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/57541.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/57541.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/57541.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/57541.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/57541.html</trackback:ping><description><![CDATA[
		<strong>
				<em>Facade模式的定义</em>
		</strong>: 为子系统中的一组接口提供一个一致的界面.。现在的软件都是按照模块进行划分，对不同的模块分别进行编程。但是在用户开来，不同的模块应该具有统一的接口，换句话说，我们应该可以通过统一的接口访问系统中的所有功能。 
<p>    有一个很典型的例子就是编译系统。通常我们将编译系统分解为：Compile和Link两个步骤。一个Compile又可以分解为词法分析、语法分析、语义分析、中间代码生成等等步骤。对于用户来讲，我们不可能将这些模块分别提供给他们，让他们依次调用。相反的，我们应该提供一个统一的接口，使得用户可以方便的使用各个功能，例如IDE 。</p><p>Facade一个典型应用就是数据库JDBC的应用,如下例对数据库的操作:</p><p></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><p></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/renyangok/aggbug/57541.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-10 17:15 <a href="http://www.blogjava.net/renyangok/articles/57541.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Bridge（桥接）模式</title><link>http://www.blogjava.net/renyangok/articles/57540.html</link><dc:creator>保尔任</dc:creator><author>保尔任</author><pubDate>Mon, 10 Jul 2006 09:13:00 GMT</pubDate><guid>http://www.blogjava.net/renyangok/articles/57540.html</guid><wfw:comment>http://www.blogjava.net/renyangok/comments/57540.html</wfw:comment><comments>http://www.blogjava.net/renyangok/articles/57540.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/renyangok/comments/commentRss/57540.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/renyangok/services/trackbacks/57540.html</trackback:ping><description><![CDATA[
		<p>Bridge模式的目的：<strong>把抽象部分和行为部分分离，使它们都能独立变化。<br /></strong><br /></p>
		<p>任何事物对象都有抽象和行为之分，例如人，人是一种抽象，人分男人和女人等；人有行为，行为也有各种具体表现，所以，“人”与“人的行为”两个概念也反映了抽象和行为之分。</p>
		<p>在面向对象设计的基本概念中，对象这个概念实际是由属性和行为两个部分组成的，属性我们可以认为是一种静止的，是一种抽象，一般情况下，行为是包含在一个对象中，但是，在有的情况下，我们需要将这些行为也进行归类，形成一个总的行为接口，这就是桥模式的用处。<br /></p>
		<p>总之，Bridge模式就是使抽象和行为分离，做到各自的独立发展，就是说抽象和行为各抽象出一个接口。当需要扩展行为或者抽象部分时，<br />只需扩展相应部分，而不用修改原来的结构。<br /><br /><strong>例子一：</strong><br />假如有个类DrawGraph有个画圆的接口，当然这个圆形可以用铅笔画，也可以用钢笔画。其中画圆是抽象部分，<br />用铅笔画和用钢笔画是行为部分。往往这个时候我们分别会定义铅笔类PencilDraw，钢笔类PenDraw来实现Draw，<br />这样就使得抽象部分和行为部分固定的捆绑在一起，扩展性不强。假如要动态增加一个用粉笔画的行为和一个画方形的抽象部分，<br />就必然要新定义一个ChalkDraw类，DrawGraph类里增加drawRectangle接口。显然这是很麻烦的。</p>
		<p>Bridge模式是这样实现的：<br />//抽象部分<br />public abstract class DrawGraph {</p>
		<p> private ToolDraw toolDraw;<br /> public void setToolDraw(){<br />  <strong>this.toolDraw = ToolDrawSingleton.getToolDraw();//用Singleton模式来选工具。</strong><br /> }<br /> <br /> public ToolDraw getToolDraw(){<br />  return toolDraw;<br /> }<br /> <br /> public abstract void draw();<br />}<br /><br />//画圆<br />public class DrawCircle implements DrawGraph{<br /> public DrawCircle(){<br />  setToolDraw();<br /> }<br /> public void draw(){<br />  System.out.pritnln(toolDraw.getName() + " draw circle");<br /> }<br />}<br /><br />//画矩形<br />public class DrawRectangle implements DrawGraph{<br /> public DrawRectangle(){<br />  setToolDraw();<br /> }<br /> public void draw(){<br />  System.out.pritnln(toolDraw.getName() + " draw rectangle");<br /> }<br />}</p>
		<p>//行为部分<br />public abstract class ToolDraw{<br /> public abstract String getName();<br /> public abstract void drawWithTool();<br />}<br /><br />//铅笔<br />public class PencilDraw implements ToolDraw{<br /> private final static String name = "Pencil";<br /> <br /> public static String getName(){<br />  return name;<br /> }<br /> <br /> public void drawWithTool(){<br />  System.out.println("Draw with Pencil.");<br /> }<br />}<br /><br />//钢笔<br />public class PenDraw implements ToolDraw{<br /> private final static String name = "Pen";<br /> <br /> public String getName(){<br />  return name;<br /> }<br /> <br /> public void drawWithTool(){<br />  System.out.println("Draw with Pen.");<br /> }<br />}<br /><br />//粉笔<br />public class ChalkDraw implements ToolDraw{<br /> private final static String name = "Chalk";<br /> <br /> public String getName(){<br />  return name;<br /> }<br /> <br /> public void drawWithTool(){<br />  System.out.println("Draw with Chalk.");<br /> }<br />}</p>
		<p>做一个Singleton类来联系抽象和行为。通过此类来选工具<br />public class ToolDrawSingleton{<br /> private static ToolDraw toolDraw;<br /> <br /> public ToolDrawSingleton(ToolDraw toolDraw){<br />  this.toolDraw = toolDraw<br /> }<br /> public static ToolDraw getToolDraw(){<br />  return toolDraw;<br /> }<br />}</p>
		<p>假如我们现在要用粉笔来画一个方形,一个圆形：<br />//取得工具<br />ToolDrawSingleton tool = new ToolDrawSingleton(new ChalkDraw());<br />//画方形<br />DrawGraph drawRectangle = new DrawRectangle();<br />drawRectangle.draw();<br />//画圆形<br />drawRectangle = new DrawCircle();<br />drawRectangle.draw();<br /></p>
		<p>例子二：<br />例如,一杯咖啡为例,子类实现类为四个：中杯加奶、大杯加奶、 中杯不加奶、大杯不加奶。</p>
		<p>但是，我们注意到：上面四个子类中有概念重叠，可从另外一个角度进行考虑，这四个类实际是两个角色的组合：抽象 和行为，其中抽象为：中杯和大杯；行为为：加奶 不加奶（如加橙汁 加苹果汁）. </p>
		<p>实现四个子类在抽象和行为之间发生了固定的绑定关系，如果以后动态增加加葡萄汁的行为，就必须再增加两个类：中杯加葡萄汁和大杯加葡萄汁。显然混乱,扩展性极差。</p>
		<p>那我们从分离抽象和行为的角度，使用Bridge模式来实现。</p>
		<p>
				<strong>如何实现?</strong>
				<br />以上面提到的咖啡 为例. 我们原来打算只设计一个接口(抽象类),使用Bridge模式后,我们需要将抽象和行为分开,加奶和不加奶属于行为,我们将它们抽象成一个专门的行为接口.</p>
		<p>先看看抽象部分的接口代码:<br /></p>
		<p>
		</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>
		<p>
		</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>
		<p>
		</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>
		<p>
		</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>
		<p>
		</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是该模式的关键。<br /><br /><img src="http://www.blog.edu.cn/user2/40416/upload/20058319945.png" /></p>
<img src ="http://www.blogjava.net/renyangok/aggbug/57540.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/renyangok/" target="_blank">保尔任</a> 2006-07-10 17:13 <a href="http://www.blogjava.net/renyangok/articles/57540.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>