﻿<?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-eric-随笔分类-设计模式</title><link>http://www.blogjava.net/jjshcc/category/46277.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 10 Nov 2010 18:49:56 GMT</lastBuildDate><pubDate>Wed, 10 Nov 2010 18:49:56 GMT</pubDate><ttl>60</ttl><item><title>访问者模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/10/31/336613.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Sun, 31 Oct 2010 09:24:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/10/31/336613.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/336613.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/10/31/336613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/336613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/336613.html</trackback:ping><description><![CDATA[<div class="" id="contentDiv" style="padding-right: 15px; padding-left: 15px; font-size: 14px; min-height: 100px; padding-bottom: 0px; overflow: visible; line-height: 170%; padding-top: 15px; height: 100px" onclick="getTop().preSwapLink(event, 'html');">
<div id="mailContentContainer" style="padding-right: 0px; padding-left: 0px; font-size: 14px; min-height: auto; padding-bottom: 0px; margin-right: 170px; padding-top: 0px; font-family: 'lucida Grande',Verdana; height: auto">具体元素的接口与实现类<br />
<br />
public interface Person {<br />
&nbsp;&nbsp;&nbsp; &nbsp; void accept(Visitor visitor);<br />
}<br />
<br />
<br />
public class Woman implements Person{<br />
<br />
&nbsp; &nbsp; public void accept(Visitor visitor) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; visitor.visit(this);<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
public class Man implements Person{<br />
<br />
&nbsp; &nbsp; public void accept(Visitor visitor) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; visitor.visit(this);<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
访问者接口与实现类，分别代表男人与女人在不同的状态下的表现<br />
<br />
public interface Visitor {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public void visit(Man man);<br />
&nbsp;&nbsp;&nbsp; &nbsp; public void visit(Woman girl);<br />
}<br />
<br />
//成功时Man与Woman的不同表现<br />
public class Success implements Visitor{<br />
<br />
&nbsp; &nbsp; public void visit(Man man) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当男人成功时，背后多半有一个伟大的女人");<br />
&nbsp; &nbsp; }<br />
<br />
<br />
&nbsp; &nbsp; public void visit(Woman woman) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当女人成功时，背后大多有一个不成功的男人");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
//恋爱时Man与Woman的不同表现<br />
public class Love implements Visitor{<br />
<br />
&nbsp; &nbsp; public void visit(Man man) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当男人恋爱时，凡事不懂也装懂");<br />
&nbsp; &nbsp; }<br />
<br />
<br />
&nbsp; &nbsp; public void visit(Woman girl) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当女人恋爱时，遇事懂也装不懂");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
ObjectStructure与客户端测试代码<br />
<br />
import java.util.*;<br />
<br />
public class ObjectStructure {<br />
&nbsp; &nbsp; private List&lt;Person&gt; elements = new ArrayList&lt;Person&gt;();<br />
<br />
&nbsp; &nbsp; public void attach(Person element){<br />
&nbsp; &nbsp; &nbsp; &nbsp; elements.add(element);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; public void detach(Person element){<br />
&nbsp; &nbsp; &nbsp; &nbsp; elements.remove(elements);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; //遍历各种具体元素并执行他们的accept方法<br />
&nbsp; &nbsp; public void display(Visitor visitor){<br />
&nbsp; &nbsp; &nbsp; &nbsp; for(Person p:elements){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.accept(visitor);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
public class Client {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public static void main(String[] args) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; ObjectStructure o = new ObjectStructure();&nbsp; //依赖于ObjectStructure<br />
&nbsp; &nbsp; &nbsp; &nbsp; //实例化具体元素<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Man());&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Woman());<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //当成功时不同元素的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor success = new Success();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(success);<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //当恋爱时的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor amativeness = new Love();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(amativeness);<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
需求的变化<br />
<br />
假设现在需求要扩展数据结构，增加一种具体元素，男与女之外的一种不明物体，我们暂时把它称为&#8220;怪兽&#8221;，在既有访问者模式的架构下，应该怎样？首先增加一个Bruce类，实现Person接口。最麻烦的是要修改访问者接口及其所有具体访问者!<br />
<br />
&nbsp; 因为Visit方法中没有包含访问Bruce对象的行为，因此我们被迫要去手工更改Visitor(包括抽象的，具体的)，在其中添加有关Bruce对象的行为，这严重违反了&#8220;开放-封闭&#8221;原则。究其原因在于目前的结构下，被访问对象与访问对象互相依赖，自然不利于分离变化，必须去掉一层依赖关系。<br />
<br />
我们尝试把Visitor对Person(元素)的依赖关系去掉，抽象出对应每个具体元素的ElementVisitor接口 --&gt;ManVisitor,WomanVisitor，然后把Visitor对Person的依赖关系转移到ManVisitor与 WomanVisitor身上。<br />
&nbsp;<br />
现在Visitor接口已经没有任何抽象方法，只是一个空接口，每一个具体元素对应有一个ElementVisitor接口，每一个元素对应的ElementVisitor接口有访问该元素的visit(),相当把原来在Visitor接口中声明工作，交由各个具体ElementVisitor接口完成。<br />
<br />
<br />
经过改造后的代码：<br />
原Visitor接口<br />
<br />
public interface Visitor {<br />
&nbsp;&nbsp;&nbsp; &nbsp; //退化到没有任何抽象方法<br />
}<br />
<br />
<br />
<br />
新增加ManVisitor,WomanVisitor接口<br />
<br />
public interface ManVisitor {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public void visit(Man man);<br />
}<br />
<br />
public interface WomanVisitor {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public void visit(Woman w);<br />
}<br />
<br />
&nbsp;<br />
具体Visitor实现类现在同时实现3个接口<br />
<br />
//由实现Visitor接口扩展成实现Visitor,WomanVisitor,ManVisitor三个接口<br />
public class Success implements Visitor,WomanVisitor,ManVisitor{<br />
<br />
&nbsp; &nbsp; public void visit(Man man) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当男人成功时，背后多半有一个伟大的女人");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void visit(Woman girl) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当女人成功时，背后大多有一个不成功的男人");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
//由实现Visitor接口扩展成实现Visitor,WomanVisitor,ManVisitor三个接口<br />
public class Love implements Visitor,WomanVisitor,ManVisitor{<br />
<br />
&nbsp; &nbsp; public void visit(Man man) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当男人恋爱时，凡事不懂也装懂");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void visit(Woman girl) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当女人恋爱时，遇事懂也装不懂");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
Person接口没有变化,依旧只依赖于Visitor接口<br />
<br />
public interface Person {<br />
&nbsp;&nbsp;&nbsp; &nbsp; void accept(Visitor visitor);<br />
}<br />
<br />
<br />
<br />
改造后的具体元素类Man与Woman<br />
<br />
public class Man implements Person {<br />
<br />
&nbsp; &nbsp; // 先对visitor进行类型转换，再执行visit方法，因为Visitor接口已经没有声明任何抽象方法了<br />
&nbsp; &nbsp; public void accept(Visitor visitor) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; if (visitor instanceof ManVisitor) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ManVisitor mv = (ManVisitor) visitor;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mv.visit(this);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
public class Woman implements Person {<br />
<br />
&nbsp; &nbsp; // 先对visitor进行类型转换，再执行visit方法，因为Visitor接口已经没有声明任何抽象方法了<br />
&nbsp; &nbsp; public void accept(Visitor visitor) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; if (visitor instanceof WomanVisitor) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; WomanVisitor wv = (WomanVisitor) visitor;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; wv.visit(this);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
ObjectStructure与客户端测试代码没有变化<br />
<br />
import java.util.*;<br />
<br />
public class ObjectStructure {<br />
&nbsp; &nbsp; private List&lt;Person&gt; elements = new ArrayList&lt;Person&gt;();<br />
<br />
&nbsp; &nbsp; public void attach(Person element){<br />
&nbsp; &nbsp; &nbsp; &nbsp; elements.add(element);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; public void detach(Person element){<br />
&nbsp; &nbsp; &nbsp; &nbsp; elements.remove(elements);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; //遍历各种具体元素并执行他们的accept方法<br />
&nbsp; &nbsp; public void display(Visitor visitor){<br />
&nbsp; &nbsp; &nbsp; &nbsp; for(Person p:elements){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.accept(visitor);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
public class Client {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public static void main(String[] args) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; ObjectStructure o = new ObjectStructure();&nbsp; //依赖于ObjectStructure<br />
&nbsp; &nbsp; &nbsp; &nbsp; //实例化具体元素<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Man());&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Woman());<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //当成功时不同元素的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor success = new Success();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(success);<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //当恋爱时的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor amativeness = new Love();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(amativeness);&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
至此改造完毕！我们执行客户端测试代码，结果显示：<br />
当男人成功时，背后多半有一个伟大的女人<br />
当女人成功时，背后大多有一个不成功的男人<br />
当男人恋爱时，凡事不懂也装懂<br />
当女人恋爱时，遇事懂也装不懂<br />
<br />
此时，客户端仍然只依赖于Visitor空接口与ObjectStructure类。可能一开始大家会认为空接口没有什么用，现在就能体现出他的威力了，使客户端与具体Visitor的高度解耦！也正是这种思维的核心在JavaAPI中也有类似的应用，这种空接口被称为标识接口。比如java.io.Serializable与java.rmi.Remote等，标识接口里没有任何方法和属性，标识不对实现接口不对实现它的类有任何语义上的要求，它仅仅是表明实现它的类属于一种特定的类型。<br />
上面具体访问者实现的多个接口被称为混合类型。这个概念《Java与模式》中有提及过：当一个具体类处于一个类的等级结构之中的时候，为这个具体类定义一个混合类型是可以保证基于这个类型的可插入性的关键。<br />
<br />
=================================无敌分界线====================================<br />
<br />
讲了这么长，现在我们测试下改造后的访问者模式<br />
首先增加一种行为(状态)，即原访问者模式的优点<br />
<br />
增加一个具体访问者Fail,修改一下客户端测试代码<br />
<br />
public class Fail implements Visitor,ManVisitor,WomanVisitor{<br />
<br />
&nbsp; &nbsp; public void visit(Man man) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当男人失败时，闷头喝酒，谁也不用劝");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void visit(Woman woman) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当女人失败时，眼泪汪汪，谁也劝不了");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
public class Client {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public static void main(String[] args) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; ObjectStructure o = new ObjectStructure();&nbsp; //依赖于ObjectStructure<br />
&nbsp; &nbsp; &nbsp; &nbsp; //实例化具体元素<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Man());&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Woman());<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //当成功时不同元素的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor success = new Success();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(success);<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println();<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //当恋爱时的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor amativeness = new Love();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(amativeness);&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println();<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; //新增加失败时的不同反映<br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor fail = new Fail();<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(fail);<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
结果显示：<br />
当男人成功时，背后多半有一个伟大的女人<br />
当女人成功时，背后大多有一个不成功的男人<br />
<br />
当男人恋爱时，凡事不懂也装懂<br />
当女人恋爱时，遇事懂也装不懂<br />
<br />
当男人失败时，闷头喝酒，谁也不用劝<br />
当女人失败时，眼泪汪汪，谁也劝不了<br />
<br />
<br />
<br />
增加新的行为(状态)与原来一样方便！只需要增加一个具体访问者即可！<br />
现在我们来增加一个具体元素(正是写这篇文章的初衷)<br />
<br />
首先增加一个具体元素Bruce<br />
<br />
public class Bruce implements Person{<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; public void accept(Visitor visitor) {&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; if(visitor instanceof BruceVisitor){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BruceVisitor bv = (BruceVisitor) visitor;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bv.visit(this);<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; //这个else可写可不写<br />
&nbsp; &nbsp; &nbsp; &nbsp; else{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String s = visitor.getClass().getName();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String state = s.substring(s.lastIndexOf(".")+1,s.length());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("噢..原来怪兽在"+state+"的时候是没有行为的!!");<br />
&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
//按照新的思维方式增加一个对应的ElementVisitor接口<br />
public interface BruceVisitor {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public void visit(Bruce bruce);<br />
}<br />
<br />
<br />
<br />
我们让Success这个具体访问者多实现一个BruceVisitor访问者接口,和修改一下客户端代码进行测试<br />
<br />
public class Success implements Visitor,WomanVisitor,ManVisitor,BruceVisitor{<br />
<br />
&nbsp; &nbsp; public void visit(Man man) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当男人成功时，背后多半有一个伟大的女人");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void visit(Woman girl) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当女人成功时，背后大多有一个不成功的男人");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void visit(Bruce bruce) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("当怪兽成功时.........无语..........");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
public class Client {<br />
&nbsp;&nbsp;&nbsp; &nbsp; public static void main(String[] args) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; ObjectStructure o = new ObjectStructure();&nbsp; //依赖于ObjectStructure<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Man());&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Woman());<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.attach(new Bruce());&nbsp;&nbsp;&nbsp; &nbsp; //新增一种具体元素Bruce<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor success = new Success();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(success);<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println();<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor amativeness = new Love();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; //依赖于抽象的Visitor接口<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(amativeness);&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println();<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; Visitor fail = new Fail();<br />
&nbsp; &nbsp; &nbsp; &nbsp; o.display(fail);<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
<br />
<br />
显示结果：<br />
当男人成功时，背后多半有一个伟大的女人<br />
当女人成功时，背后大多有一个不成功的男人<br />
当怪兽成功时.........无语..........<br />
<br />
当男人恋爱时，凡事不懂也装懂<br />
当女人恋爱时，遇事懂也装不懂<br />
噢..原来怪兽在Love的时候是没有行为的!!<br />
<br />
当男人失败时，闷头喝酒，谁也不用劝<br />
当女人失败时，眼泪汪汪，谁也劝不了<br />
噢..原来怪兽在Fail的时候是没有行为的!!<br />
<br />
<br />
这个结果你满意吗？<br />
虽然，这只是部分符合&#8220;开放-封闭&#8221;原则，我们不需要修改Visitor接口，但还是得去修改Success实现新的接口。但是修改具体类比修改接口的代价小得多，不需要重新编译所有访问接口和具体访问者。使我们面对新的变化也容易得多。而且这还有一个好处，就是可以让各种元素有选择地让别人访问，如上述例子，这样使访问者模式的运用起来更加灵活。 <br />
</div>
</div>
<img src ="http://www.blogjava.net/jjshcc/aggbug/336613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-10-31 17:24 <a href="http://www.blogjava.net/jjshcc/archive/2010/10/31/336613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>适配器模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/10/29/336517.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Fri, 29 Oct 2010 12:56:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/10/29/336517.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/336517.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/10/29/336517.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/336517.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/336517.html</trackback:ping><description><![CDATA[<p>类适配器 <br />
客户的开发人员定义了一个接口，期望用这个接口来完成整数的求和操作，接口定义如下： <br />
&nbsp;<br />
public interface Operation{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int add(int a,int b);&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;开发人员在了解这个接口的定义后，发现一个第三方类，里面有一个方法能实现他们期望的功能，其代码如下： <br />
&nbsp;<br />
public class OtherOperation{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int otherAdd(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a + b;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;以上第三方类OtherOperation的方法public int otherAdd(int a,int b)所提供的功能，完全能符合客户的期望，所以只需要想办法把OtherOperation的otherAdd(int a,int b)和客户的Operation接口联系起来，让这个第三方类来为客户提供他们期望的服务就行了，这样就避免了开发人员再度去研究类似OtherOperation的otherAdd(int a,int b)方法的实现（利用已有的轮子，避免重复发明），这方法之一，就是用适配器模式： <br />
&nbsp;<br />
public class AdapterOperation extends OtherOperation implements Operation{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int add(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return otherAdd(a,b);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;以上就是适配器的实现方法之一，类适配器，在以上实现中存在着三中角色分别是： <br />
1：适配目标角色：Operation。 <br />
2：适配类（原）角色：OtherOperation。 <br />
3：适配器角色：AdapterOperation。 <br />
其中适配器角色是适配器模式的核心。 <br />
适配器的主要工作就是通过封装现有的功能，使他满足需要的接口。 <br />
对象适配器 <br />
我们再来看看另一种情况： <br />
假如客户接口期望的功能不止一个，而是多个： <br />
&nbsp;<br />
public interface Operation{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int add(int a,int b);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int minus(int a,int b);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int multiplied(int a,int b);&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;而能提供这些实现的原可能不止一个： <br />
&nbsp;<br />
public class OtherAdd{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int otherAdd(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a + b;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
public class OtherMinus{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int minus(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a - b;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
public class OtherMultiplied{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int multiplied(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a * b;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;由于java是不能实现多继承的，所以我们不能通过构建一个适配器，让他来继承所有原以完成我们的期望，这时候怎么办呢?只能用适配器的另一种实现--对象适配器： <br />
&nbsp;<br />
public class AdapterOperation implements Operation{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private OtherAdd add;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private OtherMinus minus;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private OtherMultiplied multiplied;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setAdd(OtherAdd add){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.add = add;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setMinus(OtherMinus minus){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.minus = minus;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setMultiplied(OtherMultiplied multiplied){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.multiplied = multiplied;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //适配加法运算&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int add(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return add.otherAdd(a,b);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //适配减法运算&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int minus(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return minus.minus(a,b);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //适配乘法运算&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int multiplied(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return multiplied.multiplied(a,b);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}<br />
&nbsp; <br />
&nbsp;</p>
<p>上面代码很明显，适配器并不是通过继承来获取适配类（原）的功能的，而是通过适配类的对象来获取的，这就解决了java不能多继承所带来的不便了。这也是java提倡的编程思想之一，即尽量使用聚合不要使用继承。 还有一种情况是需要使用对象适配器的。我们来看看，单我们的客户提供的需求并不是一个明确的接口，而是一个类，并没有定义期望的方法，如下 <br />
&nbsp;<br />
public class A{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; public int add(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a + b;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;<br />
现在客户要一个新类B，要求能在保留类A功能的情况下增加一个运算减法的功能，并要求B能随时替换掉A但不能对已有系统造成影响。这样我们只能新建一个类B，并让B继承A。 <br />
&nbsp;<br />
public class B extends A{&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; b(){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public int minus(int a,int b){&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //待实现的减法运算函数..&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;<br />
这时候，我们发现类C已经提供了实现减法的函数， <br />
&nbsp; <br />
public class C{<br />
&nbsp;&nbsp;&nbsp; public int minus(int a,int b){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return a - b;<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>为了避免重复去设计该函数，我们决定引入C类，通过适配C类来达到我们的期望，但问题是A和C都是一个具体类，我们无法让B同时继承这个两个类，而B继承A又是必须的，所以我们只能考虑把C给内聚到B内部，对象适配器又得派上用场了。 <br />
&nbsp;<br />
public class B extends A{<br />
&nbsp;&nbsp;&nbsp; private C c;<br />
&nbsp;&nbsp;&nbsp; B(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void setMinus(C c){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.c= c;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public int minus(int a,int b){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return c.minus(a,b);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>这样，在需要A类的地方都能用B类来代替，同时又保证了新的功能的引入。 <br />
更灵活的实现--隐藏目标接口的抽象适配器 <br />
做java 桌面应用的都知道WindowListener接口， <br />
&nbsp;<br />
public interface WindowListener extends EventListener{<br />
&nbsp;public void windowActivated(WindowEvent e)；<br />
&nbsp;public void windowClosed(WindowEvent e)；<br />
&nbsp;public void windowClosing(WindowEvent e)；<br />
&nbsp;public void windowDeactivated(WindowEvent e)；<br />
&nbsp;public void windowDeiconified(WindowEvent e)；<br />
&nbsp;public void windowIconified(WindowEvent e)；<br />
&nbsp;public void windowOpened(WindowEvent e)；<br />
}</p>
<p>要实现这个接口，我们就必须实现它所定义的所有方法，但是实际上，我们很少需要同时用到所有的方法，我们要的只是其中的两三个。为了不使我们实现多余的方法， <br />
jdk WindowListener提供了一个WindowListener的默认实现类WindowAdapter类，这是一个抽象类， <br />
&nbsp; <br />
public abstract class WindowAdapter implements WindowListener{<br />
&nbsp;public void windowActivated(WindowEvent e){}<br />
&nbsp;public void windowClosed(WindowEvent e){}<br />
&nbsp;public void windowClosing(WindowEvent e){}<br />
&nbsp;public void windowDeactivated(WindowEvent e){}<br />
&nbsp;public void windowDeiconified(WindowEvent e){}<br />
&nbsp;public void windowIconified(WindowEvent e){}<br />
&nbsp;public void windowOpened(WindowEvent e){}<br />
}</p>
<p>WindowAdapter类对WindowListener接口的所有有方法都提供了空实现， <br />
有了WindowAdapter类，我们只需要去继承WindowAdapter，然后选择我们所关心的方法来实现就行了，这样就避免了直接去实现WindowListener接口。 <br />
</p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/336517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-10-29 20:56 <a href="http://www.blogjava.net/jjshcc/archive/2010/10/29/336517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>策略模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/10/16/335308.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Sat, 16 Oct 2010 13:21:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/10/16/335308.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/335308.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/10/16/335308.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/335308.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/335308.html</trackback:ping><description><![CDATA[<div style="padding-bottom: 0px; min-height: auto; padding-left: 0px; padding-right: 0px; font-family: 'lucida Grande', Verdana; height: auto; font-size: 14px; margin-right: 0px; padding-top: 0px" id="mailContentContainer">设计模式解读之一： 策略模式<br />
1. 模式定义<br />
<br />
把会变化的内容取出并封装起来，以便以后可以轻易地改动或扩充部分，而不影响不需要变化的其他部分；<br />
<br />
2. 问题缘起<br />
当涉及至代码维护时，为了复用目的而使用继承，结局并不完美。对父类的修改，会影响到子类型。在超类中增加的方法，会导致子类型有该方法，甚至连那些不该具备该方法的子类型也无法免除。示例，一个鸭子类型：<br />
<br />
public abstract class Duck {<br />
&nbsp; &nbsp; //所有的鸭子均会叫以及游泳，所以父类中处理这部分代码<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Quack");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void swim() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("All ducks float, even decoys.");&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; //因为每种鸭子的外观是不同的，所以父类中该方法是抽象的，由子类型自己完成。<br />
&nbsp; &nbsp; public abstract void display();<br />
}<br />
<br />
public class MallardDuck extends Duck {<br />
&nbsp; &nbsp; //野鸭外观显示为绿头<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Green head.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
public class RedHeadDuck extends Duck {<br />
&nbsp; &nbsp; //红头鸭显示为红头<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Red head.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
public class RubberDuck extends Duck {<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; //橡皮鸭叫声为吱吱叫，所以重写父类以改写行为<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Squeak");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; //橡皮鸭显示为黄头<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Yellow head.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 上述代码，初始实现得非常好。现在我们如果给Duck.java中加入fly()方法的话，那么在子类型中均有了该方法，于是我们看到了会飞的橡皮鸭子，你看过吗？当然，我们可以在子类中通过空实现重写该方法以解决该方法对于子类型的影响。但是父类中再增加其它的方法呢？<br />
<br />
通过继承在父类中提供行为，会导致以下缺点：<br />
<br />
a. 代码在多个子类中重复;<br />
b. 运行时的行为不容易改变；<br />
c. 改变会牵一发动全身，造成部分子类型不想要的改变；<br />
<br />
好啦，还是刚才鸭子的例子，你也许想到使用接口，将飞的行为、叫的行为定义为接口，然后让Duck的各种子类型实现这些接口。这时侯代码类似于：<br />
<br />
public abstract class Duck {<br />
&nbsp; &nbsp; //将变化的行为 fly() 以及quake()从Duck类中分离出去定义形成接口，有需求的子类中自行去实现<br />
<br />
&nbsp; &nbsp; public void swim() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("All ducks float, even decoys.");&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public abstract void display();<br />
}<br />
<br />
//变化的 fly() 行为定义形成的接口<br />
public interface FlyBehavior {<br />
&nbsp; &nbsp; void fly();<br />
}<br />
<br />
//变化的 quack() 行为定义形成的接口<br />
public interface QuackBehavior {<br />
&nbsp; &nbsp; void quack();<br />
}<br />
<br />
//野鸭子会飞以及叫，所以实现接口&nbsp; FlyBehavior, QuackBehavior<br />
public class MallardDuck extends Duck implements FlyBehavior, QuackBehavior{<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Green head.");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void fly() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Fly.");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Quack.");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
}<br />
<br />
//红头鸭子会飞以及叫，所以也实现接口&nbsp; FlyBehavior, QuackBehavior<br />
public class RedHeadDuck extends Duck implements FlyBehavior, QuackBehavior{<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Red head.");<br />
&nbsp; &nbsp; } &nbsp; <br />
<br />
&nbsp; &nbsp; public void fly() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Fly.");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Quack.");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; } &nbsp; <br />
}<br />
<br />
//橡皮鸭不会飞，但会吱吱叫，所以只实现接口QuackBehavior<br />
public class RubberDuck extends Duck implements QuackBehavior{<br />
&nbsp; &nbsp; //橡皮鸭叫声为吱吱叫<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Squeak");<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; //橡皮鸭显示为黄头<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Yellow head.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
上述代码虽然解决了一部分问题，让子类型可以有选择地提供一些行为(例如 fly() 方法将不会出现在橡皮鸭中).但我们也看到，野鸭子MallardDuck.java和红头鸭子RedHeadDuck.java的一些相同行为代码不能得到重复使用。很大程度上这是从一个火坑跳到另一个火坑。<br />
<br />
在一段程序之后，让我们从细节中跳出来，关注一些共性问题。不管使用什么语言，构建什么应用，在软件开发上，一直伴随着的不变的真理是：需要一直在变化。不管当初软件设计得多好，一段时间之后，总是需要成长与改变，否则软件就会死亡。<br />
&nbsp; &nbsp; 我们知道，继承在某种程度上可以实现代码重用，但是父类(例如鸭子类Duck)的行为在子类型中是不断变化的，让所有子类型都有这些行为是不恰当的。我们可以将这些行为定义为接口，让Duck的各种子类型去实现，但接口不具有实现代码，所以实现接口无法达到代码复用。这意味着，当我们需要修改某个行为，必须往下追踪并在每一个定义此行为的类中修改它，一不小心，会造成新的错误。<br />
<br />
设计原则：把应用中变化的地方独立出来，不要和那些不需要变化的代码混在一起。这样代码变化引起的不经意后果变少，系统变得更有弹性。<br />
<br />
按照上述设计原则，我们重新审视之前的Duck代码。<br />
<br />
1) 分开变化的内容和不变的内容<br />
<br />
Duck类中的行为 fly(), quack(), 每个子类型可能有自己特有的表现，这就是所谓的变化的内容。<br />
Duck类中的行为 swim() 每个子类型的表现均相同，这就是所谓不变的内容。<br />
<br />
我们将变化的内容从Duck()类中剥离出来单独定义形成接口以及一系列的实现类型。将变化的内容定义形成接口可实现变化内容和不变内容的剥离。其实现类型可实现变化内容的重用。这些实现类并非Duck.java的子类型，而是专门的一组实现类，称之为"行为类"。由行为类而不是Duck.java的子类型来实现接口。这样，才能保证变化的行为独立于不变的内容。于是我们有：<br />
<br />
变化的内容：<br />
<br />
//变化的 fly() 行为定义形成的接口<br />
public interface FlyBehavior {<br />
&nbsp; &nbsp; void fly();<br />
}<br />
<br />
//变化的 fly() 行为的实现类之一<br />
public class FlyWithWings implements FlyBehavior {<br />
&nbsp; &nbsp; public void fly() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("I'm flying.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
//变化的 fly() 行为的实现类之二<br />
public class FlyNoWay implements FlyBehavior {<br />
&nbsp; &nbsp; public void fly() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("I can't fly.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
-----------------------------------------------------------------<br />
<br />
//变化的 quack() 行为定义形成的接口<br />
public interface QuackBehavior {<br />
&nbsp; &nbsp; void quack();<br />
}<br />
<br />
//变化的 quack() 行为实现类之一<br />
public class Quack implements QuackBehavior {<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Quack");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
//变化的 quack() 行为实现类之二<br />
public class Squeak implements QuackBehavior {<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Squeak.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
//变化的 quack() 行为实现类之三<br />
public class MuteQuack implements QuackBehavior {<br />
&nbsp; &nbsp; public void quack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("&lt;&lt; Slience &gt;&gt;");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
通过以上设计，fly()行为以及quack()行为已经和Duck.java没有什么关系，可以充分得到复用。而且我们很容易增加新的行为,既不影响现有的行为，也不影响Duck.java。但是，大家可能有个疑问，就是在面向对象中行为不是体现为方法吗？为什么现在被定义形成类(例如Squeak.java)？在OO中，类代表的"东西"一般是既有状态(实例变量）又有方法。只是在本例中碰巧"东西"是个行为。既使是行为，也有属性及方法，例如飞行行为，也需要一些属性记录飞行的状态，如飞行高度、速度等。<br />
<br />
2) 整合变化的内容和不变的内容<br />
<br />
Duck.java将 fly()以及quack()的行为委拖给行为类处理。<br />
<br />
不变的内容：<br />
<br />
public abstract class Duck {<br />
<br />
&nbsp; &nbsp; //将行为类声明为接口类型，降低对行为实现类型的依赖<br />
&nbsp; &nbsp; FlyBehavior flyBehavior;<br />
&nbsp; &nbsp; QuackBehavior quackBehavior;<br />
<br />
&nbsp; &nbsp; public void performFly() {<br />
&nbsp; &nbsp; //不自行处理fly()行为，而是委拖给引用flyBehavior所指向的行为对象<br />
&nbsp; &nbsp; &nbsp; &nbsp; flyBehavior.fly();<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void performQuack() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; quackBehavior.quack();<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void swim() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("All ducks float, even decoys.");&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public abstract void display();<br />
}<br />
<br />
Duck.java不关心如何进行 fly()以及quack(), 这些细节交由具体的行为类完成。<br />
<br />
public class MallardDuck extends Duck{<br />
&nbsp; &nbsp; public MallardDuck() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; flyBehavior=new FlyWithWings();<br />
&nbsp; &nbsp; &nbsp; &nbsp; quackBehavior=new Quack();&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void display() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("Green head.");<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
测试类：<br />
<br />
public class DuckTest {<br />
&nbsp; &nbsp; public static void main(String[] args) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; Duck duck=new MallardDuck();<br />
&nbsp; &nbsp; &nbsp; &nbsp; duck.performFly();<br />
&nbsp; &nbsp; &nbsp; &nbsp; duck.performQuack();&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; <br />
&nbsp; &nbsp; }<br />
}<br />
<br />
在Duck.java子类型MallardDuck.java的构造方法中，直接实例化行为类型，在编译的时侯便指定具体行为类型。当然，我们可以：<br />
<br />
1) 我们可以通过工厂模式或其它模式进一步解藕(可参考后续模式讲解);<br />
2) 或做到在运行时动态地改变行为。<br />
<br />
3) 动态设定行为<br />
<br />
在父类Duck.java中增加设定行为类型的setter方法，接受行为类型对象的参数传入。为了降藕，行为参数被声明为接口类型。这样，既便在运行时，也可以通过调用这二个方法以改变行为。<br />
<br />
public abstract class Duck {<br />
&nbsp; &nbsp; //在刚才Duck.java中加入以下二个方法。<br />
&nbsp; &nbsp; public void setFlyBehavior(FlyBehavior flyBehavior) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.flyBehavior=flyBehavior;<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public void setQuackBehavior(QuackBehavior quackBehavior) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; this.quackBehavior=quackBehavior;<br />
&nbsp; &nbsp; }<br />
<br />
//其它方法同，省略...<br />
}<br />
<br />
测试类：<br />
<br />
public class DuckTest {<br />
&nbsp; &nbsp; public static void main(String[] args) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; Duck duck=new MallardDuck();<br />
&nbsp; &nbsp; &nbsp; &nbsp; duck.performFly();<br />
&nbsp; &nbsp; &nbsp; &nbsp; duck.performQuack();<br />
&nbsp; &nbsp; &nbsp; &nbsp; duck.setFlyBehavior(new FlyNoWay());<br />
&nbsp; &nbsp; &nbsp; &nbsp; duck.performFly();<br />
&nbsp; &nbsp; }<br />
}<br />
<br />
如果，我们要加上火箭助力的飞行行为，只需再新建FlyBehavior.java接口的实现类型。而子类型可通过调用setQuackBehavior(...)方法动态改变。至此，在Duck.java增加新的行为给我们代码所带来的困绕已不复存在。<br />
<br />
该是总结的时侯了，让我们从代码的水中浮出来，做一只在水面上自由游动的鸭子吧:<br />
<br />
3.&nbsp; 解决方案<br />
<br />
MallardDuck 继承&nbsp; Duck抽象类；&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; -&gt; 不变的内容<br />
FlyWithWings 实现 FlyBehavior接口；&nbsp;&nbsp; &nbsp; -&gt; 变化的内容,行为或算法<br />
在Duck.java提供setter方法以装配关系；&nbsp; &nbsp; -&gt; 动态设定行为<br />
<br />
以上就是策略模式的实现三步曲。接下来，让我们透过步骤看本质:<br />
<br />
1) 初始，我们通过继承实现行为的重用，导致了代码的维护问题。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; -&gt; 继承, is a<br />
2) 接着，我们将行为剥离成单独的类型并声明为不变内容的实例变量并通过&nbsp; -&gt; 组合, has a<br />
setter方法以装配关系；<br />
<br />
继承，可以实现静态代码的复用；组合，可以实现代码的弹性维护；使用组合代替继承，可以使代码更好地适应软件开发完后的需求变化。<br />
<br />
策略模式的本质：少用继承，多用组合<br />
</div>
<script>

( function(){
function adjustAdPanel() {

var _nEnableMargin = 1000;
var _nAdWidth = 170;
var _nMainWinWidth = getTop().getMainWin().document.documentElement.clientWidth;
var _oMailContainer = getTop().S( "mailContentContainer", getTop().getMainWin() );

if( _oMailContainer && _nMainWinWidth > _nEnableMargin )
{
_oMailContainer.style.marginRight = _nAdWidth + "px";
}
else
{
_oMailContainer.style.marginRight = "0px";
}
}
getTop().addEvent( getTop().getMainWin(), "resize" , adjustAdPanel  );
adjustAdPanel();

})();
</script>
<img src ="http://www.blogjava.net/jjshcc/aggbug/335308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-10-16 21:21 <a href="http://www.blogjava.net/jjshcc/archive/2010/10/16/335308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>备忘录模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331546.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331546.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331546.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331546.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331546.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331546.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">一、 模式定义:<br />
在不破坏封装的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样就可以将该对象恢复到原先保存前的状态。<br />
二、 模式解说<br />
在程序运行过程中，某些对象的状态处在转换过程中，可能由于某种原因需要保存此时对象的状态，以便程序运行到某个特定阶段，需要恢复到对象之前处于某个点时的状态。如果使用一些公有接口让其它对象来得到对象的状态，便会暴露对象的实现细节。<br />
<br />
三、 结构图<br />
&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/Memento.gif" width="561" height="104" /><br />
1) 备忘录（Memento）角色：备忘录角色存储&#8220;备忘发起角色&#8221;的内部状态。&#8220;备忘发起角色&#8221;根据需要决定备忘录角色存储&#8220;备忘发起角色&#8221;的哪些内部状态。为了防止&#8220;备忘发起角色&#8221;以外的其他对象访问备忘录。备忘录实际上有两个接口，&#8220;备忘录管理者角色&#8221;只能看到备忘录提供的窄接口——对于备忘录角色中存放的属性是不可见的。&#8220;备忘发起角色&#8221;则能够看到一个宽接口——能够得到自己放入备忘录角色中属性。 <br />
2) 备忘发起（Originator）角色：&#8220;备忘发起角色&#8221;创建一个备忘录，用以记录当前时刻它的内部状态。在需要时使用备忘录恢复内部状态。 <br />
3) 备忘录管理者（Caretaker）角色：负责保存好备忘录。不能对备忘录的内容进行操作或检查。</font></p>
<font style="background-color: #cce8cf">
<p><font style="background-color: #cce8cf">class WindowsSystem{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;private String state;<br />
&nbsp;<br />
&nbsp;public Memento createMemento(){ //创建系统备份<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new Memento(state);<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void restoreMemento(Memento m){ //恢复系统<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.state=m.getState();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public String getState() {<br />
&nbsp;&nbsp;return state;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void setState(String state) {<br />
&nbsp;&nbsp;this.state = state;<br />
&nbsp;&nbsp;System.out.println("当前系统处于"+this.state);<br />
&nbsp;}</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf">class Memento{<br />
&nbsp;private String state;</font></p>
<p><font style="background-color: #cce8cf">&nbsp;public Memento(String state) {<br />
&nbsp;&nbsp;this.state = state;<br />
&nbsp;}</font></p>
<p><font style="background-color: #cce8cf">&nbsp;public String getState() {<br />
&nbsp;&nbsp;return state;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public void setState(String state) {<br />
&nbsp;&nbsp;this.state = state;<br />
&nbsp;}<br />
}</font></p>
<p><font style="background-color: #cce8cf">class User{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;private Memento memento;</font></p>
<p><font style="background-color: #cce8cf">&nbsp;public Memento retrieveMemento() {&nbsp; //恢复系统<br />
&nbsp; return this.memento;<br />
&nbsp;}</font></p>
<p><font style="background-color: #cce8cf">&nbsp;public void saveMemento(Memento memento){&nbsp; //保存系统<br />
&nbsp; this.memento = memento;<br />
&nbsp;}<br />
&nbsp;<br />
}</font></p>
<p><font style="background-color: #cce8cf">public class Test{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;public static void main(String[] args) {<br />
&nbsp;<br />
&nbsp;&nbsp; WindowsSystem Winxp = new WindowsSystem(); //Winxp系统<br />
&nbsp;&nbsp; User user = new User();&nbsp;&nbsp; //某一用户<br />
&nbsp;&nbsp; Winxp.setState("好的状态");&nbsp;&nbsp; //Winxp处于好的运行状态<br />
&nbsp;&nbsp; user.saveMemento(Winxp.createMemento()); //用户对系统进行备份，Winxp系统要产生备份文件<br />
&nbsp;&nbsp; Winxp.setState("坏的状态");&nbsp;&nbsp; //Winxp处于不好的运行状态<br />
&nbsp;&nbsp; Winxp.restoreMemento(user.retrieveMemento());&nbsp;&nbsp; //用户发恢复命令，系统进行恢复<br />
&nbsp;&nbsp; System.out.println("当前系统处于"+Winxp.getState());<br />
&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<p><font style="background-color: #cce8cf">在本例中，WindowsSystem是发起人角色(Orignation),Memento是备忘录角色(Memento),User是备忘录管理角色(Caretaker)。Memento提供了两个接口（注意这里的接口,并不是java中的接口，它指的是可被外界调用的方法）：一个是为WindowsSystem 类的宽接口，能够得到WindowsSystem放入Memento的state属性，代码见WindowsSystem的createMemento方法和restoreMemento方法，createMemento方法向Memento放入state属性，restoreMemento方法获得放入的state属性。另一个是为User类提供的窄接口，只能管理Memento而不能对它的内容进行任何操作（见User类）。<br />
五、 优缺点<br />
1） 保持封装边界 使用备忘录可以避免暴露一些只应由原发器管理却又必须存储在原发器之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽起来，从而保持了封装边界。 <br />
2） 它简化了原发器 在其他的保持封装性的设计中，Originator负责保持客户请求过的内部状态版本。这就把所有存储管理的重任交给了Originator。让客户管理它们请求的状态将会简化Originator，并且使得客户工作结束时无需通知原发器。 <br />
3） 使用备忘录可能代价很高 如果原发器在生成备忘录时必须拷贝并存储大量的信息，或者客户非常频繁地创建备忘录和恢复原发器状态，可能会导致非常大的开销。除非封装和恢复Originator状态的开销不大，否则该模式可能并不合适。 <br />
4） 维护备忘录的潜在代价 管理器负责删除它所维护的备忘录。然而，管理器不知道备忘录中有多少个状态。因此当存储备忘录时，一个本来很小的管理器，可能会产生大量的存储开销。<br />
六、 适用性<br />
1）必须保存一个对象在某一个时刻的（部分）状态，这样以后需要时它才能恢复到先前的状态。<br />
2）如果一个用接口来让其它对象直接得到这些状态，将会暴露对象的实现细节并破坏对象的封装性。</font></p>
<p><font style="background-color: #cce8cf"><br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<p><br />
&nbsp;</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 16:35 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中介者模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331528.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 07:56:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331528.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331528.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331528.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331528.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331528.html</trackback:ping><description><![CDATA[<font style="background-color: #cce8cf">中介者模式（Mediator）：用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互。<br />
&nbsp;<br />
通用类图：<br />
&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/215125946.jpg" width="516" height="335" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;举例：在一个公司里面，有很多部门、员工（我们统称他们互相为Colleague&#8220;同事&#8221;），为了完成一定的任务，&#8220;同事&#8221;之间肯定有许多需要互相配合、交流的过程。如果由各个&#8220;同事&#8221;频繁地到处去与自己有关的&#8220;同事&#8221;沟通，这样肯定会形成一个多对多的杂乱的联系网络而造成工作效率低下。<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;此时就需要一位专门的&#8220;中介者&#8221;给各个&#8220;同事&#8221;分配任务，以及统一跟进大家的进度并在&#8220;同事&#8221;之间实时地进行交互，保证&#8220;同事&#8221;之间必须的沟通交流。很明显我们知道此时的&#8220;中介者&#8221;担任了沟通&#8220;同事&#8221;彼此之间的重要角色了，&#8220;中介者&#8221;使得每个&#8220;同事&#8221;都变成一对一的联系方式，减轻了每个&#8220;同事&#8221;的负担，增强工作效率。<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大概理清上面简单例子中的意图之后，给出中介者模式适用场景：<br />
1、一组对象以定义良好但是复杂的方式进行通信。产生的相互依赖关系结构混乱且难以理解。<br />
2、一个对象引用其他很多对象并且直接与这些对象通信,导致难以复用该对象。<br />
3、想定制一个分布在多个类中的行为，而又不想生成太多的子类。<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;其实，中介者模式又被称为&#8220;调停者&#8221;模式，我们可以理解为一群小孩子（同事）吵架了，这时就很需要一位大人（调停者）过来处理好小孩子们的关系，以免发生不必要的冲突。&#8220;中介者&#8221;和&#8220;调停者&#8221;只不过是同一个英语单词&#8220;Mediator&#8221;的不同翻译罢了。反正最最重要的是：中介者就是一个处于众多对象，并恰当地处理众多对象之间相互之间的联系的角色。<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下面给出具体的代码例子，对比通用类图增加了AbstractColleague抽象同事类和AbstractMediator抽象中介者，另外就是两个具体同事类和一个具体中介者，代码中有较多注释，相应类图也不给出了，应该不难理解的：</font> <br />
<font style="background-color: #cce8cf">
<p><br />
同事类族：<br />
&nbsp;//抽象同事类&nbsp; <br />
&nbsp;abstract class AbstractColleague {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;protected AbstractMediator mediator;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;/**既然有中介者，那么每个具体同事必然要与中介者有联系，<br />
&nbsp;&nbsp;* 否则就没必要存在于 这个系统当中，这里的构造函数相当 <br />
&nbsp;&nbsp;* 于向该系统中注册一个中介者，以取得联系&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;*/&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public AbstractColleague(AbstractMediator mediator) {<br />
&nbsp;&nbsp;&nbsp;this.mediator = mediator;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;// 在抽象同事类中添加用于与中介者取得联系（即注册）的方法<br />
&nbsp;&nbsp;public void setMediator(AbstractMediator mediator) {<br />
&nbsp;&nbsp;&nbsp;this.mediator = mediator; <br />
&nbsp;&nbsp;}</p>
<p>&nbsp;} <br />
&nbsp;<br />
&nbsp; //具体同事A&nbsp; <br />
&nbsp; class ColleagueA extends AbstractColleague { <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; //每个具体同事都通过父类构造函数与中介者取得联系 <br />
&nbsp;&nbsp; public ColleagueA(AbstractMediator mediator) {super(mediator);}&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; //每个具体同事必然有自己分内的事，没必要与外界相关联 <br />
&nbsp;&nbsp; public void self(){<br />
&nbsp;&nbsp;System.out.println("同事A --&gt; 做好自己分内的事情 ...");<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; //每个具体同事总有需要与外界交互的操作，通过中介者来处理这些逻辑并安排工作<br />
&nbsp;&nbsp; public void out() {<br />
&nbsp;&nbsp;&nbsp; System.out.println("同事A --&gt; 请求同事B做好分内工作 ...");<br />
&nbsp;&nbsp;&nbsp; super.mediator.execute("ColleagueB", "self");<br />
&nbsp;&nbsp; } <br />
&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp; <br />
&nbsp; //具体同事B&nbsp; <br />
&nbsp; class ColleagueB extends AbstractColleague {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;<br />
&nbsp;&nbsp; public ColleagueB(AbstractMediator mediator) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;super(mediator);&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; public void self() {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;System.out.println("同事B --&gt; 做好自己分内的事情 ...");&nbsp; <br />
&nbsp;&nbsp; }&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; public void out() {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;System.out.println("同事B --&gt; 请求同事A做好分内工作&nbsp; ...");&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;super.mediator.execute("ColleagueA", "self");&nbsp; <br />
&nbsp;&nbsp; } <br />
&nbsp; } <br />
<font style="background-color: #cce8cf">//抽象中介者&nbsp; <br />
&nbsp;abstract class AbstractMediator {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; //中介者肯定需要保持有若干同事的联系方式&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; protected Hashtable&lt;String, AbstractColleague&gt; colleagues = new Hashtable&lt;String, AbstractColleague&gt;();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; //中介者可以动态地与某个同事建立联系&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; public void addColleague(String name, AbstractColleague c) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;this.colleagues.put(name, c);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; //中介者也可以动态地撤销与某个同事的联系&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; public void deleteColleague(String name) {<br />
&nbsp;&nbsp;&nbsp;this.colleagues.remove(name);&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; //中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; public abstract void execute(String name, String method);<br />
&nbsp; }&nbsp; <br />
&nbsp;//具体中介者 <br />
&nbsp;class Mediator extends AbstractMediator{<br />
&nbsp;&nbsp;//中介者最重要的功能，来回奔波与各个同事之间 <br />
&nbsp;&nbsp;public void execute(String name, String method) {<br />
&nbsp;&nbsp;&nbsp;if("self".equals(method)){&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;//各自做好分内事 <br />
&nbsp;&nbsp;&nbsp;&nbsp;if("ColleagueA".equals(name)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colleague.self();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;}else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colleague.self();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;}else { //与其他同事合作&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if("ColleagueA".equals(name)) {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colleague.out();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colleague.out();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;} <br />
&nbsp;} <br />
<br />
</p>
<p><font style="background-color: #cce8cf">&nbsp;//测试类 <br />
&nbsp;public class Client {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public static void main(String[] args) {&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;//创建一个中介者&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;AbstractMediator mediator = new Mediator();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;//创建两个同事&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;ColleagueA colleagueA = new ColleagueA(mediator);&nbsp; <br />
&nbsp;&nbsp;ColleagueB colleagueB = new ColleagueB(mediator);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;//中介者分别与每个同事建立联系&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;mediator.addColleague("ColleagueA", colleagueA);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;mediator.addColleague("ColleagueB", colleagueB);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//同事们开始工作&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;colleagueA.self();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;colleagueA.out();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;System.out.println("======================合作愉快，任务完成！\n");&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;colleagueB.self();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;colleagueB.out();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;System.out.println("======================合作愉快，任务完成！");&nbsp; <br />
&nbsp;&nbsp;} <br />
&nbsp;} <br />
&nbsp;测试结果： <br />
&nbsp;同事A --&gt; 做好自己分内的事情 ...&nbsp; <br />
&nbsp;同事A --&gt; 请求同事B做好分内工作 ...&nbsp; <br />
&nbsp;同事B --&gt; 做好自己分内的事情 ...&nbsp; <br />
&nbsp;======================合作愉快，任务完成！ <br />
&nbsp;同事B --&gt; 做好自己分内的事情 ...&nbsp; <br />
&nbsp;同事B --&gt; 请求同事A做好分内工作&nbsp; ... <br />
&nbsp;同事A --&gt; 做好自己分内的事情 ...<br />
&nbsp;======================合作愉快，任务完成！&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;虽然以上代码中只有两个具体同事类，并且测试类中也只是创建了两个同事，但是这些我们都可以根据中介者模式的宗旨进行适当地扩展，即增加具体同事类，然后中介者就得担负更加重的任务了。为啥？我们看到上面具体中介者类Mediator中的execute()方法中现在就有一堆冗长的判断代码了。虽然可以把它分解并增加到Mediator类中的其它private方法中，但是具体的业务逻辑是少不了的。<br />
&nbsp;<br />
所以，在解耦同事类之间的联系的同时，中介者自身也不免任务过重，因为几乎所有的业务逻辑都交代到中介者身上了，可谓是&#8220;万众期待&#8221;的一个角色了。这就是中介者模式的不足之处了 。 <br />
此外，上面这个代码例子是相当理想的了，有时候我们根本抽取不了&#8220;同事&#8221;之间的共性来形成一个AbstractColleague抽象同事类，这也大大增加了中介者模式的使用难度。&nbsp;&nbsp; </font></p>
<p><font style="background-color: #cce8cf"></font></p>
<p><font style="background-color: #cce8cf">由于上面代码实现中存在"双向关联暴露在App中"的不足之处,修改上面代码，如下：</font></p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<p><font style="background-color: #cce8cf">修改后的同事类族：</font></p>
<p><font style="background-color: #cce8cf">&nbsp;//抽象同事类 <br />
&nbsp;abstract class AbstractColleague {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;<br />
&nbsp;&nbsp;protected AbstractMediator mediator;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//舍去在构造函数中建立起与中介者的联系 <br />
&nbsp;&nbsp;//public AbstractColleague(AbstractMediator mediator) { <br />
&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.mediator = mediator;&nbsp; <br />
&nbsp;&nbsp;//}&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;// 在抽象同事类中添加用于与中介者取得联系（即注册）的方法&nbsp;&nbsp; <br />
&nbsp;&nbsp;public void setMediator(AbstractMediator mediator) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;this.mediator = mediator;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;} <br />
&nbsp;} <br />
&nbsp;<br />
&nbsp;//具体同事A <br />
&nbsp;<br />
&nbsp; class ColleagueA extends AbstractColleague { <br />
&nbsp; <br />
&nbsp;&nbsp; //舍去在构造函数中建立起与中介者的联系 <br />
&nbsp;&nbsp; // public ColleagueA(AbstractMediator mediator) { <br />
&nbsp;&nbsp; // &nbsp;super(mediator); <br />
&nbsp;&nbsp; // }&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; //每个具体同事必然有自己分内的事，没必要与外界相关联&nbsp;&nbsp; <br />
&nbsp;&nbsp; public void self() {&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;System.out.println("同事A --&gt; 做好自己分内的事情 ...");&nbsp;&nbsp; <br />
&nbsp;&nbsp; } <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; //每个具体同事总有需要与外界交互的操作，通过中介者来处理这些逻辑并安排工作&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; public void out() {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;System.out.println("同事A --&gt; 请求同事B做好分内工作 ...");&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;super.mediator.execute("ColleagueB", "self");&nbsp; <br />
&nbsp;&nbsp; } <br />
&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp;//具体同事B&nbsp; <br />
&nbsp;<br />
&nbsp;class ColleagueB extends AbstractColleague {&nbsp;&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;//舍去在构造函数中建立起与中介者的联系&nbsp; <br />
&nbsp;&nbsp;// public ColleagueB(AbstractMediator mediator) {<br />
&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(mediator);&nbsp; <br />
&nbsp;&nbsp;// }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;public void self() {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;System.out.println("同事B --&gt; 做好自己分内的事情 ...");&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;public void out() {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;System.out.println("同事B --&gt; 请求同事A做好分内工作&nbsp; ...");&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;super.mediator.execute("ColleagueA", "self");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;} <br />
&nbsp;} </font></p>
<p>&nbsp;</p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;修改后的中介者：</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;//抽象中介者 <br />
&nbsp;&nbsp;abstract class AbstractMediator {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;//中介者肯定需要保持有若干同事的联系方式&nbsp;&nbsp;&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;protected Hashtable&lt;String, AbstractColleague&gt; colleagues = new Hashtable&lt;String, AbstractColleague&gt;();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//中介者可以动态地与某个同事建立联系&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public void addColleague(String name, AbstractColleague c) {&nbsp; <br />
&nbsp;&nbsp;&nbsp;// 在中介者这里帮助具体同事建立起于中介者的联系&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;c.setMediator(this);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;this.colleagues.put(name, c);&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//中介者也可以动态地撤销与某个同事的联系&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;public void deleteColleague(String name) {&nbsp; <br />
&nbsp;&nbsp;&nbsp;this.colleagues.remove(name);&nbsp;&nbsp; <br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;//中介者必须具备在同事之间处理逻辑、分配任务、促进交流的操作&nbsp; <br />
&nbsp;&nbsp;public abstract void execute(String name, String method);&nbsp; <br />
&nbsp;&nbsp;} <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;//测试类 <br />
&nbsp;&nbsp;public class Client {&nbsp; <br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;public static void main(String[] args) {&nbsp; <br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//创建一个中介者&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;AbstractMediator mediator = new Mediator();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//不用构造函数为具体同事注册中介者来取得联系了 <br />
&nbsp;&nbsp;&nbsp;&nbsp;// ColleagueA colleagueA = new ColleagueA(mediator); <br />
&nbsp;&nbsp;&nbsp;&nbsp;// ColleagueB colleagueB = new ColleagueB(mediator);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;ColleagueA colleagueA = new ColleagueA();&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;ColleagueB colleagueB = new ColleagueB();&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//中介者分别与每个同事建立联系&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;mediator.addColleague("ColleagueA", colleagueA);&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;mediator.addColleague("ColleagueB", colleagueB);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;//同事们开始工作&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;colleagueA.self();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;colleagueA.out();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("======================合作愉快，任务完成！\n");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;colleagueB.self();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;colleagueB.out();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("======================合作愉快，任务完成！");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;}&nbsp;&nbsp; 测试之后的结果与修改前一样。<br />
</font></p>
<p><br />
</font><br />
</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 15:56 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解释器模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331527.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331527.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331527.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331527.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331527.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331527.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">Interpreter模式也叫解释器模式，是由GoF提出的23种设计模式中的一种。Interpreter是行为模式之一，它是一种特殊的设计模式，它建立一个解释器，对于特定的计算机程序设计语言，用来解释预先定义的文法。<br />
本文介绍设计模式中的解释器（Interpreter）模式的概念，用法，以及实际应用中怎么样使用Interpreter模式进行开发。</font></p>
<p><font style="background-color: #cce8cf">Interpreter模式的概念</font></p>
<p><font style="background-color: #cce8cf">Interpreter是一种特殊的设计模式，它建立一个解释器，对于特定的计算机程序设计语言，用来解释预先定义的文法。简单地说，Interpreter模式是一种简单的语法解释器构架。</font></p>
<p><font style="background-color: #cce8cf">Interpreter模式有很多种实现方法，下面我们给出Interpreter模式的一种类图来说明Interpreter模式：</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/080624104128.jpg" width="377" height="177" /></p>
<p><font style="background-color: #cce8cf">在上图中，我们假设需要在Client中解释某文法，Client调用Context来存储文法规则，并调用解释器AbstractionExpression类树来对该文法加以解释。注意，上图只是Interpreter模式的一种实现方式的类图。</font></p>
<font style="background-color: #cce8cf">
<p><br />
Context<br />
&nbsp;&nbsp;&nbsp; 解释器上下文环境类。用来存储解释器的上下文环境，比如需要解释的文法等。<br />
AbstractExpression<br />
&nbsp;&nbsp;&nbsp; 解释器抽象类。<br />
ConcreteExpression<br />
&nbsp;&nbsp;&nbsp; 解释器具体实现类。</p>
<p>&nbsp;</p>
<p><br />
Interpreter模式的实现范例<br />
为了帮助大家理解Interpreter模式的基本概念，我们在这里只举一个最简单的例子。<br />
让一个表达式a经过PlusExpression解释器处理后使该表达式+1，经过MinusExpression解释器处理后使该表达式-1。</p>
<p><br />
代码：</p>
<p>import java.util.ArrayList;<br />
import java.util.List;</p>
<p>public class Client {<br />
&nbsp;&nbsp;&nbsp; public static void main(String []args) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String inputExpr = "10";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context context = new Context(inputExpr);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List list = new ArrayList();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new PlusExpression());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new PlusExpression());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new MinusExpression());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new MinusExpression());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(new MinusExpression());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i=0;i&lt;list.size();i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AbstractExpression expression = (AbstractExpression)list.get(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; expression.interpret(context);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(context.getOutput());<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p><br />
/**<br />
* Context<br />
*<br />
*/<br />
class Context {<br />
&nbsp;&nbsp;&nbsp; private String input;<br />
&nbsp;&nbsp;&nbsp; private int output;</p>
<p>&nbsp;&nbsp;&nbsp; public Context (String input) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this. input = input;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public String getInput() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return input;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setInput(String input) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.input = input;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public int getOutput() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return output;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void setOutput(int output) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.output = output;<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p><br />
/**<br />
* Expression &amp; subclass<br />
*<br />
*/<br />
abstract class AbstractExpression {<br />
&nbsp;&nbsp;&nbsp; public abstract void interpret(Context context);<br />
}</p>
<p>class PlusExpression extends AbstractExpression {<br />
&nbsp;&nbsp;&nbsp; public void interpret(Context context) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("PlusExpression ++");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String input = context.getInput();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int parsedResult = Integer.parseInt(input);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; parsedResult ++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.setInput(String.valueOf(parsedResult));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.setOutput(parsedResult);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>class MinusExpression extends AbstractExpression {<br />
&nbsp;&nbsp;&nbsp; public void interpret(Context context) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("PlusExpression --");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String input = context.getInput();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int parsedResult = Integer.parseInt(input);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; parsedResult --;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.setInput(String.valueOf(parsedResult));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.setOutput(parsedResult);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>&nbsp;</p>
<p>运行并显示Client：</p>
<p>C:\Interpreter&gt;javac *.java<br />
C:\Interpreter&gt;java Client<br />
PlusExpression ++<br />
PlusExpression ++<br />
PlusExpression --<br />
PlusExpression --<br />
PlusExpression --<br />
9<br />
C:\Interpreter&gt;</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331527.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 15:40 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331527.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>命令模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331526.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 07:29:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331526.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331526.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331526.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331526.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331526.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">1.这一节我们的任务是创建一个类似智能家居的万能遥控器，控制各种家电。我们需要将&#8220;请求&#8221;封装成对象（一个命令对象通过在特定接收者上绑定一组动作来封装请求），以便使用不同的请求、队列、或者日志来参数化其对象——这就是命令模式。</font></p>
<p><font style="background-color: #cce8cf">2.我们具体来看一个例子：</font></p>
<p><font style="background-color: #cce8cf">首先我们要完成对命令的对象封装：</font></p>
<p><font style="background-color: #cce8cf">public interface Command { <br />
&nbsp;&nbsp;&nbsp; public void execute(); <br />
}</font></p>
<p><font style="background-color: #cce8cf">只有一个方法，所有的具体命令的对象都要实现这个接口，这就做到了封装，比如对于灯这个对象，</font></p>
<p><font style="background-color: #cce8cf">public class Light { </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public Light() { <br />
&nbsp;&nbsp;&nbsp; } </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void on() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Light is on"); <br />
&nbsp;&nbsp;&nbsp; } </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void off() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Light is off"); <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">我们可以通过上述接口封装&#8220;开灯&#8221;这个命令，这个就是所谓的命令对象，它把动作和接收者包进对象之中，只暴露一个execute方法：</font></p>
<p><font style="background-color: #cce8cf">public class LightOnCommand implements Command { <br />
&nbsp;&nbsp;&nbsp; Light light; <br />
&nbsp;&nbsp;&nbsp; public LightOnCommand(Light light) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.light = light; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void execute() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; light.on(); <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">而我们的遥控器对于上述封装要一无所知，这样才能做到解耦：</font></p>
<p><font style="background-color: #cce8cf">public class SimpleRemoteControl { <br />
&nbsp;&nbsp;&nbsp; Command slot; <br />
&nbsp;&nbsp;&nbsp; public SimpleRemoteControl() {} <br />
&nbsp;&nbsp;&nbsp; public void setCommand(Command command) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slot = command; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void buttonWasPressed() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; slot.execute(); <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">我们现在试着用一下这个遥控器，我们首先创建一个遥控器，然后创建开灯这个命令并置于其中，最后按下按键，这样，遥控器不知道是哪个对象（实际上是灯）进行了哪个动作（实际上是开灯这个动作）就可以完成请求的发出。如此一来，遥控器和灯之间的耦合性就非常低了：</font></p>
<p><font style="background-color: #cce8cf">public class RemoteControlTest { <br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SimpleRemoteControl remote = new SimpleRemoteControl(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Light light = new Light(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LightOnCommand lightOn = new LightOnCommand(light); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remote.setCommand(lightOn); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remote.buttonWasPressed(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">很简单的，我们想要在一个遥控机中实现控制多个家电的能力就可以用一个数组来维护这样的一组命令，可以看做提供了多个命令的插槽：</font></p>
<p><font style="background-color: #cce8cf">public class RemoteControl { <br />
&nbsp;&nbsp;&nbsp; Command[] onCommands; <br />
&nbsp;&nbsp;&nbsp; Command[] offCommands; <br />
&nbsp;&nbsp;&nbsp; public RemoteControl() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands = new Command[7]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands = new Command[7]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command noCommand = new NoCommand(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 7; i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands[i] = noCommand; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands[i] = noCommand; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void setCommand(int slot, Command onCommand, Command offCommand) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands[slot] = onCommand; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands[slot] = offCommand; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void onButtonWasPushed(int slot) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands[slot].execute(); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void offButtonWasPushed(int slot) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands[slot].execute(); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public String toString() { <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">你可能会注意到一个叫做noCommand的对象出现在初始化遥控器对象时。这个是个小技巧，我们并不想每次都检查某个插槽是不是都绑定了命令，那么我们就引入了这个东东，实现一个不做事情的命令：</font></p>
<p><font style="background-color: #cce8cf">public class NoCommand implements Command { <br />
&nbsp;&nbsp;&nbsp; public void execute() { } <br />
}</font></p>
<p><font style="background-color: #cce8cf">这样初始化就让每一个插槽都有命令了，以后若不进一步指明命令的插槽，那么就是默认这个noCommand对象。这就是一个典型的&#8220;空对象&#8221;例子，当你不想返回一个有意义的对象时，空对象就十分有用，此时空对象可以做成判断NULL或者提示&#8220;未绑定&#8221;信息的工作。</font></p>
<p><font style="background-color: #cce8cf">3.我们在命令模式中也可以设置类似undo的撤销命令来撤销发出的命令请求：</font></p>
<p><font style="background-color: #cce8cf">public interface Command { <br />
&nbsp;&nbsp;&nbsp; public void execute(); <br />
&nbsp;&nbsp;&nbsp; public void undo(); <br />
}</font></p>
<p><font style="background-color: #cce8cf">我们还是拿开电灯这个操作来说明，毕竟这足够简单：对于一个开灯命令，其对应的撤销命令自然是&#8220;关电灯&#8221;：</font></p>
<p><font style="background-color: #cce8cf">public class LightOnCommand implements Command { <br />
&nbsp;&nbsp;&nbsp; Light light; <br />
&nbsp;&nbsp;&nbsp; public LightOnCommand(Light light) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.light = light; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void execute() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; light.on(); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void undo() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; light.off(); <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">虽然这简单之极，这还没完，我们必须让遥控器记住上次到底做了什么操作，才可能去撤销：</font></p>
<p><font style="background-color: #cce8cf">package headfirst.command.undo; </font></p>
<p><font style="background-color: #cce8cf">import java.util.*; </font></p>
<p><font style="background-color: #cce8cf">// <br />
// This is the invoker <br />
// <br />
public class RemoteControlWithUndo { <br />
&nbsp;&nbsp;&nbsp; Command[] onCommands; <br />
&nbsp;&nbsp;&nbsp; Command[] offCommands; <br />
&nbsp;&nbsp;&nbsp; Command undoCommand; <br />
&nbsp;&nbsp;&nbsp; public RemoteControlWithUndo() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands = new Command[7]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands = new Command[7]; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command noCommand = new NoCommand(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;7;i++) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands[i] = noCommand; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands[i] = noCommand; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undoCommand = noCommand; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void setCommand(int slot, Command onCommand, Command offCommand) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands[slot] = onCommand; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands[slot] = offCommand; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void onButtonWasPushed(int slot) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; onCommands[slot].execute(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undoCommand = onCommands[slot];//记录操作动作 <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void offButtonWasPushed(int slot) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offCommands[slot].execute(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undoCommand = offCommands[slot];//记录操作动作 <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void undoButtonWasPushed() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; undoCommand.undo();//发出撤销命令 <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public String toString() { <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">对于电灯，我们只有两种状态，但是要是多个状态呢？我们举一个吊扇的例子，吊扇有多个转速，高中低关，四个状态：</font></p>
<p><font style="background-color: #cce8cf">public class CeilingFan { <br />
&nbsp;&nbsp;&nbsp; String location = ""; <br />
&nbsp;&nbsp;&nbsp; int level; <br />
&nbsp;&nbsp;&nbsp; public static final int HIGH = 2; <br />
&nbsp;&nbsp;&nbsp; public static final int MEDIUM = 1; <br />
&nbsp;&nbsp;&nbsp; public static final int LOW = 0; <br />
&nbsp;&nbsp;&nbsp; public CeilingFan(String location) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.location = location; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void high() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // turns the ceiling fan on to high <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; level = HIGH; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(location + " ceiling fan is on high"); <br />
&nbsp;&nbsp;&nbsp; } </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void medium() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // turns the ceiling fan on to medium <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; level = MEDIUM; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(location + " ceiling fan is on medium"); <br />
&nbsp;&nbsp;&nbsp; } </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void low() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // turns the ceiling fan on to low <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; level = LOW; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(location + " ceiling fan is on low"); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void off() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // turns the ceiling fan off <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; level = 0; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(location + " ceiling fan is off"); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public int getSpeed() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return level; <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">那么在实现风扇各个转速命令时，就要去记录在执行这个命令前风扇的转速，其撤销命令中则根据记录的部分完成undo操作。</font></p>
<p><font style="background-color: #cce8cf">public class CeilingFanHighCommand implements Command { <br />
&nbsp;&nbsp;&nbsp; CeilingFan ceilingFan; <br />
&nbsp;&nbsp;&nbsp; int prevSpeed; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public CeilingFanHighCommand(CeilingFan ceilingFan) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ceilingFan = ceilingFan; <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void execute() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prevSpeed = ceilingFan.getSpeed(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ceilingFan.high(); <br />
&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; public void undo() { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (prevSpeed) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case CeilingFan.HIGH:&nbsp;&nbsp;&nbsp;&nbsp; ceilingFan.high(); break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case CeilingFan.MEDIUM: ceilingFan.medium(); break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case CeilingFan.LOW:&nbsp;&nbsp;&nbsp;&nbsp; ceilingFan.low(); break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ceilingFan.off(); break; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp;&nbsp;&nbsp; } <br />
}</font></p>
<p><font style="background-color: #cce8cf">当然你也可以实现诸如多个命令批量执行和完成多个撤销操作。</font></p>
<p><font style="background-color: #cce8cf">命令模式可以用于工作队列和日志操作等方面。</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331526.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 15:29 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331526.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>责任链模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331514.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 06:44:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331514.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331514.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331514.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331514.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<p><font style="background-color: #cce8cf">　显然，击鼓传花符合责任链模式的定义。参加游戏的人是一个个的具体处理者对象，击鼓的人便是客户端对象。花代表酒令，是传向处理者的请求，每一个参加游戏的人在接到传来的花时，可选择的行为只有两个：一是将花向下传；一是执行酒令---喝酒。一个人不能既执行酒令，又向下家传花；当某一个人执行了酒令之后，游戏重新开始。击鼓的人并不知道最终是由哪一个做游戏的人执行酒令，当然执行酒令的人必然是做游戏的人们中的一个。</font></p>
<p><font style="background-color: #cce8cf">　　击鼓传花的类图结构如下：</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/jt-2002-4-15-flowerpassing0.gif" width="339" height="239" /></p>
<p><font style="background-color: #cce8cf">图5、击鼓传花系统的类图定义。</font></p>
<p><font style="background-color: #cce8cf">　　单独考虑击鼓传花系统，那么像贾母、贾赦、贾政、贾宝玉和贾环等传花者均应当是&#8220;具体传花者&#8221;的对象，而不应当是单独的类；但是责任链模式往往是建立在现有系统的基础之上的，因此链的结构和组成不由责任链模式本身决定。</font></p>
<font style="background-color: #cce8cf">
<p><br />
　　系统的分析<br />
　　在《红楼梦》第七十五回里生动地描述了贾府里的一场击鼓传花游戏：&#8220;贾母坐下，左垂首贾赦，贾珍，贾琏，贾蓉，右垂首贾政，宝玉，贾环，贾兰，团团围坐。...贾母便命折一枝桂花来，命一媳妇在屏后击鼓传花。若花到谁手中，饮酒一杯...于是先从贾母起，次贾赦，一一接过。鼓声两转，恰恰在贾政手中住了，只得饮了酒。&#8221;这场游戏接着又把花传到了宝玉和贾赦手里，接着又传到了在贾环手里...</p>
<p><br />
　　如果用一个对象系统描述贾府，那么贾母、贾赦、贾政、贾宝玉和贾环等等就应当分别由一个个具体类代表，而这场击鼓传花游戏的类图，按照责任链模式，应当如下图所示：</p>
<p>&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/jt-2002-4-15-flowerpassing2.gif" width="583" height="305" /><br />
</p>
<p></font>&nbsp;<font style="background-color: #cce8cf">图6、红楼梦中的击鼓传花游戏的示意性类图。 <br />
　换言之，在击鼓传花游戏里面，有下面的几种角色：<br />
　抽象传花者，或Handler角色、定义出参加游戏的传花人要遵守的规则，也就是一个处理请求的接口　和对下家的引用；<br />
　具体传花者，或ConcreteHandler角色、每一个传花者都知道下家是谁，要么执行酒令，要么把花　向下传。这个角色由贾母、贾赦、贾珍、贾琏、贾蓉、贾政、宝玉、贾环、贾兰等扮演。　击鼓人，或Client角色、即行酒令的击鼓之人。《红楼梦》没有给出此人的具体姓名，只是说由&#8220;一　媳妇&#8221;扮演。</font><br />
<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/jt-2002-4-15-flowerpassing3.gif" width="522" height="184" /><br />
</p>
<p><font style="background-color: #cce8cf">图7、贾府这次击鼓传花的示意性对象图。 </font></p>
<p><font style="background-color: #cce8cf">　　可以看出，击鼓传花游戏满足责任链模式的定义，是纯的责任链模式的例子.<br />
Java系统的解下面的类图给出了这些类的具体接口设计。读者不难看出，DrumBeater（击鼓者）、Player（传花者）、JiaMu（贾母）、JiaShe（贾赦）、JiaZheng（贾政）、JiaBaoYu（宝玉）、JiaHuan（贾环）等组成这个系统。<br />
</font></p>
<p><br />
<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/jt-2002-4-15-flowerpassing.gif" width="520" height="412" /><br />
</p>
<p><font style="background-color: #cce8cf">图8、击鼓传花的类图完全符合责任链模式的定义。 </font></p>
<p><font style="background-color: #cce8cf">　　下面是客户端类DrumBeater的源代码：</font></p>
<p><font style="background-color: #cce8cf">&nbsp;//DrumBeater的源代码<br />
&nbsp;public class DrumBeater <br />
&nbsp;{<br />
&nbsp;　 private static Player player;<br />
&nbsp;　 static public void main(String[] args) <br />
&nbsp;　　 { <br />
&nbsp;　　　 player = new JiaMu( new JiaShe( new JiaZheng( new JiaBaoYu(new JiaHuan(null))))); <br />
&nbsp;　　　　player.handle(4);<br />
&nbsp;　　 } <br />
&nbsp;}&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;//抽象传花者Play类的源代码<br />
&nbsp;abstract class Player <br />
&nbsp;{<br />
&nbsp;&nbsp;abstract public void handle(int i);<br />
&nbsp;&nbsp;private&nbsp; Player successor; <br />
&nbsp;&nbsp;public&nbsp;&nbsp; Player() { successor = null;}</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;protected void setSuccessor(Player aSuccessor) <br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;　 successor = aSuccessor;<br />
&nbsp;&nbsp;}</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;public void next(int index)<br />
&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;　 if( successor != null ) <br />
&nbsp;&nbsp;　　 { <br />
&nbsp;&nbsp;　　　 successor.handle(index);<br />
&nbsp;&nbsp;　　 }<br />
&nbsp;&nbsp;　 else <br />
&nbsp;&nbsp;　　 { <br />
&nbsp;&nbsp;　　　 System.out.println("Program terminated."); <br />
&nbsp;&nbsp;　　 }<br />
&nbsp;&nbsp;　 }<br />
&nbsp;&nbsp;}&nbsp; <br />
&nbsp;}<br />
　 </font></p>
<p><font style="background-color: #cce8cf">　　抽象类Player给出了两个方法的实现，以格式setSuccessor()，另一个是next()。前者用来设置一个传花者对象的下家，后者用来将酒令传给下家。Player类给出了一个抽象方法handle()，代表执行酒令。</font></p>
<p><font style="background-color: #cce8cf">　　下面的这些具体传花者类将给出handle()方法的实现。</font></p>
<p><font style="background-color: #cce8cf">&nbsp;//贾母的JiaMu类<br />
&nbsp;class JiaMu extends Player <br />
&nbsp;{<br />
&nbsp;　　 public JiaMu(Player aSuccessor)<br />
&nbsp;　　 { <br />
&nbsp;　　　 this.setSuccessor(aSuccessor);<br />
&nbsp;　　 }<br />
&nbsp;　　 public void handle(int i)<br />
&nbsp;　　 { <br />
&nbsp;　　　 if( i == 1 )<br />
&nbsp;　　　 { <br />
&nbsp;　　　　 System.out.println("Jia Mu gotta drink!"); <br />
&nbsp;　　　 }<br />
&nbsp;　　　 else<br />
&nbsp;　　　 { <br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Jia Mu passed!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;next(i);<br />
&nbsp;　　　 }<br />
&nbsp;　　 }<br />
&nbsp;}&nbsp; </font></p>
<p><font style="background-color: #cce8cf">　 <br />
&nbsp;&nbsp; //贾赦的JiaShe类<br />
&nbsp;&nbsp; class JiaShe extends Player <br />
　 {<br />
　　 public JiaShe(Player aSuccessor)<br />
　　 {<br />
　　　 this.setSuccessor(aSuccessor); <br />
　　 }<br />
　　 public void handle(int i)<br />
　　　 { <br />
　　　　 if( i == 2 ) <br />
　　　　 {<br />
　　　　　 System.out.println("Jia She gotta drink!"); <br />
　　　　 }<br />
　　　　 else<br />
　　　　 {<br />
　　　　　 System.out.println("Jia She passed!");<br />
　　　　　 next(i);<br />
　　　　 }<br />
　　　 }<br />
　 }&nbsp; </font></p>
<p><font style="background-color: #cce8cf">　　 <br />
&nbsp;&nbsp; //贾政的JiaZheng类<br />
&nbsp;&nbsp; class JiaZheng extends Player <br />
　 {<br />
　　 public JiaZheng(Player aSuccessor)<br />
　　 {<br />
　　　 this.setSuccessor(aSuccessor); <br />
　　 }<br />
　　 public void handle(int i)<br />
　　 { <br />
　　　 if( i == 3 )<br />
　　　 { <br />
　　　　 System.out.println("Jia Zheng gotta drink!");<br />
　　　 } <br />
　　　 else<br />
　　　 {<br />
　　　　 System.out.println("Jia Zheng passed!"); <br />
　　　　 next(i); <br />
　　　 }<br />
　　 }<br />
　 }&nbsp; </font></p>
<p><font style="background-color: #cce8cf">　 <br />
&nbsp;//贾宝玉的JiaBaoYu类<br />
&nbsp;&nbsp; class JiaBaoYu extends Player<br />
　 {<br />
　　 public JiaBaoYu(Player aSuccessor)<br />
　　 {<br />
　　　 this.setSuccessor(aSuccessor); <br />
　　 }<br />
　　 public void handle(int i)<br />
　　 {<br />
　　　 if( i == 4 ) <br />
　　　 {<br />
　　　　 System.out.println("Jia Bao Yu gotta drink!");<br />
　　　 } <br />
　　　 else<br />
　　　 {<br />
　　　　 System.out.println("Jia Bao Yu passed!");<br />
　　　　 next(i);<br />
　　　 }<br />
　　 }<br />
　 }&nbsp; </font></p>
<p><font style="background-color: #cce8cf">　　 <br />
&nbsp;//JiaHuan类<br />
&nbsp;class JiaHuan extends Player <br />
　 {<br />
　　 public JiaHuan(Player aSuccessor) <br />
　　　 { <br />
　　　　 this.setSuccessor(aSuccessor);<br />
　　　 }<br />
　　 public void handle(int i)<br />
　　 {<br />
　　　 if( i == 5 )<br />
　　　 {<br />
　　　　 System.out.println("Jia Huan gotta drink!");<br />
　　　 }<br />
　　　 else<br />
　　　 {<br />
　　　　 System.out.println("Jia Huan passed!");<br />
　　　　 next(i);<br />
　　　 }<br />
　　 }<br />
　 }&nbsp; </font></p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<p><font style="background-color: #cce8cf">　　可以看出，DrumBeater设定了责任链的成员和他们的顺序：责任链由贾母开始到贾环，周而复始。JiaMu类、JiaShe类、JiaZheng类、JiaBaoYu类与JiaHuan类均是抽象传花者Player类的子类。</font></p>
<p><font style="background-color: #cce8cf">　　本节所实现的DrumBeater类在把请求传给贾母时，实际上指定了由4号传花者处理酒令。虽然DrumBeater并不知道哪一个传花者类持有号码4，但是这个号码在本系统一开始就写死的。这当然并不符合击鼓传花游戏的精神，因为这个游戏实际上要求有两个同时进行的过程：击鼓过程和传花过程。击鼓应当是定时停止的，当击鼓停止时，执行酒令者就确定了。但是本节这样做可以使问题得到简化并将读者的精力放在责任链模式上，而不是两个过程的处理上。<br />
&nbsp;<br />
在什么情况下使用责任链模式</font></p>
<p><font style="background-color: #cce8cf">　　在下面的情况下使用责任链模式：</font></p>
<p><font style="background-color: #cce8cf">　　第一、系统已经有一个由处理者对象组成的链。这个链可能由复合模式给出，</font></p>
<p><font style="background-color: #cce8cf">　　第一、当有多于一个的处理者对象会处理一个请求，而且在事先并不知道到底由哪一个处理者对象处理一个请求。这个处理者对象是动态确定的。</font></p>
<p><font style="background-color: #cce8cf">　　第二、当系统想发出一个请求给多个处理者对象中的某一个，但是不明显指定是哪一个处理者对象会处理此请求。</font></p>
<p><font style="background-color: #cce8cf">　　第三、当处理一个请求的处理者对象集合需要动态地指定时。</font></p>
<p><font style="background-color: #cce8cf">　　使用责任链模式的长处和短处</font></p>
<p><font style="background-color: #cce8cf">　　责任链模式减低了发出命令的对象和处理命令的对象之间的耦合，它允许多与一个的处理者对象根据自己的逻辑来决定哪一个处理者最终处理这个命令。换言之，发出命令的对象只是把命令传给链结构的起始者，而不需要知道到底是链上的哪一个节点处理了这个命令。</font></p>
<p><font style="background-color: #cce8cf">　　显然，这意味着在处理命令上，允许系统有更多的灵活性。哪一个对象最终处理一个命令可以因为由那些对象参加责任链、以及这些对象在责任链上的位置不同而有所不同。</font></p>
<p><font style="background-color: #cce8cf">　　责任链模式的实现</font></p>
<p><font style="background-color: #cce8cf">　　链结构的由来</font></p>
<p><font style="background-color: #cce8cf">　　值得指出的是，责任链模式并不创建出责任链。责任链的创建必须有系统的其它部分完成。</font></p>
<p><font style="background-color: #cce8cf">　　责任链模式减低了请求的发送端和接收端之间的耦合，使多个对象都有机会处理这个请求。一个链可以是一条线，一个树，也可以是一个环。链的拓扑结构可以是单连通的或多连通的，责任链模式并不指定责任链的拓扑结构。但是责任链模式要求在同一个时间里，命令只可以被传给一个下家（或被处理掉）；而不可以传给多于一个下家。在下面的图中，责任链是一个树结构的一部分。</font></p>
<p><font style="background-color: #cce8cf">&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/jt-2002-4-15-tree.gif" width="482" height="221" /></font></p>
<p><font style="background-color: #cce8cf">图9、责任链是系统已有的树结构的一部分。图中有阴影的对象给出了一个可能的命令传播路径。</font></p>
<p><font style="background-color: #cce8cf">　　责任链的成员往往是一个更大的结构的一部分。比如在前面所讨论的《红楼梦》中击鼓传花的游戏中，所有的成员都是贾府的成员。如果责任链的成员不存在，那么为了使用责任链模式，就必须创建它们；责任链的具体处理者对象可以是同一个具体处理者类的实例。</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 14:44 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Singleton（单态）模式 和 Double-Checked Locking（双重检查锁定）模式 </title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331511.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331511.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331511.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331511.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331511.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331511.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">确保一个特定的类只有一个对象被实例化。</font></p>
<p><font style="background-color: #cce8cf">Singleton：用于单线程应用程序<br />
public class Singleton {</font></p>
<p><font style="background-color: #cce8cf">　　private Singleton(){}</font></p>
<p><font style="background-color: #cce8cf">　　//在自己内部定义自己一个实例，是不是很奇怪？<br />
　　//注意这是private 只供内部调用</font></p>
<p><font style="background-color: #cce8cf">　　private static Singleton instance = new Singleton();</font></p>
<p><font style="background-color: #cce8cf">　　//这里提供了一个供外部访问本class的静态方法，可以直接访问　　<br />
　　public static Singleton getInstance() {<br />
　　　　return instance; 　　<br />
　　 } <br />
}&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">Double-Checked Locking：用于多线程应用程序</font></p>
<p><font style="background-color: #cce8cf">public class Singleton { <br />
　　private static Singleton instance = null;</font></p>
<p><font style="background-color: #cce8cf">　　public static synchronized Singleton getInstance() {</font></p>
<p><font style="background-color: #cce8cf">　　//这个方法比上面有所改进，不用每次都进行生成对象，只是第一次　　　 　<br />
　　//使用时生成实例，提高了效率！<br />
　　if (instance==null)<br />
　　　　instance＝new Singleton();<br />
　　return instance; 　　} <br />
} <br />
&nbsp;</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331511.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 14:21 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331511.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>原型模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331509.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 06:13:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331509.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331509.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331509.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331509.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331509.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">原型模式（Prototype）属于创建型模式，实现了对象的创建；具体而言，它实现了对象的复制（拷贝）。</font></p>
<p><font style="background-color: #cce8cf">关于对象的复制，我们需要考虑以下两个问题：</font></p>
<p><font style="background-color: #cce8cf">1.对象实时状态的复制；</font></p>
<p><font style="background-color: #cce8cf">2.对象引用成员变量的复制。</font></p>
<p><font style="background-color: #cce8cf">如果通过new方式来实例化对象，只能得到对象的初始状态，这显然不行。在Java中，所有类都继承于Object类，而Object有一个clone()方法。通过查看JDK文档，该clone()方法虽然能够实现实时状态的复制（解决了问题1），但是只能实现&#8220;浅拷贝&#8221;，即只能实现基本数据类型（包含String）的拷贝，不能实现引用数据类型的拷贝，并不能满足原型模式的要求（问题2不能得到解决）。</font></p>
<font style="background-color: #cce8cf">
<p><br />
怎么办？重写类的clone()方法，通过对象的写入写出来实现&#8220;深拷贝&#8221;和实时状态复制。重写（Override）需要遵循的条件是：方法名，参数列表和父类一致；返回值是父类返回值的子类。重写clone方法完全满足了条件。（无参数，方法名一致，返回的所有类都是Object的子类；当然可以不重写，方法名改用其它，但是不建议。）</p>
<p>可以想象，若一个类含有若干个引用数据类型（类），而该引用数据类型（类）中又含有若干个引用数据类型&#8230;这样嵌套下去，需要复制的就不是一个类，而是一个&#8220;类树&#8221;（树结构）。Java通过将对象序列化到文件或内存，底层封装了对类树的遍历和复制过程。这个机制已经封装，我们无需了解。</p>
<p>考虑这样一个应用场景：</p>
<p>一个RPG游戏，英雄类含有两个成员变量：一个是英雄名字，为普通成员变量；一个是英雄属性，为引用成员变量（封装了英雄的状态，如生命值、魔法值）。为了实现对象实时拷贝的高效率，我们选择将对象序列化到内存（不是文件（硬盘））。通过输入输出流实现对象的&#8220;深拷贝&#8221;。</p>
<p>具体的实现代码如下：</p>
<p><br />
package com.csufox.Prototype;</p>
<p>import java.io.ByteArrayInputStream;<br />
import java.io.ByteArrayOutputStream;<br />
import java.io.ObjectInputStream;<br />
import java.io.ObjectOutputStream;</p>
<p>class Property implements java.io.Serializable{<br />
&nbsp;&nbsp;&nbsp; int blood = 100;&nbsp; //生命值<br />
&nbsp;&nbsp;&nbsp; int magic = 100;&nbsp; //魔法值<br />
}</p>
<p>class Hero implements java.io.Serializable{ //需要实现序列化接口<br />
&nbsp;&nbsp;&nbsp; String name = "英雄";<br />
&nbsp;&nbsp;&nbsp; Property property = new Property(); //含有引用成员，需要&#8220;深&#8221;拷贝</p>
<p>&nbsp;&nbsp;&nbsp; public Hero clone(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hero copy = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实例化ObjectOutputStream，写入字节数组输出流<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ByteArrayOutputStream baos = new ByteArrayOutputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectOutputStream oos = new ObjectOutputStream(baos);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oos.writeObject(this);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] data = baos.toByteArray();&nbsp; //data是字节数组，存储着对象的拷贝</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实例化ObjectInputStream，从字节数组输入流中读取对象<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ByteArrayInputStream bais = new ByteArrayInputStream(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectInputStream ois = new ObjectInputStream(bais);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copy = (Hero)ois.readObject();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception ex){ex.printStackTrace();}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return copy;<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>public class Prototype {<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hero hero = new Hero();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hero.property.blood -= 20;&nbsp; //原英雄状态发生改变，生命值减少20<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Hero copy = hero.clone();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(copy.property.blood);&nbsp; //输出&#8220;80&#8221;，说明实现了实时拷贝和深拷贝<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
&nbsp;</p>
<p>由上述代码可知，原型模式具有以下特点：</p>
<p>实现Serializable序列化接口； <br />
在类中重写clone()方法（由Object继承而来）； <br />
通过Java I/0，将对象写入内存，然后再从内存读取（反序列化）。 </font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 14:13 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>建造者模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331506.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 05:58:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331506.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331506.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331506.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331506.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331506.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">Builder模式定义:<br />
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.</font></p>
<p><font style="background-color: #cce8cf">Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.用户不知道内部的具体构建细节.Builder模式是非常类似抽象工厂模式,细微的区别大概只有在反复使用中才能体会到.</font></p>
<p><font style="background-color: #cce8cf">为何使用?<br />
是为了将构建复杂对象的过程和它的部件解耦.注意: 是解耦过程和部件.</font></p>
<p><font style="background-color: #cce8cf">因为一个复杂的对象,不但有很多大量组成部分,如汽车,有很多部件:车轮 方向盘 发动机还有各种小零件等等,部件很多,但远不止这些,如何将这些部件装配成一辆汽车,这个装配过程也很复杂(需要很好的组装技术),Builder模式就是为了将部件和组装过程分开.</font></p>
<p><font style="background-color: #cce8cf">如何使用?<br />
首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部件的创建分别开来,分别用Builder类和Director类来表示.</font></p>
<p><font style="background-color: #cce8cf">首先,需要一个接口,它定义如何创建复杂对象的各个部件:<br />
&nbsp; <br />
public interface Builder { </font></p>
<p><font style="background-color: #cce8cf">　　//创建部件A　　比如创建汽车车轮<br />
　　void buildPartA(); <br />
　　//创建部件B 比如创建汽车方向盘<br />
　　void buildPartB(); <br />
　　//创建部件C 比如创建汽车发动机<br />
　　void buildPartC(); </font></p>
<p><font style="background-color: #cce8cf">　　//返回最后组装成品结果 (返回最后装配好的汽车)<br />
　　//成品的组装过程不在这里进行,而是转移到下面的Director类中进行.<br />
　　//从而实现了解耦过程和部件<br />
　　Product getResult(); </font></p>
<p><font style="background-color: #cce8cf">}&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">用Director构建最后的复杂对象,而在上面Builder接口中封装的是如何创建一个个部件(复杂对象是由这些部件组成的),也就是说Director的内容是如何将部件最后组装成成品:<br />
&nbsp;&nbsp; <br />
public class Director {</font></p>
<p><font style="background-color: #cce8cf">　　private Builder builder; </font></p>
<p><font style="background-color: #cce8cf">　　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(); </font></p>
<p><font style="background-color: #cce8cf">　　} </font></p>
<p><font style="background-color: #cce8cf">}&nbsp;<br />
&nbsp;</font></p>
<p><font style="background-color: #cce8cf">Builder的具体实现ConcreteBuilder:<br />
通过具体完成接口Builder来构建或装配产品的部件;<br />
定义并明确它所要创建的是什么具体东西;<br />
提供一个可以重新获取产品的接口:</font></p>
<p><font style="background-color: #cce8cf">&nbsp;<br />
public class ConcreteBuilder implements Builder { </font></p>
<p><font style="background-color: #cce8cf">　　Part partA, partB, partC; <br />
　　public void buildPartA() {<br />
　　　　//这里是具体如何构建partA的代码</font></p>
<p><font style="background-color: #cce8cf">　　}; <br />
　　public void buildPartB() { <br />
　　　　//这里是具体如何构建partB的代码<br />
　　}; <br />
　　 public void buildPartC() { <br />
　　　　//这里是具体如何构建partB的代码<br />
　　}; <br />
　　 public Product getResult() { <br />
　　　　//返回最后组装成品结果<br />
　　}; </font></p>
<font style="background-color: #cce8cf">
<p><br />
}<br />
&nbsp;</p>
<p>复杂对象:产品Product:</p>
<p>public interface Product { }&nbsp; </p>
<p><br />
复杂对象的部件:</p>
<p>public interface Part { } </p>
<p>&nbsp;</p>
<p>我们看看如何调用Builder模式:</p>
<p>ConcreteBuilder builder = new ConcreteBuilder();<br />
Director director = new Director( builder ); </p>
<p>director.construct(); <br />
Product product = builder.getResult(); </p>
<p>Builder模式的应用<br />
在Java实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池.</p>
<p>"池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能.修改Builder模式中Director类使之能诊断"断肢"断在哪个部件上,再修复这个部件.</p>
<p>&nbsp;</p>
<p>&nbsp;</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 13:58 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>工厂方法设计模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331496.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 04:08:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331496.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331496.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331496.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331496.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331496.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">在设计模式中,Factory Method也是比较简单的一个,但应用非常广泛,EJB,RMI,COM,CORBA,Swing中都可以看到此模式的影子,它是最重要的模式之一.在很多地方我们都会看到xxxFactory这样命名的类,那么,什么是Factory Method,为什么要用这个模式,如何用Java语言来实现该模式,这就是本文想要带给大家的内容.<br />
基本概念</font></p>
<p><font style="background-color: #cce8cf">FactoryMethod是一种创建性模式,它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪种类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式了.简单说来,Factory Method可以根据不同的条件产生不同的实例,当然这些不同的实例通常是属于相同的类型,具有共同的父类.Factory Method把创建这些实例的具体过程封装起来了,简化了客户端的应用,也改善了程序的扩展性,使得将来可以做最小的改动就可以加入新的待创建的类. 通常我们将Factory Method作为一种标准的创建对象的方法,当发现需要更多的灵活性的时候,就开始考虑向其它创建型模式转化</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;<font style="background-color: #cce8cf"></p>
<p>简单分析</p>
<p>图1是Factory Method 模式的结构图,这里提供了一些术语,让我们可以进行更方便的描述:<br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/fig1.gif" width="530" height="178" /></div>
<br />
</p>
<p>Product: 需要创建的产品的抽象类. <br />
ConcreteProduct: Product的子类,一系列具体的产品. <br />
Creator: 抽象创建器接口,声明返回Product类型对象的Factory Method. <br />
ConcreteCreator: 具体的创建器,重写Creator中的Factory Method,返回ConcreteProduct类型的实例. </p>
<p>图1: Factory Method 模式结构<br />
&nbsp;</p>
<p>由此可以清楚的看出这样的平行对应关系: Product &lt;====&gt; Creator ; ConreteProduct &lt;====&gt; ConreteCreator</p>
<p>抽象产品对应抽象创建器,具体产品对应具体创建器.这样做的好处是什么呢?为什么我们不直接用具体的产品和具体的创建器完成需求呢?实际上我们也可以这样做.但通过Factory Method模式来完成,客户(client)只需引用抽象的Product和Creater,对具体的ConcreteProduct和ConcreteCreator可以毫不关心,这样做我们可以获得额外的好处:</p>
<p>首先客户端可以统一从抽象创建器获取产生的实例,Creator的作用将client和产品创建过程分离开来,客户不用操心返回的是那一个具体的产品,也不用关心这些产品是如何创建的.同时,ConcreteProduct也被隐藏在Product后面,ConreteProduct继承了Product的所有属性,并实现了Product中定义的抽象方法,按照Java中的对象造型(cast)原则,通过ConcreteCreator产生的ConcreteProduct可以自动的上溯造型成Product.这样一来,实质内容不同的ConcreteProduct就可以在形式上统一为Product,通过Creator提供给client来访问. <br />
其次,当我们添加一个新的ConcreteCreator时,由于Creator所提供的接口不变,客户端程序不会有丝毫的改动,不会带来动一发而牵全身的灾难, 这就是良好封装性的体现.但如果直接用ConcreteProduct和ConcreteCreator两个类是无论如何也做不到这点的. 优良的面向对象设计鼓励使用封装(encapsulation)和委托(delegation),而Factory Method模式就是使用了封装和委托的典型例子,这里封装是通过抽象创建器Creator来体现的,而委托则是通过抽象创建器把创建对象的责任完全交给具体创建器ConcreteCreator来体现的. <br />
现在,请再回头看看基本概念中的那段话,开始也许觉得生涩难懂,现在是不是已经明朗化了很多.</p>
<p>下面让我们看看在 Java 中如何实现Factory Method模式,进一步加深对它的认识.</p>
<p>&nbsp;</p>
<p>具体实施</p>
<p>先说明一点,用Factory Method模式创建对象并不一定会让我们的代码更短,实事上往往更长,我们也使用了更多的类,真正的目的在于这样可以灵活的,有弹性的创建不确定的对象.而且,代码的可重用性提高了,客户端的应用简化了,客户程序的代码会大大减少,变的更具可读性.</p>
<p>标准实现: 这里我采用Bruce Eckel 用来描述OO思想的经典例子 Shape.这样大家会比较熟悉一些.我完全按照图1中所定义的结构写了下面的一段演示代码.这段代码的作用是创建不同的Shape实例,每个实例完成两个操作:draw和erase.具体的创建过程委托ShapeFactory来完成. <br />
1.a 首先定义一个抽象类Shape,定义两个抽象的方法.</p>
<p>abstract class Shape {<br />
&nbsp; // 勾画shape<br />
&nbsp; public abstract void draw();<br />
&nbsp; // 擦去 shape<br />
&nbsp; public abstract void erase();<br />
&nbsp; public String name;<br />
&nbsp; public Shape(String aName){<br />
&nbsp;&nbsp;&nbsp; name = aName;<br />
&nbsp; }<br />
} </p>
<p><br />
1.b 定义 Shape的两个子类: Circle, Square,实现Shape中定义的抽象方法</p>
<p>// 圆形子类<br />
class Circle extends Shape {<br />
&nbsp; public void draw() {<br />
&nbsp;&nbsp;&nbsp; System.out.println("It will draw a circle.");<br />
&nbsp; }<br />
&nbsp; public void erase() {<br />
&nbsp;&nbsp;&nbsp; System.out.println("It will erase a circle."); <br />
&nbsp; }<br />
&nbsp; // 构造函数<br />
&nbsp; public Circle(String aName){<br />
&nbsp;&nbsp;&nbsp; super(aName);<br />
&nbsp; }<br />
}<br />
// 方形子类<br />
class Square extends Shape {<br />
&nbsp; public void draw() { <br />
&nbsp;&nbsp;&nbsp; System.out.println("It will draw a square."); <br />
&nbsp; }<br />
&nbsp; public void erase() { <br />
&nbsp;&nbsp;&nbsp; System.out.println("It will erase a square."); <br />
&nbsp; }<br />
&nbsp; // 构造函数<br />
&nbsp; public Square(String aName){<br />
&nbsp;&nbsp;&nbsp; super(aName);<br />
&nbsp; }<br />
}<br />
&nbsp;</p>
<p><br />
1.c 定义抽象的创建器,anOperation调用factoryMethod创建一个对象,并对该对象进行一系列操作.</p>
<p>abstract class ShapeFactory {&nbsp; <br />
&nbsp; protected abstract Shape factoryMethod(String aName);<br />
&nbsp; // 在anOperation中定义Shape的一系列行为<br />
public void anOperation(String aName){<br />
&nbsp;&nbsp;&nbsp; Shape s = factoryMethod(aName);<br />
&nbsp;&nbsp;&nbsp; System.out.println("The current shape is: " + s.name);<br />
&nbsp;&nbsp;&nbsp; s.draw();<br />
&nbsp;&nbsp;&nbsp; s.erase();<br />
&nbsp; }<br />
} </p>
<p><br />
1.d 定义与circle和square相对应的两个具体创建器CircleFactory,SquareFactory,实现父类的methodFactory方法</p>
<p>// 定义返回 circle 实例的 CircleFactory<br />
class CircleFactory extends ShapeFactory {<br />
&nbsp; // 重载factoryMethod方法,返回Circle对象<br />
&nbsp; protected Shape factoryMethod(String aName) {<br />
&nbsp;&nbsp;&nbsp; return new Circle(aName + " (created by CircleFactory)");<br />
&nbsp; }<br />
}<br />
&nbsp; <br />
// 定义返回 Square 实例的 SquareFactory<br />
class SquareFactory extends ShapeFactory {<br />
&nbsp; // 重载factoryMethod方法,返回Square对象<br />
protected Shape factoryMethod(String aName) {<br />
&nbsp;&nbsp;&nbsp; return new Square(aName + " (created by SquareFactory)");<br />
&nbsp; }<br />
}<br />
&nbsp;</p>
<p><br />
1.e 测试类:请注意这个客户端程序多么简洁,既没有罗嗦的条件判断语句,也无需关心ConcreteProduct和ConcreteCreator的细节(因为这里我用anOperation封装了Product里的两个方法,所以连Product的影子也没看见,当然把Product里方法的具体调用放到客户程序中也是不错的).</p>
<p>class Main {<br />
&nbsp; public static void main(String[] args){<br />
&nbsp;&nbsp;&nbsp; ShapeFactory sf1 = new SquareFactory(); <br />
&nbsp;&nbsp;&nbsp; ShapeFactory sf2 = new CircleFactory();<br />
&nbsp;&nbsp;&nbsp; sf1.anOperation("Shape one");<br />
&nbsp;&nbsp;&nbsp; sf2.anOperation("Shape two");<br />
&nbsp; }<br />
}&nbsp; <br />
&nbsp;</p>
<p><br />
运行结果如下:</p>
<p>The current shape is: Shape one (created by SquareFactory)</p>
<p>It will draw a square.</p>
<p>It will erase a square.</p>
<p>The current shape is: Shape two (created by CircleFactory)</p>
<p>It will draw a circle.</p>
<p>It will erase a circle.</p>
<p>参数化的Factory Method: 这种方式依靠指定的参数作为标志来创建对应的实例,这是很常见的一种办法.比如JFC中的BorderFactory就是个很不错的例子. 以下的这个例子是用字符串作为标记来进行判断的,如果参数的类型也不一样,那就可以用到过载函数来解决这个问题,定义一系列参数和方法体不同的同名函数,这里java.util.Calendar.getInstance()又是个极好的例子.参数化的创建方式克服了Factory Method模式一个最显著的缺陷,就是当具体产品比较多时,我们不得不也建立一系列与之对应的具体构造器. 但是在客户端我们必须指定参数来决定要创建哪一个类. <br />
2.a 我们在第一种方法的基础上进行修改,首先自定义一个的异常,这样当传入不正确的参数时可以得到更明显的报错信息.</p>
<p>class NoThisShape extends Exception {<br />
&nbsp; public NoThisShape(String aName) {<br />
&nbsp;&nbsp;&nbsp; super(aName);<br />
&nbsp; }<br />
}<br />
&nbsp;</p>
<p><br />
2.b去掉了ShapeFactory的两个子类,改为由ShapeFactory直接负责实例的创建. ShapeFactory自己变成一个具体的创建器,直接用参数化的方法实现factoryMethod返回多种对象.</p>
<p>abstract class ShapeFactory {&nbsp; <br />
&nbsp; private static Shape s;<br />
&nbsp; private ShapeFactory() {}<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp; static Shape factoryMethod(String aName, String aType) throws NoThisShape{<br />
&nbsp;&nbsp;&nbsp; if (aType.compareTo("square")==0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Square(aName);<br />
&nbsp;&nbsp;&nbsp; else if (aType.compareTo("circle")==0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return new Circle(aName);<br />
&nbsp;&nbsp;&nbsp; else throw new NoThisShape(aType);&nbsp; <br />
&nbsp; }<br />
&nbsp; <br />
&nbsp; // 在anOperation中定义Shape的一系列行为<br />
&nbsp; static void anOperation(String aName, String aType) throws NoThisShape{<br />
&nbsp;&nbsp;&nbsp; s = factoryMethod(aName, aType);<br />
&nbsp;&nbsp;&nbsp; System.out.println("The current shape is: " + s.name);<br />
&nbsp;&nbsp;&nbsp; s.draw();<br />
&nbsp;&nbsp;&nbsp; s.erase();<br />
&nbsp; }<br />
}<br />
&nbsp;</p>
<p><br />
2.c 测试类:这里客户端必须指定参数来决定具体创建哪个类.这个例子里的anOperation是静态函数,可以直接引用.</p>
<p>class Main {<br />
&nbsp; public static void main(String[] args) throws NoThisShape{<br />
&nbsp;&nbsp;&nbsp; ShapeFactory.anOperation("Shape one","circle");<br />
&nbsp;&nbsp;&nbsp; ShapeFactory.anOperation("Shape two","square");<br />
&nbsp;&nbsp;&nbsp; ShapeFactory.anOperation("Shape three", "delta");<br />
&nbsp; }<br />
}<br />
&nbsp;</p>
<p><br />
运行结果如下:</p>
<p>The current shape is: Shape one<br />
It will draw a circle.<br />
It will erase a circle.<br />
The current shape is: Shape two<br />
It will draw a square.<br />
It will erase a square.<br />
Exception in thread "main" NoThisShape: delta<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at ShapeFactory.factoryMethod(ShapeFactory.java:10)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at ShapeFactory.anOperation(ShapeFactory.java:15)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; at Main.main(Main.java:5)<br />
&nbsp;</p>
<p><br />
动态装载机制: <br />
有的时候我们会把ConcreteProduct的实例传给创建器作为参数,这种情况下,如果在创建器里完成创建过程,就必须判断参数的具体类型(用instanceof),然后才能产生相应的实例,那么比较好的做法是利用Java的动态装载机制来完成这件事.比如:</p>
<p>我们得到一个Shape的子类s,但不知道具体是那个子类,就可以利用Class类自带的方法newInstance()得到实例</p>
<p>return (Shape)s.getClass().newInstance();</p>
<p>这种方法有兴趣得读者可以自己尝试,限于篇幅,不写具体代码出来了.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
&nbsp;回页首 <br />
&nbsp;</p>
<p>&nbsp;</p>
<p>后话:</p>
<p>看完这篇文章后,相信读者对Factory Method模式有一个比较清楚的了解了.我想说的是,我们不仅应该关心一个具体的模式有什么作用,如何去实现这个模式,更应该透过现象看本质,不但知其然,还要知其所以然.要通过对模式的学习加深对面向对象思想的理解,让自己的认识得到升华.Factory Method模式看似简单,实则深刻.抽象,封装,继承,委托,多态,针对接口编程等面向对象中的概念都在这里得到了一一的体现.只有抓住了它的本质,我们才能够不拘于形式的灵活运用,而不是为了使用模式而使用模式.<br />
</font></p>
 <img src ="http://www.blogjava.net/jjshcc/aggbug/331496.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 12:08 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331496.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>代理模式（静态代理和动态代理）</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331488.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 03:47:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331488.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331488.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331488.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331488.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331488.html</trackback:ping><description><![CDATA[<font style="background-color: #cce8cf">
<p><font style="background-color: #cce8cf">一、 Proxy模式定义:<br />
为其他对象提供一种代理以控制这个对象的访问。<br />
二、 模式解说<br />
Proxy代理模式是一种结构型设计模式，主要解决的问题是：在直接访问对象时带来的问题，比如说：要访问的对象在远程的机器上。在面向对象系统中，有些对象由于某些原因（比如对象创建开销很大，或者某些操作需要安全控制，或者需要进程外的访问），直接访问会给使用者或者系统结构带来很多麻烦，我们可以在访问此对象时加上一个对此对象的访问层,这个访问层也叫代理。Proxy模式是最常见的模式，在我们生活中处处可见，例如我们买火车票不一定非要到火车站去买，可以到一些火车票的代售点去买。寄信不一定是自己去寄，可以把信委托给邮局，由邮局把信送到目的地，现实生活中还有很多这样的例子，就不一一列举了。 <br />
三、 结构图<br />
Proxy模式结构图如下:</font><br />
<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/proxy.gif" width="483" height="266" /><br />
&nbsp;四、 一个例子<br />
举一个比较俗的例子，一个男孩boy喜欢上了一个女孩girl，男孩一直想认识女孩，直接去和女孩打招呼吧，又觉得不好意思（这个男孩比较害羞）。于是男孩想出了一个办法，委托女孩的室友Proxy去帮他搞定这件事（获得一些关于女孩的信息，如有没有BF等,这就叫知己知彼，才能百战不殆）。下面给出这个例子的程序实现：</p>
<p>&nbsp;interface GirlInfo{<br />
&nbsp;&nbsp;public void hasBoyFriend();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;class Girl implements GirlInfo{</p>
<p>&nbsp;&nbsp;public void hasBoyFriend(){<br />
&nbsp;&nbsp;&nbsp;System.out.println("还没有男朋友");<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;}<br />
&nbsp;<br />
&nbsp;class Proxy implements GirlInfo{<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;private GirlInfo girl;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;public Proxy(GirlInfo girl){<br />
&nbsp;&nbsp;&nbsp;this.girl=girl;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public void hasBoyFriend(){<br />
&nbsp;&nbsp;&nbsp;this.girl.hasBoyFriend();<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;}<br />
&nbsp;<br />
&nbsp;public class ProxyClient {</p>
<p>&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;GirlInfo girl=new Girl();<br />
&nbsp;&nbsp;Proxy proxy=new Proxy(girl);<br />
&nbsp;&nbsp;proxy.hasBoyFriend();<br />
&nbsp;}</p>
<p>&nbsp;}<br />
&nbsp;从这个例子我们可以看出，Proxy模式是不是和Adapter模式差不多，都是调用一个已有对象的方法来完成功能。但是他们之间还是有区别的，那就是Proxy模式的目标类必须要实现某个接口，代理类没有必要实现该接口，模式是死的，它的实现是活的，如果一味的相信某些书上的实现，学习模式也就失去了意义。有的书上称这种实现为静态代理，之所以这样是为了区别于Proxy模式在jdk中的另一种实现,jdk中的实现称为动态代理。下面用jdk中的方法给出这个例子的实现。代码如下:</p>
<p>import java.lang.reflect.InvocationHandler;<br />
import java.lang.reflect.Method;<br />
import java.lang.reflect.Proxy;</p>
<p>&nbsp;interface GirlInfo{<br />
&nbsp;&nbsp;public void hasBoyFriend();<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;class Girl implements GirlInfo{</p>
<p>&nbsp;&nbsp;public void hasBoyFriend(){<br />
&nbsp;&nbsp;&nbsp;System.out.println("还没有男朋友");<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;}<br />
&nbsp;<br />
&nbsp;class GirlProxy implements InvocationHandler{<br />
&nbsp;&nbsp;private Object delegate;<br />
&nbsp;&nbsp;public Object bind(Object delegate){<br />
&nbsp;&nbsp;&nbsp;this.delegate=delegate;<br />
&nbsp;&nbsp;&nbsp;return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(),this);<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {</p>
<p>&nbsp;&nbsp;&nbsp;method.invoke(delegate, args);<br />
&nbsp;&nbsp;&nbsp;return null;<br />
&nbsp;&nbsp;}<br />
&nbsp; <br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public class ProxyClient {</p>
<p>&nbsp;&nbsp;public static void main(String[] args) {<br />
&nbsp;&nbsp;&nbsp;GirlProxy girlProxy=new GirlProxy();<br />
&nbsp;&nbsp;&nbsp;GirlInfo girl=(GirlInfo)girlProxy.bind(new Girl());<br />
&nbsp;&nbsp;&nbsp;girl.hasBoyFriend();<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;}</p>
<p>五、 适用性<br />
1） 假如有一个外部组件包，不允许实现其接口，则就只能使用其动态代理了。<br />
2） 直接访问一个对象很困难，或者说不能访问，此时只能是找个代理去访问，然后把结果反馈给自己。<br />
六、 优缺点<br />
1) 优点: 向客户端隐藏了访问某个对象的细节及复杂性；可以动态地调用一个对象中的方法，且无需实现固定的接口。<br />
2) 缺点：暂时没发现</p>
<p><br />
&nbsp;</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331488.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 11:47 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331488.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>抽象工厂模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331487.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 03:34:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331487.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331487.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331487.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331487.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331487.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">抽象工厂模式（Abstract Factory）：为创建一组相关或者互相依赖的对象提供一个接口，而无需指定它们对应的具体类。<br />
通用类图如下： <br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/174906629.jpg" width="566" height="404" /></div>
<br />
例如，我们现在有两种产品A和B，而产品A和B分别都有两个厂商1和2进行生产，在这里我们把不同的厂商1、厂商2理解为牌子1和牌子2，那么厂商1就生产A1、B1，厂商2生产A2、B2。<br />
此时，不同的厂商肯定要生产自己的产品（如A1、B1），每个厂商都有自己的一系列产品，这就与上面抽象工厂模式的描述类似了。<br />
该例子的类图如下： <br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/174928984.jpg" width="657" height="490" /></div>
<br />
</font></p>
<p><font style="background-color: #cce8cf">具体代码实现如下：<br />
//定义不同的产品之间的一定具备的标准，用interface实现 <br />
//其中的method()方法可看作提取出不同产品的共性，如手机都有类似的功能 <br />
interface IProductA{ <br />
&nbsp; public void method(); <br />
} </font></p>
<p><font style="background-color: #cce8cf">interface IProductB{ <br />
&nbsp; public void method(); <br />
} </font></p>
<p><font style="background-color: #cce8cf">//实现了产品标准实现的一系列具体产品 <br />
//由于已经设计好A1由厂商1生产，故以下输出代码有&#8220;厂商x&#8221; <br />
class ProductA1 implements IProductA{ <br />
&nbsp; public void method() { <br />
&nbsp;&nbsp;&nbsp; System.out.println("厂商1&nbsp;&nbsp;&nbsp; 生产ProductA1 ..."); <br />
&nbsp; } <br />
} </font></p>
<p><font style="background-color: #cce8cf">class ProductA2 implements IProductA{ <br />
&nbsp; public void method() { <br />
&nbsp;&nbsp;&nbsp; System.out.println("厂商2&nbsp;&nbsp;&nbsp; 生产ProductA2 ..."); <br />
&nbsp; } <br />
} </font></p>
<p><font style="background-color: #cce8cf">class ProductB1 implements IProductB{ <br />
&nbsp; public void method() { <br />
&nbsp;&nbsp;&nbsp; System.out.println("厂商1&nbsp;&nbsp;&nbsp; 生产ProductB1 ..."); <br />
&nbsp; } <br />
} </font></p>
<p><font style="background-color: #cce8cf">class ProductB2 implements IProductB{ <br />
&nbsp; public void method() { <br />
&nbsp;&nbsp;&nbsp; System.out.println("厂商2&nbsp;&nbsp;&nbsp; 生产ProductB2 ..."); <br />
&nbsp; } <br />
} </font></p>
<p><font style="background-color: #cce8cf">//每一种牌子的产品生产工厂，即不同的厂商负责自己牌子产品的生产 <br />
abstract class Factory1{ <br />
&nbsp; abstract IProductA getProductA1(); <br />
&nbsp; abstract IProductB getProductB1(); <br />
} </font></p>
<p><font style="background-color: #cce8cf">abstract class Factory2{ <br />
&nbsp; abstract IProductA getProductA2(); <br />
&nbsp; abstract IProductB getProductB2(); <br />
} </font></p>
<p><font style="background-color: #cce8cf">//具体的工厂用来生产相关的产品 <br />
class ConcreteFactory1 extends Factory1{ <br />
&nbsp; public IProductA getProductA1() { <br />
&nbsp;&nbsp;&nbsp; return new ProductA1(); <br />
&nbsp; } <br />
&nbsp; public IProductB getProductB1() { <br />
&nbsp;&nbsp;&nbsp; return new ProductB1(); <br />
&nbsp; } <br />
} </font></p>
<p><font style="background-color: #cce8cf">class ConcreteFactoryB extends Factory2{ <br />
&nbsp; public IProductA getProductA2() { <br />
&nbsp;&nbsp;&nbsp; return new ProductA2(); <br />
&nbsp; } <br />
&nbsp; public IProductB getProductB2() { <br />
&nbsp;&nbsp;&nbsp; return new ProductB2(); <br />
&nbsp; } <br />
} </font></p>
<p><font style="background-color: #cce8cf">//测试类 <br />
public class Client { <br />
&nbsp; public static void main(String[] args) { <br />
&nbsp;&nbsp;&nbsp; //厂商1负责生产产品A1、B1 <br />
&nbsp;&nbsp;&nbsp; Factory1 factory1 = new ConcreteFactory1(); <br />
&nbsp;&nbsp;&nbsp; IProductA productA1 = factory1.getProductA1(); <br />
&nbsp;&nbsp;&nbsp; IProductB productB1 = factory1.getProductB1(); <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; productA1.method(); <br />
&nbsp;&nbsp;&nbsp; productB1.method(); <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; //厂商2负责生产产品A2、B2 <br />
&nbsp;&nbsp;&nbsp; Factory2 factory2 = new ConcreteFactoryB(); <br />
&nbsp;&nbsp;&nbsp; IProductA productA2 = factory2.getProductA2(); <br />
&nbsp;&nbsp;&nbsp; IProductB productB2 = factory2.getProductB2(); <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; productA2.method(); <br />
&nbsp;&nbsp;&nbsp; productB2.method(); <br />
&nbsp; } <br />
}<br />
运行结果：<br />
厂商1&nbsp; 生产ProductA1 ...<br />
厂商1&nbsp; 生产ProductB1 ...<br />
厂商2&nbsp; 生产ProductA2 ...<br />
厂商2&nbsp; 生产ProductB2 ... </font></p>
<p><font style="background-color: #cce8cf">&nbsp;<br />
其实，上例中本来可以不用到了两个抽象工厂，只剩一个也可，但是这样子与我们现实生活中不同厂商各自生产自己的产品有点不同，所以就将其分开为两个了，也就是将两个厂商完全地分离开。<br />
由上面类图可以知道，一旦任何一个厂商开发出了产品C的话，那么这个厂商肯定需要扩展自己的工厂来投入到C产品的生产中，那么此时工厂1和工厂2就需要进行一定的改变了，这很明显不符合开闭原则。</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331487.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 11:34 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331487.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>外观模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331484.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 03:22:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331484.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331484.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331484.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331484.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331484.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">Facade模式是这样描述的: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为子系统中的一组接口提供一个统一接口。Facade模式定义了一个更高层的接口，使子系统更加容易使用。</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大致意思是说：使用一种比原有方式更简单的办法与系统交互。例如，我们拿一个文件，这个文件放在了第二抽屉里，而第二个抽屉的钥匙放在了第一个抽屉里，我们要想取出这个文件，第一步肯定要拿到第一个抽屉的钥匙，然后打开它再拿出第二个抽屉的钥匙，最后打开第二个抽屉取出文件。<br />
&nbsp;我就上面说的那个情形写一下实现代码</font></p>
<p><font style="background-color: #cce8cf">class DrawerOne {</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void open(){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("第一个抽屉被打开了");</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getKey();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void getKey(){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("得到第二个抽屉的钥匙");</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf">class DrawerTwo{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void open(){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("第二个抽屉被打开了");</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getFile();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void getFile(){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("得到这个重要文件");</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf">public class Client{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public static void main(String []args){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawerOne darwerOne=new DrawerOne();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawerTwo darwerTwo=new DrawerTwo();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; darwerOne.open();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; darwerTwo.open();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf">由于没有使用Fa?ade模式，可以看到要想得到这个文件要首先打开第一个抽屉，然后再打开第二个抽屉，在我们实际所开发的系统中，有时候客户要实现某一操作，并不需要知道实现这一操作的详细步骤，而是简单地点击某一个按钮就可以得到自己想要的结果。下面对上面的代码使用Fa?ade模式进行改进，建立一个FacadeDrawer类：</font></p>
<p><font style="background-color: #cce8cf">class DrawerFacade{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; DrawerOne darwerOne=new DrawerOne();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; DrawerTwo darwerTwo=new DrawerTwo();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public void open(){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; darwerOne.open();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; darwerTwo.open();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf">修改Client类：</font></p>
<p><font style="background-color: #cce8cf">public class DrawerClient{</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public static void main(String []args){</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DrawerFacade drawer=new DrawerFacade();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; drawer.open();</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}</font></p>
<p><font style="background-color: #cce8cf">输出结果如下：</font></p>
<p><font style="background-color: #cce8cf">第一个抽屉被打开了</font></p>
<p><font style="background-color: #cce8cf">得到第二个抽屉的钥匙</font></p>
<p><font style="background-color: #cce8cf">第二个抽屉被打开了</font></p>
<p><font style="background-color: #cce8cf">得到这个重要文件</font></p>
<p><font style="background-color: #cce8cf">正如上面所说，客户端client，它并不需要关心子系统，而是关心DrawerFacade所留下来的和外部交互的接口，而子系统在DrawerFacade的聚合。</font></p>
<p><font style="background-color: #cce8cf">以上只是个人拙见，哪里有不正确的地方，希望大家多多批评指正。^_^</font></p>
<p><font style="background-color: #cce8cf">Facade模式主要适用于以下几种情况:</font></p>
<p><font style="background-color: #cce8cf">1)不需要使用一个复杂系统的所有功能，而且可以创建一个新的类，包含访问系统的所有规则。如果只需要使用系统的部分功能，那么你为新类所创建的API将比原系统的API简单的多。</font></p>
<p><font style="background-color: #cce8cf">2)希望封装或者隐藏系统原系统。</font></p>
<p><font style="background-color: #cce8cf">3)希望使用原系统的功能，而且还希望增加一些新的功能。</font></p>
<p><font style="background-color: #cce8cf">4) 编写新类的成本小于所有人学会使用或者未来维护原系统上所需的成本。</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331484.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 11:22 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331484.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>享元模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331481.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 03:13:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331481.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331481.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331481.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331481.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331481.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">一、FlyWeight模式定义:</font></p>
<p><font style="background-color: #cce8cf">运用共享技术有效地支持大量细粒度对象。</font></p>
<p><font style="background-color: #cce8cf">二、模式解说</font></p>
<p><font style="background-color: #cce8cf">也就是说在一个系统中如果有多个相同的对象，那么只共享一份就可以了，不必每个都去实例化一个对象。在Flyweight模式中，由于要产生各种各样的对象，所以在Flyweight(享元)模式中常出现Factory模式。Flyweight的内部状态是用来共享的,Flyweight factory负责维护一个对象存储池（Flyweight Pool）来存放内部状态的对象。Flyweight模式是一个提高程序效率和性能的模式,会大大加快程序的运行速度。</font></p>
<p><font style="background-color: #cce8cf">三、结构图</font></p>
<p><font style="background-color: #cce8cf">&nbsp;<img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/flyweight.jpg" width="781" height="384" /></font></p>
<p><font style="background-color: #cce8cf">享元模式所涉及的角色有抽象享元角色、具体（单纯）享元角色、复合享元角色、享员工厂角色，以及客户端角色等。</font></p>
<p><font style="background-color: #cce8cf">抽象享元角色（Flyweight）：此角色是所有的具体享元类的超类，为这些类规定出需要实现的公共接口或抽象类。那些需要外蕴状态(External State)的操作可以通过方法的参数传入。抽象享元的接口使得享元变得可能，但是并不强制子类实行共享，因此并非所有的享元对象都是可以共享的。</font></p>
<p><font style="background-color: #cce8cf">具体享元(ConcreteFlyweight)角色：实现抽象享元角色所规定的接口。如果有内蕴状态的话，必须负责为内蕴状态提供存储空间。享元对象的内蕴状态必须与对象所处的周围环境无关，从而使得享元对象可以在系统内共享。有时候具体享元角色又叫做单纯具体享元角色，因为复合享元角色是由单纯具体享元角色通过复合而成的。</font></p>
<p><font style="background-color: #cce8cf">复合享元(UnsharableFlyweight)角色：复合享元角色所代表的对象是不可以共享的，但是一个复合享元对象可以分解成为多个本身是单纯享元对象的组合。复合享元角色又称做不可共享的享元对象。这个角色一般很少使用。</font></p>
<p><font style="background-color: #cce8cf">享元工厂(FlyweightFactoiy)角色：本角色负责创建和管理享元角色。本角色必须保证享元对象可以被系统适当地共享。当一个客户端对象请求一个享元对象的时候，享元工厂角色需要检查系统中是否已经有一个符合要求的享元对象，如果已经有了，享元工厂角色就应当提供这个已有的享元对象；如果系统中没有一个适当的享元对象的话，享元工厂角色就应当创建一个新的合适的享元对象。</font></p>
<p><font style="background-color: #cce8cf">客户端(Client)角色：本角色还需要自行存储所有享元对象的外蕴状态。</font></p>
<p><font style="background-color: #cce8cf">四、一个例子</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<p><font style="background-color: #cce8cf">import java.util.Hashtable;</font></p>
<font style="background-color: #cce8cf">
<p><br />
/** <br />
&nbsp;*<br />
&nbsp;* @author &lt;a href="mailto:flustar2008@163.com"&gt;flustar&lt;/a&gt;<br />
&nbsp;* @version 1.0 <br />
&nbsp;* Creation date: Jan 25, 2008 1:33:49 PM<br />
&nbsp;*/</p>
<p>&nbsp; // "Flyweight"</p>
<p>&nbsp; abstract class Character<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; protected char symbol;<br />
&nbsp;&nbsp;&nbsp; protected int width;<br />
&nbsp;&nbsp;&nbsp; protected int height;<br />
&nbsp;&nbsp;&nbsp; protected int ascent;<br />
&nbsp;&nbsp;&nbsp; protected int descent;<br />
&nbsp;&nbsp;&nbsp; protected int pointSize;</p>
<p>&nbsp;&nbsp;&nbsp; public abstract void Display(int pointSize);<br />
&nbsp; }</p>
<p>&nbsp; // "ConcreteFlyweight"</p>
<p>&nbsp; class CharacterA extends Character<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; // Constructor<br />
&nbsp;&nbsp;&nbsp; public CharacterA()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.symbol = 'A';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.height = 100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.width = 120;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ascent = 70;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.descent = 0;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public&nbsp; void Display(int pointSize)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pointSize = pointSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(this.symbol +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " (pointsize " + this.pointSize + ")");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }</p>
<p>&nbsp; // "ConcreteFlyweight"</p>
<p>&nbsp; class CharacterB extends Character<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; // Constructor<br />
&nbsp;&nbsp;&nbsp; public CharacterB()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.symbol = 'B';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.height = 100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.width = 140;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ascent = 72;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.descent = 0;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public&nbsp; void Display(int pointSize)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pointSize = pointSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(this.symbol +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " (pointsize " + this.pointSize + ")");<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp; }</p>
<p>&nbsp; //&nbsp; C, D, E, etc.</p>
<p>&nbsp; // "ConcreteFlyweight"</p>
<p>&nbsp; class CharacterZ extends Character<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; // Constructor<br />
&nbsp;&nbsp;&nbsp; public CharacterZ()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.symbol = 'Z';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.height = 100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.width = 100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ascent = 68;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.descent = 0;<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public&nbsp; void Display(int pointSize)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pointSize = pointSize;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(this.symbol +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " (pointsize " + this.pointSize + ")");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
&nbsp; // "FlyweightFactory"</p>
<p>&nbsp; class CharacterFactory<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; private Hashtable characters = new Hashtable();</p>
<p>&nbsp;&nbsp;&nbsp; public Character GetCharacter(char key)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Uses "lazy initialization"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Character character = (Character)characters.get(key);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (character == null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (key)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'A': character = new CharacterA(); break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'B': character = new CharacterB(); break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 'Z': character = new CharacterZ(); break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; characters.put(key, character);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return character;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }<br />
// test application<br />
&nbsp; public class Test<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; public static void main(String []args)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Build a document with text<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String document = "AAZZBBZB";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char[] chars = document.toCharArray();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CharacterFactory f = new CharacterFactory();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // extrinsic state<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int pointSize = 10;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // For each character use a flyweight object<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(char c : chars)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pointSize++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Character character = f.GetCharacter(c);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; character.Display(pointSize);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }</p>
<p>&nbsp;</p>
<p>五、 适用性</p>
<p>Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下情况都成立时使用Flyweight模式。</p>
<p>1）一个应用程序使用了大量的对象。</p>
<p>2）完全由于使用大量的对象，造成很大的存储开销。</p>
<p>3）对象的大多数状态都可变为外部状态。</p>
<p>4）如果删除对象的外部状态，那么可以用相对较少的共享对象取代很多组对象。</p>
<p>5）应用程序不依赖对象标识。</p>
<p>六、优缺点</p>
<p>1）享元模式使得系统更加复杂。为了使对象可以共享，需要将一些状态外部化，这使得程序的逻辑复杂化。 </p>
<p>2）享元模式将享元对象的状态外部化，而读取外部状态使得运行时间稍微变长。<br />
</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331481.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 11:13 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331481.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>组合模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331478.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 02:59:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331478.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331478.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331478.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331478.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331478.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>设计模式之Composite(组合)</p>
<p>Composite定义:<br />
将对象以树形结构组织起来,以达成&#8220;部分－整体&#8221; 的层次结构，使得客户端对单个对象和组合对象的使用具有一致性.</p>
<p>Composite比较容易理解，想到Composite就应该想到树形结构图。组合体内这些对象都有共同接口,当组合体一个对象的方法被调用执行时，Composite将遍历(Iterator)整个树形结构,寻找同样包含这个方法的对象并实现调用执行。可以用牵一动百来形容。</p>
<p>所以Composite模式使用到Iterator模式，和Chain of Responsibility模式类似。</p>
<p>Composite好处:<br />
1.使客户端调用简单，客户端可以一致的使用组合结构或其中单个对象，用户就不必关系自己处理的是单个对象还是整个组合结构，这就简化了客户端代码。<br />
2.更容易在组合体内加入对象部件. 客户端不必因为加入了新的对象部件而更改代码。</p>
<p>如何使用Composite?<br />
首先定义一个接口或抽象类，这是设计模式通用方式了，其他设计模式对接口内部定义限制不多，Composite却有个规定，那就是要在接口内部定义一个用于访问和管理Composite组合体的对象们（或称部件Component）.</p>
<p>下面的代码是以抽象类定义，一般尽量用接口interface,</p>
<p>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 />
} </p>
<p><br />
抽象类Equipment就是Component定义，代表着组合体类的对象们,Equipment中定义几个共同的方法。</p>
<p>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 />
}</p>
<p><br />
Disk是组合体内的一个对象，或称一个部件，这个部件是个单独元素(Primitive)。<br />
还有一种可能是，一个部件也是一个组合体，就是说这个部件下面还有'儿子'，这是树形结构中通常的情况，应该比较容易理解。现在我们先要定义这个组合体：</p>
<p>abstract class CompositeEquipment extends Equipment<br />
{<br />
　　private int i=0; <br />
　　//定义一个Vector 用来存放'儿子'<br />
　　private Lsit equipment=new ArrayList();</p>
<p>　　public CompositeEquipment(String name) { super(name); }</p>
<p>　　public boolean add(Equipment equipment) { <br />
　　　　 this.equipment.add(equipment); <br />
　　　　 return true; <br />
　　 }</p>
<p>　　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 />
　　}</p>
<p>　　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 />
　　</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 />
　　</p>
<p>}</p>
<p><br />
上面CompositeEquipment继承了Equipment,同时为自己里面的对象们提供了外部访问的方法,重载了Iterator,Iterator是Java的Collection的一个接口，是Iterator模式的实现.</p>
<p>我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子Cabinet，箱子里面可以放很多东西，如底板，电源盒，硬盘盒等；盘盒里面可以放一些小设备，如硬盘 软驱等。无疑这两个都是属于组合体性质的。</p>
<p>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>
<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>
<p><br />
至此我们完成了整个Composite模式的架构。</p>
<p>我们可以看看客户端调用Composote代码:</p>
<p>Cabinet cabinet=new Cabinet("Tower");</p>
<p>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"));</p>
<p>//调用 netPrice()方法;<br />
System.out.println("netPrice="+cabinet.netPrice());<br />
System.out.println("discountPrice="+cabinet.discountPrice());</p>
<p>上面调用的方法netPrice()或discountPrice()，实际上Composite使用Iterator遍历了整个树形结构,寻找同样包含这个方法的对象并实现调用执行.</p>
<p>Composite是个很巧妙体现智慧的模式，在实际应用中，如果碰到树形结构，我们就可以尝试是否可以使用这个模式。</p>
<p>以论坛为例，一个版(forum)中有很多帖子(message),这些帖子有原始贴，有对原始贴的回应贴，是个典型的树形结构，那么当然可以使用Composite模式，那么我们进入Jive中看看，是如何实现的.</p>
<p>Jive解剖<br />
在Jive中 ForumThread是ForumMessages的容器container(组合体).也就是说，ForumThread类似我们上例中的 CompositeEquipment.它和messages的关系如图：<br />
[thread]<br />
　　 |- [message]<br />
　　 |- [message]<br />
　　 　　 |- [message]<br />
　　 　　 |- [message]<br />
　　 　　 　　 |- [message] </p>
<p>我们在ForumThread看到如下代码：</p>
<p>public interface ForumThread {<br />
　　 .... <br />
　　 public void addMessage(ForumMessage parentMessage, ForumMessage newMessage)<br />
　　 　　 　　 throws UnauthorizedException; </p>
<p>　　 public void deleteMessage(ForumMessage message)<br />
　　 　　 　　 throws UnauthorizedException;</p>
<p>　　<br />
　　 public Iterator messages();<br />
　　 　　 .... </p>
<p>}<br />
类似CompositeEquipment, 提供用于访问自己组合体内的部件方法: 增加 删除 遍历.</p>
<p>三. 测试程序与源程序的组织结构，&#8220;分离但等同&#8221;原则<br />
四. junit.jar加入到classpath中，可以被javac任务找到，但不能java任务识别。</p>
<p>junit与ant构建工具的集成</p>
<p>如果junit任务下面没有设置&lt;formatter&gt;子元素，那将无法打印出详细的信息。<br />
一个junit任务下可以有多个&lt;formatter&gt;子元素,&lt;formatter&gt;的usefile属性决定是否生成文件。<br />
junitreport任务首先把多个test-....xml文件合并成一个汇总的xml文件，其todir属性指定该文件的存储目录.其report子元素用于指定生成的html文件的目录。在用junitreport之前，要小心junit的haltonfaiure。</p>
<p>batchtest指定的java源文件或class文件，而不是要运行的测试类名称，junit从这些文件中找出要运行的测试类名。</p>
<p>五. junit与ant构建工具的集成的例子,<br />
&lt;project name="junitlesson" default="run"&gt;</p>
<p>&lt;property name="src.java.dir" value="src/java"/&gt;&lt;!--被测试的java源文件的路径--&gt;<br />
&lt;property name="src.test.dir" value="src/test"/&gt;&lt;!--测试的java源文件的路径--&gt;</p>
<p>&lt;property name="classes.java.dir" value="classes/java"/&gt;&lt;!--被测试的class文件的路径--&gt;<br />
&lt;property name="classes.test.dir" value="classes/test"/&gt;&lt;!--测试的class文件的路径--&gt;</p>
<p>&lt;target name="init"&gt;<br />
&nbsp;&nbsp; &lt;mkdir dir="${classes.java.dir}"/&gt;<br />
&nbsp;&nbsp; &lt;mkdir dir="${classes.test.dir}"/&gt;<br />
&lt;/target&gt;</p>
<p>&lt;target name="compileJava" depends="init"&gt;<br />
&nbsp;&nbsp; &lt;javac srcdir="${src.java.dir}/cn/itcast" destdir="${classes.java.dir}"/&gt;<br />
&lt;/target&gt;</p>
<p>&lt;target name="compileTest" depends="init"&gt;<br />
&nbsp;&nbsp; &lt;javac srcdir="${src.test.dir}/cn/itcast" destdir="${classes.test.dir}"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;classpath&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;pathelement path="."/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;pathelement path="${classes.java.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/classpath&gt;<br />
&nbsp;&nbsp; &lt;/javac&gt;<br />
&lt;/target&gt;</p>
<p>&lt;target name="compile" depends="compileJava,compileTest"/&gt;</p>
<p>&lt;target name="run" depends="compile"&gt;<br />
&nbsp;&nbsp; &lt;mkdir dir="testResult"/&gt;<br />
&nbsp;&nbsp; &lt;junit fork="true" printsummary="on"&gt;&lt;!-- haltonfailure="true"--&gt;&lt;!--注意:这句一加上去的话如果程序里面出错了后面的junitreport就不执行了--&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;classpath&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;pathelement path="${classes.test.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;pathelement path="${classes.java.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/classpath&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;test name="cn.itcast.TestCalculator" todir=".\testResult" outfile="result"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;formatter type="xml" /&gt;<br />
&nbsp;&nbsp; &lt;/junit&gt;<br />
&nbsp; <br />
&nbsp;&nbsp; &lt;junitreport todir=".\testResult"&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;fileset dir=".\testResult"&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;include name="result.xml"/&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/fileset&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;report format="frames" todir=".\testResult"/&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/junitreport&gt;&nbsp; <br />
&lt;/target&gt;</p>
<p>&lt;/project&gt;<br />
&lt;!--正确执行的话打开src所在的目录就会看到一个新建的testResult目录,里面已经生成了一大堆测试报告的网页 :) --&gt; </p>
<p>&nbsp;</p>
 <img src ="http://www.blogjava.net/jjshcc/aggbug/331478.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 10:59 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331478.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>观察者模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331468.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331468.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331468.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331468.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331468.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331468.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">一、要完成的任务</font></p>
<p><font style="background-color: #cce8cf">此系统中的三个部分是气象站（获取实际气象数据的物理装置）、WeatherData对象（追踪来自气象站的数据，并更新布告板）和布告板（显示目前天气状况给用户看）。</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-observer-1.jpg" width="600" height="360" /></div>
<font style="background-color: #cce8cf"><br />
二、Observer模式</font></p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<p><font style="background-color: #cce8cf">1、定义观察者模式</font></p>
<p><font style="background-color: #cce8cf">观察者模式定义了对象之间的一对多依赖，这样一来，当一个对象改变状态时，它的所有依赖者都会收到通知并自动更新。</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/DesignPattern-observer-2.gif" width="421" height="344" /></div>
</p>
<p><font style="background-color: #cce8cf">&nbsp; <br />
2.设计气象站</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-observer-3.gif" width="599" height="312" /></div>
<font style="background-color: #cce8cf"><br />
&nbsp; <br />
三、代码实现</p>
<p>&nbsp;</p>
<p>1．定义接口</p>
<p>&nbsp;</p>
<p>（1）Subject接口</p>
<p>Subject.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>public interface Subject {<br />
&nbsp;&nbsp;&nbsp; public void registerObserver(Observer o);<br />
&nbsp;&nbsp;&nbsp; public void removeObserver(Observer o);<br />
&nbsp;&nbsp;&nbsp; public void notifyObservers();<br />
}</p>
<p>&nbsp; <br />
（2）Observer接口</p>
<p>Observer.java<br />
package com.leanhuadeng.DesignPattern.Observer;</p>
<p>public interface Observer {<br />
&nbsp;&nbsp;&nbsp; public void update(float temp,float humidity,float pressure);<br />
}<br />
&nbsp; <br />
（3）Displayment接口</p>
<p>Displayment.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>public interface Displayment {<br />
&nbsp;&nbsp;&nbsp; public void display();<br />
}</p>
<p>&nbsp;</p>
<p>&nbsp; </p>
<p>2．实现接口</p>
<p>&nbsp;</p>
<p>（1）WeatherData</p>
<p>WeatherData.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>import java.util.ArrayList;</p>
<p>public class WeatherData implements Subject {<br />
&nbsp;&nbsp;&nbsp; private ArrayList observers;<br />
&nbsp;&nbsp;&nbsp; private float temperature;<br />
&nbsp;&nbsp;&nbsp; private float humidity;<br />
&nbsp;&nbsp;&nbsp; private float pressure;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public WeatherData(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; observers=new ArrayList();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void notifyObservers() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;observers.size();i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Observer observer=(Observer)observers.get(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; observer.update(temperature, humidity, pressure);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void registerObserver(Observer o) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; observers.add(o);<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void removeObserver(Observer o) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i=observers.indexOf(o);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(i&gt;=0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; observers.remove(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void measurementsChanged(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; notifyObservers();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public void setMeasurements(float temperature,float humidity,float pressure){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.temperature=temperature;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.humidity=humidity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.pressure=pressure;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; measurementsChanged();<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>&nbsp; <br />
（2）CurrentConditionsDisplay</p>
<p>CurrentConditionsDisplay.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>public class CurrentConditionsDisplay implements Observer, Displayment {<br />
&nbsp;&nbsp;&nbsp; private float temperature;<br />
&nbsp;&nbsp;&nbsp; private float humidity;<br />
&nbsp;&nbsp;&nbsp; private Subject weatherData;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public CurrentConditionsDisplay(Subject weatherData){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.weatherData=weatherData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weatherData.registerObserver(this);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void update(float temp, float humidity, float pressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.temperature=temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.humidity=humidity;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; display();<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Current conditions:"+temperature+"F degrees and "+humidity+"% humidity");<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p>&nbsp; <br />
（3）StatisticsDisplay</p>
<p>StatisticsDisplay.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>import java.util.*;</p>
<p>public class StatisticsDisplay implements Observer, Displayment {<br />
&nbsp;&nbsp;&nbsp; private float maxTemp = 0.0f;<br />
&nbsp;&nbsp;&nbsp; private float minTemp = 200;<br />
&nbsp;&nbsp;&nbsp; private float tempSum= 0.0f;<br />
&nbsp;&nbsp;&nbsp; private int numReadings;<br />
&nbsp;&nbsp;&nbsp; private WeatherData weatherData;</p>
<p>&nbsp;&nbsp;&nbsp; public StatisticsDisplay(WeatherData weatherData) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.weatherData = weatherData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weatherData.registerObserver(this);<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void update(float temp, float humidity, float pressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempSum += temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; numReadings++;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp &gt; maxTemp) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxTemp = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (temp &lt; minTemp) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; minTemp = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; display();<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)+ "/" + maxTemp + "/" + minTemp);<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>&nbsp; <br />
（4）ForecastDisplay</p>
<p>ForecastDisplay.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>import java.util.*;</p>
<p>public class ForecastDisplay implements Observer, Displayment {<br />
&nbsp;&nbsp;&nbsp; private float currentPressure = 29.92f;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private float lastPressure;<br />
&nbsp;&nbsp;&nbsp; private WeatherData weatherData;</p>
<p>&nbsp;&nbsp;&nbsp; public ForecastDisplay(WeatherData weatherData) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.weatherData = weatherData;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weatherData.registerObserver(this);<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void update(float temp, float humidity, float pressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastPressure = currentPressure;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currentPressure = pressure;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; display();<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void display() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.print("Forecast: ");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (currentPressure &gt; lastPressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Improving weather on the way!");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (currentPressure == lastPressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("More of the same");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (currentPressure &lt; lastPressure) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Watch out for cooler, rainy weather");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>&nbsp; <br />
3．实现气象站</p>
<p>WeatherStation.java</p>
<p>package com.leanhuadeng.DesignPattern.Observer;</p>
<p>public class WeatherStation {<br />
&nbsp;&nbsp;&nbsp; public static void main(String[] args){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WeatherData weatherData=new WeatherData();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weatherData.setMeasurements(80, 65, 30.4f);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weatherData.setMeasurements(82, 70, 29.2f);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; weatherData.setMeasurements(78, 90, 29.2f);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 10:08 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>装饰者模式</title><link>http://www.blogjava.net/jjshcc/archive/2010/09/09/331457.html</link><dc:creator>Eric_jiang</dc:creator><author>Eric_jiang</author><pubDate>Thu, 09 Sep 2010 01:32:00 GMT</pubDate><guid>http://www.blogjava.net/jjshcc/archive/2010/09/09/331457.html</guid><wfw:comment>http://www.blogjava.net/jjshcc/comments/331457.html</wfw:comment><comments>http://www.blogjava.net/jjshcc/archive/2010/09/09/331457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jjshcc/comments/commentRss/331457.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jjshcc/services/trackbacks/331457.html</trackback:ping><description><![CDATA[<p><strong><span style="font-family: 宋体; color: black; font-size: 12pt">一、要完成的任务</span></strong></p>
<p style="text-indent: 21pt"><span style="font-family: 宋体; color: black">星巴兹（</span><span style="font-family: Arial; color: black">Starbuzz</span><span style="font-family: 宋体; color: black">）是以扩张速度最快而闻名的咖啡连锁店。如果你在街角看到它的店，在对面街上肯定还会看到另一家。因为扩张速度实在太快了，他们准备更新订单系统，以合乎他们的饮料供应要求。他们原先的类设计是这样的&#8230;&#8230;</span></p>
&nbsp;
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-Decorator-1-mission.gif" width="800" height="532" /></div>
<p style="text-indent: 21pt" class="MsoNormal"><span style="font-family: 宋体; color: black">购买咖啡时，也可以要求在其中加入各种调料，例如：蒸奶（</span><span style="font-family: Arial; color: black">Steamed Milk</span><span style="font-family: 宋体; color: black">）、豆浆（</span><span style="font-family: Arial; color: black">Soy</span><span style="font-family: 宋体; color: black">）、摩卡（</span><span style="font-family: Arial; color: black">Mocha</span><span style="font-family: 宋体; color: black">，也就是巧克力风味）或覆盖奶泡。星巴兹会根据所加入的调料收取不同的费用。所以订单系统必须考虑到这些调料部分。</span></p>
&nbsp;&nbsp;<font style="background-color: #cce8cf">二、Decorator模式</font>
<p><font style="background-color: #cce8cf">1、一个原则</font></p>
<p><font style="background-color: #cce8cf">类应该对扩展开放，对修改关闭</font></p>
<p><font style="background-color: #cce8cf">2、定义装饰者模式</font></p>
<p><font style="background-color: #cce8cf">装饰者模式动态地将责任附加到对象上。若要扩展功能，装饰者提供了比继承更有弹性的替代方案。<br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-Decorator-2-define.gif" width="549" height="382" /></div>
<font style="background-color: #cce8cf">3.分析任务</font><br />
</font>
<p>
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-Decorator-3-analys.gif" width="850" height="557" /></div>
<br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-Decorator-4-analys.gif" width="816" height="373" /></div>
<br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/DesignPattern-Decorator-5-analys.gif" width="816" height="525" /></div>
<font style="background-color: #cce8cf">4.设计任务</font><br />
<div align="center"><img border="0" alt="" src="http://www.blogjava.net/images/blogjava_net/jjshcc/技术截图/DesignPattern-Decorator-6-realize.gif" width="751" height="374" /></div>
<p><br />
</p>
<p><font style="background-color: #cce8cf">三、代码实现</font></p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<p><font style="background-color: #cce8cf">1．定义抽象类</font></p>
<p><font style="background-color: #cce8cf">&nbsp;</font></p>
<p><font style="background-color: #cce8cf">（1）饮料抽象类Beverage</font></p>
<p><font style="background-color: #cce8cf">Beverage.java<br />
</p>
<p><font style="background-color: #cce8cf">&nbsp;package com.leanhuadeng.DesignPattern.Decorator;</font></p>
<p><font style="background-color: #cce8cf">/* <br />
&nbsp;* Beverage是一个抽象类,有两个方法<br />
&nbsp;*/<br />
public abstract class Beverage {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String description="Unknown Beverage";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * getDescription()已经在此实现了,但是cost()必须在子类中实现<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String getDescription() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return description;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public abstract double cost();<br />
}</font></p>
<p><font style="background-color: #cce8cf"></font>&nbsp;</p>
<p><font style="background-color: #cce8cf">三、代码实现<br />
&nbsp;<br />
(2)调料抽象类CondimentDecorator<br />
CondimentDecorator.java<br />
package com.leanhuadeng.DesignPattern.Decorator;<br />
/* <br />
&nbsp;* 首先,必须让CondimentDecorator能够取代Beverage,所以将CondimentDecorator扩展自Beverage类<br />
&nbsp;*/<br />
public abstract class CondimentDecorator extends Beverage {</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; //所有的调料装饰者都必须重新实现getDescription()方法.<br />
&nbsp;&nbsp;&nbsp; public abstract String getDescription();<br />
}<br />
&nbsp; <br />
2．饮料实现</font></p>
<p><font style="background-color: #cce8cf">(1)Espresso</font></p>
<p><font style="background-color: #cce8cf">Espresso.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator;</font></p>
<p><font style="background-color: #cce8cf">/**//*<br />
&nbsp;* 首先,必须让CondimentDecorator能够取代Beverage,所以将CondimentDecorator扩展自Beverage类<br />
&nbsp;*/<br />
public abstract class CondimentDecorator extends Beverage {</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; //所有的调料装饰者都必须重新实现getDescription()方法.<br />
&nbsp;&nbsp;&nbsp; public abstract String getDescription();<br />
}</font></p>
<p><font style="background-color: #cce8cf">&nbsp; <br />
(2)HouseBlend</font></p>
<p><font style="background-color: #cce8cf">HouseBlend.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator.drink;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.Beverage;</font></p>
<p><font style="background-color: #cce8cf">public class HouseBlend extends Beverage {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public HouseBlend() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description="House Blend Coffee";<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public double cost() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0.89;<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">}<br />
&nbsp; <br />
(3)DarkRoast</font></p>
<p><font style="background-color: #cce8cf">DarkRoast.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator.drink;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.Beverage;</font></p>
<p><font style="background-color: #cce8cf">public class DarkRoast extends Beverage {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public DarkRoast() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description="Dark Roast Coffee";<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public double cost() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0.99;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
&nbsp; <br />
(4)Decaf</font></p>
<p><font style="background-color: #cce8cf">Decaf.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator.drink;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.Beverage;</font></p>
<p><font style="background-color: #cce8cf">public class Decaf extends Beverage {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Decaf() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; description="Decaf Coffee";<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public double cost() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1.05;<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></p>
<p><font style="background-color: #cce8cf">&nbsp; <br />
3．调料实现</font></p>
<p><font style="background-color: #cce8cf">(1)Mocha</font></p>
<p><font style="background-color: #cce8cf">Mocha.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator.condiment;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.Beverage;<br />
import com.leanhuadeng.DesignPattern.Decorator.CondimentDecorator;</font></p>
<p><font style="background-color: #cce8cf">public class Mocha extends CondimentDecorator {<br />
&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp; * 要让Mocha能够引用一个Beverage,做法如下:一是用一个实例变量记录饮料,也就是被装饰者.<br />
&nbsp;&nbsp;&nbsp;&nbsp; * 二是想办法让装饰者(饮料)记录到实例变量中,即把饮料当作构造器的参数,再由构造器将此饮料记录在实例变量中<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp; Beverage beverage;</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public Mocha(Beverage beverage) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.beverage = beverage;<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public String getDescription() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 我们希望叙述不只是描述饮料,而是完整的连调料都描述出来<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return beverage.getDescription()+",Mocha";<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public double cost() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 要计算带Mocha饮料的价钱,首先把调用委托给装饰对象,以计算价钱,然后再加上Mocha的价钱,得到最后结果<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0.20+beverage.cost();<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></p>
<p><font style="background-color: #cce8cf">&nbsp; <br />
(2)Soy</font></p>
<p><font style="background-color: #cce8cf">Soy.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator.condiment;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.Beverage;<br />
import com.leanhuadeng.DesignPattern.Decorator.CondimentDecorator;</font></p>
<p><font style="background-color: #cce8cf">public class Soy extends CondimentDecorator {<br />
&nbsp;&nbsp;&nbsp; Beverage beverage;</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public Soy(Beverage beverage) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.beverage = beverage;<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public String getDescription() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return beverage.getDescription() + ", Soy";<br />
&nbsp;&nbsp;&nbsp; }</font></p>
<p><font style="background-color: #cce8cf">&nbsp;&nbsp;&nbsp; public double cost() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return .15 + beverage.cost();<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></p>
<p><font style="background-color: #cce8cf">&nbsp; <br />
(3)Whip</font></p>
<p><font style="background-color: #cce8cf">Whip.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator.condiment;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.Beverage;<br />
import com.leanhuadeng.DesignPattern.Decorator.CondimentDecorator;<br />
&nbsp;<br />
public class Whip extends CondimentDecorator {<br />
&nbsp;&nbsp;&nbsp; Beverage beverage;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public Whip(Beverage beverage) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.beverage = beverage;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public String getDescription() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return beverage.getDescription() + ", Whip";<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public double cost() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return .10 + beverage.cost();<br />
&nbsp;&nbsp;&nbsp; }<br />
}</font></p>
<p><font style="background-color: #cce8cf">&nbsp; <br />
4．测试类StarbuzzCoffee</font></p>
<p><font style="background-color: #cce8cf">StarbuzzCoffee.java</font></p>
<p><font style="background-color: #cce8cf">package com.leanhuadeng.DesignPattern.Decorator;</font></p>
<p><font style="background-color: #cce8cf">import com.leanhuadeng.DesignPattern.Decorator.condiment.Mocha;<br />
import com.leanhuadeng.DesignPattern.Decorator.condiment.Soy;<br />
import com.leanhuadeng.DesignPattern.Decorator.condiment.Whip;<br />
import com.leanhuadeng.DesignPattern.Decorator.drink.DarkRoast;<br />
import com.leanhuadeng.DesignPattern.Decorator.drink.Espresso;<br />
import com.leanhuadeng.DesignPattern.Decorator.drink.HouseBlend;</font></p>
<p><font style="background-color: #cce8cf">public class StarbuzzCoffee {<br />
&nbsp;&nbsp;&nbsp; public static void main(String args[]){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 订一杯Espresso,不需要调料,打印出它的描述和价钱.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Beverage beverage=new Espresso();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(beverage.getDescription()+" $"+beverage.cost());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 制造一个DarkRoast对象,用Mocha,Whip装饰它<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Beverage beverage2=new DarkRoast();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beverage2=new Mocha(beverage2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beverage2=new Mocha(beverage2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beverage2=new Whip(beverage2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(beverage2.getDescription()+" $"+beverage2.cost());&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 最后,再来一杯调料为豆浆,摩卡\奶泡的HouseBlend咖啡<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Beverage beverage3=new HouseBlend();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beverage3=new Soy(beverage3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beverage3=new Mocha(beverage3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; beverage3=new Whip(beverage3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(beverage3.getDescription()+" $"+beverage3.cost());&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
</font></p>
<p><br />
</font></p>
<img src ="http://www.blogjava.net/jjshcc/aggbug/331457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 09:32 <a href="http://www.blogjava.net/jjshcc/archive/2010/09/09/331457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>