??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品综合久久中文字幕,亚洲国产精品乱码一区二区,亚洲黄色在线网站http://www.tkk7.com/jjshcc/category/46277.htmlzh-cnWed, 10 Nov 2010 18:49:56 GMTWed, 10 Nov 2010 18:49:56 GMT60讉K者模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/10/31/336613.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/336613.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/10/31/336613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/336613.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/336613.html</trackback:ping><description><![CDATA[<div id="jnxabna" 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 class="plmtssg" 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">具体元素的接口与实现c?br /> <br /> public interface Person {<br />       void accept(Visitor visitor);<br /> }<br /> <br /> <br /> public class Woman implements Person{<br /> <br />     public void accept(Visitor visitor) {<br />           visitor.visit(this);<br />     }<br /> }<br /> <br /> <br /> public class Man implements Person{<br /> <br />     public void accept(Visitor visitor) {<br />         visitor.visit(this);<br />     }<br /> }<br /> <br /> <br /> <br /> 讉K者接口与实现c,分别代表男h与女人在不同的状态下的表?br /> <br /> public interface Visitor {<br />       public void visit(Man man);<br />       public void visit(Woman girl);<br /> }<br /> <br /> //成功时Man与Woman的不同表?br /> public class Success implements Visitor{<br /> <br />     public void visit(Man man) {<br />         System.out.println("当男人成功时Q背后多半有一个伟大的女h");<br />     }<br /> <br /> <br />     public void visit(Woman woman) {<br />         System.out.println("当女人成功时Q背后大多有一个不成功的男?);<br />     }<br /> }<br /> <br /> //恋爱时Man与Woman的不同表?br /> public class Love implements Visitor{<br /> <br />     public void visit(Man man) {<br />         System.out.println("当男人恋爱时Q凡事不懂也装懂");<br />     }<br /> <br /> <br />     public void visit(Woman girl) {<br />         System.out.println("当女人恋爱时Q遇事懂也装不懂");<br />     }<br /> }<br /> <br /> <br /> <br /> ObjectStructure与客L(fng)试代码<br /> <br /> import java.util.*;<br /> <br /> public class ObjectStructure {<br />     private List<Person> elements = new ArrayList<Person>();<br /> <br />     public void attach(Person element){<br />         elements.add(element);<br />     }<br />     <br />     public void detach(Person element){<br />         elements.remove(elements);<br />     }<br />     <br />     //遍历各种具体元素q执行他们的acceptҎ(gu)<br />     public void display(Visitor visitor){<br />         for(Person p:elements){<br />             p.accept(visitor);<br />         }<br />     }<br /> }<br /> <br /> <br /> public class Client {<br />       public static void main(String[] args) {<br />         ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure<br />         //实例化具体元?br />         o.attach(new Man());  <br />         o.attach(new Woman());<br />         <br />         //当成功时不同元素的不同反?br />         Visitor success = new Success();           //依赖于抽象的Visitor接口<br />         o.display(success);<br />         <br />         //当恋爱时的不同反?br />         Visitor amativeness = new Love();          //依赖于抽象的Visitor接口<br />         o.display(amativeness);<br />         <br />     }<br /> }<br /> <br /> <br /> <br /> 需求的变化<br /> <br /> 假设现在需求要扩展数据l构Q增加一U具体元素,男与女之外的一U不明物体,我们暂时把它UCؓ(f)“怪兽”Q在既有讉K者模式的架构下,应该怎样Q首先增加一个Brucec,实现Person接口。最ȝ的是要修改访问者接口及(qing)其所有具体访问?<br /> <br />   因ؓ(f)VisitҎ(gu)中没有包含访问Bruce对象的行为,因此我们被迫要去手工更改Visitor(包括抽象的,具体?Q在其中d有关Bruce对象的行为,q严重违反了“开?闭”原则。究其原因在于目前的l构下,被访问对象与讉K对象互相依赖Q自然不利于分离变化Q必d掉一层依赖关pR?br /> <br /> 我们试把Visitor对Person(元素)的依赖关pd掉,抽象出对应每个具体元素的ElementVisitor接口 -->ManVisitor,WomanVisitorQ然后把Visitor对Person的依赖关p{UdManVisitor?WomanVisitorw上?br />  <br /> 现在Visitor接口已经没有M抽象Ҏ(gu)Q只是一个空接口Q每一个具体元素对应有一个ElementVisitor接口Q每一个元素对应的ElementVisitor接口有访问该元素的visit(),相当把原来在Visitor接口中声明工作,交由各个具体ElementVisitor接口完成?br /> <br /> <br /> l过攚w后的代码:(x)<br /> 原Visitor接口<br /> <br /> public interface Visitor {<br />       //退化到没有M抽象Ҏ(gu)<br /> }<br /> <br /> <br /> <br /> 新增加ManVisitor,WomanVisitor接口<br /> <br /> public interface ManVisitor {<br />       public void visit(Man man);<br /> }<br /> <br /> public interface WomanVisitor {<br />       public void visit(Woman w);<br /> }<br /> <br />  <br /> 具体Visitor实现cȝ在同时实?个接?br /> <br /> //由实现Visitor接口扩展成实现Visitor,WomanVisitor,ManVisitor三个接口<br /> public class Success implements Visitor,WomanVisitor,ManVisitor{<br /> <br />     public void visit(Man man) {<br />         System.out.println("当男人成功时Q背后多半有一个伟大的女h");<br />     }<br /> <br />     public void visit(Woman girl) {<br />         System.out.println("当女人成功时Q背后大多有一个不成功的男?);<br />     }<br /> }<br /> <br /> <br /> //由实现Visitor接口扩展成实现Visitor,WomanVisitor,ManVisitor三个接口<br /> public class Love implements Visitor,WomanVisitor,ManVisitor{<br /> <br />     public void visit(Man man) {<br />         System.out.println("当男人恋爱时Q凡事不懂也装懂");<br />     }<br /> <br />     public void visit(Woman girl) {<br />         System.out.println("当女人恋爱时Q遇事懂也装不懂");<br />     }<br /> }<br /> <br /> <br /> <br /> Person接口没有变化,依旧只依赖于Visitor接口<br /> <br /> public interface Person {<br />       void accept(Visitor visitor);<br /> }<br /> <br /> <br /> <br /> 攚w后的具体元素类Man与Woman<br /> <br /> public class Man implements Person {<br /> <br />     // 先对visitorq行cd转换Q再执行visitҎ(gu)Q因为Visitor接口已经没有声明M抽象Ҏ(gu)?br />     public void accept(Visitor visitor) {<br />         if (visitor instanceof ManVisitor) {<br />             ManVisitor mv = (ManVisitor) visitor;<br />             mv.visit(this);<br />         }<br />     }<br /> }<br /> <br /> <br /> public class Woman implements Person {<br /> <br />     // 先对visitorq行cd转换Q再执行visitҎ(gu)Q因为Visitor接口已经没有声明M抽象Ҏ(gu)?br />     public void accept(Visitor visitor) {<br />         if (visitor instanceof WomanVisitor) {<br />             WomanVisitor wv = (WomanVisitor) visitor;<br />             wv.visit(this);<br />         }<br />     }<br /> }<br /> <br /> <br /> <br /> ObjectStructure与客L(fng)试代码没有变化<br /> <br /> import java.util.*;<br /> <br /> public class ObjectStructure {<br />     private List<Person> elements = new ArrayList<Person>();<br /> <br />     public void attach(Person element){<br />         elements.add(element);<br />     }<br />     <br />     public void detach(Person element){<br />         elements.remove(elements);<br />     }<br />     <br />     //遍历各种具体元素q执行他们的acceptҎ(gu)<br />     public void display(Visitor visitor){<br />         for(Person p:elements){<br />             p.accept(visitor);<br />         }<br />     }<br /> }<br /> <br /> <br /> public class Client {<br />       public static void main(String[] args) {<br />         ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure<br />         //实例化具体元?br />         o.attach(new Man());  <br />         o.attach(new Woman());<br />         <br />         //当成功时不同元素的不同反?br />         Visitor success = new Success();           //依赖于抽象的Visitor接口<br />         o.display(success);<br />         <br />         //当恋爱时的不同反?br />         Visitor amativeness = new Love();          //依赖于抽象的Visitor接口<br />         o.display(amativeness);        <br />     }<br /> }<br /> <br /> <br /> <br /> x攚w完毕!我们执行客户端测试代码,l果昄Q?br /> 当男人成功时Q背后多半有一个伟大的女h<br /> 当女人成功时Q背后大多有一个不成功的男?br /> 当男人恋爱时Q凡事不懂也装懂<br /> 当女人恋爱时Q遇事懂也装不懂<br /> <br /> 此时Q客L(fng)仍然只依赖于VisitorI接口与ObjectStructurecR可能一开始大家会(x)认ؓ(f)I接口没有什么用Q现在就能体现出他的威力了,使客L(fng)与具体Visitor的高度解耦!也正是这U思维的核心在JavaAPI中也有类似的应用Q这U空接口被称为标识接口。比如java.io.Serializable与java.rmi.Remote{,标识接口里没有Q何方法和属性,标识不对实现接口不对实现它的cLM语义上的要求Q它仅仅是表明实现它的类属于一U特定的cd?br /> 上面具体讉K者实现的多个接口被称为؜合类型。这个概c(din)Java与模式》中有提?qing)过Q当一个具体类处于一个类的等U结构之中的时候,个具体类定义一个؜合类型是可以保证Zq个cd的可插入性的关键?br /> <br /> =================================无敌分界U?===================================<br /> <br /> 讲了q么长,现在我们试下改造后的访问者模?br /> 首先增加一U行?状?Q即原访问者模式的优点<br /> <br /> 增加一个具体访问者Fail,修改一下客L(fng)试代码<br /> <br /> public class Fail implements Visitor,ManVisitor,WomanVisitor{<br /> <br />     public void visit(Man man) {<br />         System.out.println("当男人失败时Q闷头喝酒,谁也不用?);<br />     }<br /> <br />     public void visit(Woman woman) {<br />         System.out.println("当女人失败时Q眼泪汪汪,谁也劝不?);<br />     }<br /> }<br /> <br /> <br /> <br /> public class Client {<br />       public static void main(String[] args) {<br />         ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure<br />         //实例化具体元?br />         o.attach(new Man());  <br />         o.attach(new Woman());<br />         <br />         //当成功时不同元素的不同反?br />         Visitor success = new Success();           //依赖于抽象的Visitor接口<br />         o.display(success);<br />         System.out.println();<br />         <br />         //当恋爱时的不同反?br />         Visitor amativeness = new Love();          //依赖于抽象的Visitor接口<br />         o.display(amativeness);        <br />         System.out.println();<br />         <br />         //新增加失败时的不同反?br />         Visitor fail = new Fail();<br />         o.display(fail);<br />     }<br /> }<br /> <br /> <br /> <br /> l果昄Q?br /> 当男人成功时Q背后多半有一个伟大的女h<br /> 当女人成功时Q背后大多有一个不成功的男?br /> <br /> 当男人恋爱时Q凡事不懂也装懂<br /> 当女人恋爱时Q遇事懂也装不懂<br /> <br /> 当男人失败时Q闷头喝酒,谁也不用?br /> 当女人失败时Q眼泪汪汪,谁也劝不?br /> <br /> <br /> <br /> 增加新的行ؓ(f)(状?与原来一h便!只需要增加一个具体访问者即可!<br /> 现在我们来增加一个具体元?正是写这文章的初衷)<br /> <br /> 首先增加一个具体元素Bruce<br /> <br /> public class Bruce implements Person{<br />     <br />     public void accept(Visitor visitor) {        <br />         if(visitor instanceof BruceVisitor){<br />             BruceVisitor bv = (BruceVisitor) visitor;<br />             bv.visit(this);<br />         }<br />         //q个else可写可不?br />         else{<br />             String s = visitor.getClass().getName();<br />             String state = s.substring(s.lastIndexOf(".")+1,s.length());<br />             System.out.println("?.原来怪兽?+state+"的时候是没有行ؓ(f)?!");<br />         }        <br />     }<br /> }<br /> <br /> <br /> //按照新的思维方式增加一个对应的ElementVisitor接口<br /> public interface BruceVisitor {<br />       public void visit(Bruce bruce);<br /> }<br /> <br /> <br /> <br /> 我们让Successq个具体讉K者多实现一个BruceVisitor讉K者接?和修改一下客L(fng)代码q行试<br /> <br /> public class Success implements Visitor,WomanVisitor,ManVisitor,BruceVisitor{<br /> <br />     public void visit(Man man) {<br />         System.out.println("当男人成功时Q背后多半有一个伟大的女h");<br />     }<br /> <br />     public void visit(Woman girl) {<br />         System.out.println("当女人成功时Q背后大多有一个不成功的男?);<br />     }<br /> <br />     public void visit(Bruce bruce) {<br />         System.out.println("当怪兽成功?........无语..........");<br />     }<br /> }<br /> <br /> <br /> public class Client {<br />       public static void main(String[] args) {<br />         ObjectStructure o = new ObjectStructure();  //依赖于ObjectStructure<br /> <br />         o.attach(new Man());  <br />         o.attach(new Woman());<br />         o.attach(new Bruce());      //新增一U具体元素Bruce<br />         <br />         Visitor success = new Success();           //依赖于抽象的Visitor接口<br />         o.display(success);<br />         System.out.println();<br />         <br />         Visitor amativeness = new Love();          //依赖于抽象的Visitor接口<br />         o.display(amativeness);        <br />         System.out.println();<br />         <br />         Visitor fail = new Fail();<br />         o.display(fail);<br />     }<br /> }<br /> <br /> <br /> <br /> 昄l果Q?br /> 当男人成功时Q背后多半有一个伟大的女h<br /> 当女人成功时Q背后大多有一个不成功的男?br /> 当怪兽成功?........无语..........<br /> <br /> 当男人恋爱时Q凡事不懂也装懂<br /> 当女人恋爱时Q遇事懂也装不懂<br /> ?.原来怪兽在Love的时候是没有行ؓ(f)?!<br /> <br /> 当男人失败时Q闷头喝酒,谁也不用?br /> 当女人失败时Q眼泪汪汪,谁也劝不?br /> ?.原来怪兽在Fail的时候是没有行ؓ(f)?!<br /> <br /> <br /> q个l果你满意吗Q?br /> 虽然Q这只是部分W合“开?闭”原则Q我们不需要修改Visitor接口Q但q是得去修改Success实现新的接口。但是修改具体类比修Ҏ(gu)口的代h(hun)得多,不需要重新编译所有访问接口和具体讉K者。我们面对新的变化也容易得多。而且q还有一个好处,是可以让各U元素有选择地让别h讉KQ如上述例子Q这样讉K者模式的q用h更加灉|?<br /> </div> </div> <img src ="http://www.tkk7.com/jjshcc/aggbug/336613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-10-31 17:24 <a href="http://www.tkk7.com/jjshcc/archive/2010/10/31/336613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>适配器模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/10/29/336517.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/336517.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/10/29/336517.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/336517.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/336517.html</trackback:ping><description><![CDATA[<p>c适配?<br /> 客户的开发h员定义了一个接口,期望用这个接口来完成整数的求和操作,接口定义如下Q?<br />  <br /> public interface Operation{    <br />       public int add(int a,int b);    <br /> }  <br />  开发h员在了解q个接口的定义后Q发C个第三方c,里面有一个方法能实现他们期望的功能,其代码如下:(x) <br />  <br /> public class OtherOperation{    <br />       public int otherAdd(int a,int b){    <br />            return a + b;    <br />       }    <br /> }  <br />  以上W三方类OtherOperation的方法public int otherAdd(int a,int b)所提供的功能,完全能符合客L(fng)期望Q所以只需要想办法把OtherOperation的otherAdd(int a,int b)和客L(fng)Operation接口联系hQ让q个W三方类来ؓ(f)客户提供他们期望的服务就行了Q这样就避免了开发h员再度去研究cMOtherOperation的otherAdd(int a,int b)Ҏ(gu)的实玎ͼ利用已有的轮子,避免重复发明Q,q方法之一Q就是用适配器模式:(x) <br />  <br /> public class AdapterOperation extends OtherOperation implements Operation{    <br />       public int add(int a,int b){    <br />            return otherAdd(a,b);    <br />       }    <br /> }  <br />  以上是适配器的实现Ҏ(gu)之一Q类适配器,在以上实C存在着三中角色分别是:(x) <br /> 1Q适配目标角色QOperation?<br /> 2Q适配c(原)角色QOtherOperation?<br /> 3Q适配器角Ԍ(x)AdapterOperation?<br /> 其中适配器角色是适配器模式的核心?<br /> 适配器的主要工作是通过装现有的功能,使他满需要的接口?<br /> 对象适配?<br /> 我们再来看看另一U情况:(x) <br /> 假如客户接口期望的功能不止一个,而是多个Q?<br />  <br /> public interface Operation{    <br />       public int add(int a,int b);    <br />       public int minus(int a,int b);    <br />       public int multiplied(int a,int b);    <br /> }  <br />  而能提供q些实现的原可能不止一个:(x) <br />  <br /> public class OtherAdd{    <br />       public int otherAdd(int a,int b){    <br />            return a + b;    <br />       }    <br /> }    <br />    <br /> public class OtherMinus{    <br />       public int minus(int a,int b){    <br />            return a - b;    <br />       }    <br /> }    <br />    <br /> public class OtherMultiplied{    <br />       public int multiplied(int a,int b){    <br />            return a * b;    <br />       }    <br /> }  <br />  ׃java是不能实现多l承的,所以我们不能通过构徏一个适配器,让他来承所有原以完成我们的期望Q这时候怎么办呢?只能用适配器的另一U实?-对象适配器:(x) <br />  <br /> public class AdapterOperation implements Operation{    <br />       private OtherAdd add;    <br />       private OtherMinus minus;    <br />       private OtherMultiplied multiplied;    <br />    <br />       public void setAdd(OtherAdd add){    <br />             this.add = add;    <br />       }    <br />    <br />       public void setMinus(OtherMinus minus){    <br />             this.minus = minus;    <br />       }    <br />    <br />       public void setMultiplied(OtherMultiplied multiplied){    <br />             this.multiplied = multiplied;    <br />       }    <br />    <br />       //适配加法q算    <br />       public int add(int a,int b){    <br />            return add.otherAdd(a,b);    <br />       }    <br />    <br />       //适配减法q算    <br />       public int minus(int a,int b){    <br />           return minus.minus(a,b);    <br />       }    <br />    <br />       //适配乘法q算    <br />       public int multiplied(int a,int b){    <br />          return multiplied.multiplied(a,b);    <br />       }    <br /> }<br />   <br />  </p> <p>上面代码很明显,适配器ƈ不是通过l承来获取适配c(原)的功能的Q而是通过适配cȝ对象来获取的Q这p决了java不能多承所带来的不便了。这也是java提倡的~程思想之一Q即量使用聚合不要使用l承?q有一U情冉|需要用对象适配器的。我们来看看Q单我们的客h供的需求ƈ不是一个明的接口Q而是一个类Qƈ没有定义期望的方法,如下 <br />  <br /> public class A{    <br />    public int add(int a,int b){    <br />       return a + b;    <br />    }    <br /> }  <br />  <br /> 现在客户要一个新cBQ要求能在保留类A功能的情况下增加一个运减法的功能Qƈ要求B能随时替换掉A但不能对已有pȝ造成影响。这h们只能新Z个类BQƈ让Bl承A?<br />  <br /> public class B extends A{    <br />     b(){    <br />       super();    <br />     }    <br />    <br />     public int minus(int a,int b){    <br />            //待实现的减法q算函数..    <br />     }    <br /> }  <br />  <br /> q时候,我们发现cC已经提供了实现减法的函数Q?<br />   <br /> public class C{<br />     public int minus(int a,int b){<br />            return a - b;<br />     }<br /> }</p> <p>Z避免重复去设计该函数Q我们决定引入Cc,通过适配CcL辑ֈ我们的期望,但问题是A和C都是一个具体类Q我们无法让B同时l承q个两个c,而Bl承A又是必须的,所以我们只能考虑把Cl内聚到B内部Q对象适配器又得派上用Z?<br />  <br /> public class B extends A{<br />     private C c;<br />     B(){<br />       super();<br />     }<br />     public void setMinus(C c){<br />          this.c= c;<br />     }<br />     public int minus(int a,int b){<br />            return c.minus(a,b);<br />     }<br /> }</p> <p>q样Q在需要Acȝ地方都能用BcL代替Q同时又保证了新的功能的引入?<br /> 更灵zȝ实现--隐藏目标接口的抽象适配?<br /> 做java 桌面应用的都知道WindowListener接口Q?<br />  <br /> public interface WindowListener extends EventListener{<br />  public void windowActivated(WindowEvent e)Q?br />  public void windowClosed(WindowEvent e)Q?br />  public void windowClosing(WindowEvent e)Q?br />  public void windowDeactivated(WindowEvent e)Q?br />  public void windowDeiconified(WindowEvent e)Q?br />  public void windowIconified(WindowEvent e)Q?br />  public void windowOpened(WindowEvent e)Q?br /> }</p> <p>要实现这个接口,我们必d现它所定义的所有方法,但是实际上,我们很少需要同时用到所有的Ҏ(gu)Q我们要的只是其中的两三个。ؓ(f)了不使我们实现多余的Ҏ(gu)Q?<br /> jdk WindowListener提供了一个WindowListener的默认实现类WindowAdapterc,q是一个抽象类Q?<br />   <br /> public abstract class WindowAdapter implements WindowListener{<br />  public void windowActivated(WindowEvent e){}<br />  public void windowClosed(WindowEvent e){}<br />  public void windowClosing(WindowEvent e){}<br />  public void windowDeactivated(WindowEvent e){}<br />  public void windowDeiconified(WindowEvent e){}<br />  public void windowIconified(WindowEvent e){}<br />  public void windowOpened(WindowEvent e){}<br /> }</p> <p>WindowAdaptercdWindowListener接口的所有有Ҏ(gu)都提供了I实玎ͼ <br /> 有了WindowAdapterc,我们只需要去l承WindowAdapterQ然后选择我们所兛_的方法来实现p了,q样避免了直接d现WindowListener接口?<br /> </p> <img src ="http://www.tkk7.com/jjshcc/aggbug/336517.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-10-29 20:56 <a href="http://www.tkk7.com/jjshcc/archive/2010/10/29/336517.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>{略模式http://www.tkk7.com/jjshcc/archive/2010/10/16/335308.htmlEric_jiangEric_jiangSat, 16 Oct 2010 13:21:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/10/16/335308.htmlhttp://www.tkk7.com/jjshcc/comments/335308.htmlhttp://www.tkk7.com/jjshcc/archive/2010/10/16/335308.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/335308.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/335308.html设计模式解读之一Q?{略模式
1. 模式定义

把会(x)变化的内容取出ƈ装hQ以便以后可以轻易地改动或扩充部分,而不影响不需要变化的其他部分Q?br />
2. 问题~v
当涉?qing)至代码l护ӞZ复用目的而用承,l局q不完美。对父类的修改,?x)媄响到子类型。在类中增加的Ҏ(gu)Q会(x)D子类型有该方法,甚至q那些不该具备该Ҏ(gu)的子cd也无法免除。示例,一个鸭子类型:(x)

public abstract class Duck {
    //所有的鸭子均会(x)叫以?qing)游泻I所以父cM处理q部分代?br />     public void quack() {
        System.out.println("Quack");
    }

    public void swim() {
        System.out.println("All ducks float, even decoys.");      
    }

    //因ؓ(f)每种鸭子的外观是不同的,所以父cM该方法是抽象的,由子cd自己完成?br />     public abstract void display();
}

public class MallardDuck extends Duck {
    //野鸭外观昄为绿?br />     public void display() {
        System.out.println("Green head.");
    }
}

public class RedHeadDuck extends Duck {
    //U头鸭显CZؓ(f)U头
    public void display() {
        System.out.println("Red head.");
    }
}

public class RubberDuck extends Duck {
   
    //皮鸭叫Cؓ(f)吱吱叫,所以重写父cM改写行ؓ(f)
    public void quack() {
        System.out.println("Squeak");
    }

    //皮鸭显CZؓ(f)黄头
    public void display() {
        System.out.println("Yellow head.");
    }
}

                    上述代码Q初始实现得非常好。现在我们如果给Duck.java中加入fly()Ҏ(gu)的话Q那么在子类型中均有了该Ҏ(gu)Q于是我们看C?x)飞的橡皮鸭子,你看q吗Q当Ӟ我们可以在子cM通过I实现重写该Ҏ(gu)以解册Ҏ(gu)对于子类型的影响。但是父cM再增加其它的Ҏ(gu)呢?

通过l承在父cM提供行ؓ(f)Q会(x)D以下~点Q?br />
a. 代码在多个子cM重复;
b. q行时的行ؓ(f)不容易改变;
c. 改变?x)牵一发动全nQ造成部分子类型不惌的改变;

好啦Q还是刚才鸭子的例子Q你也许惛_使用接口Q将飞的行ؓ(f)、叫的行为定义ؓ(f)接口Q然后让Duck的各U子cd实现q些接口。这时侯代码cM于:(x)

public abstract class Duck {
    //变化的行ؓ(f) fly() 以及(qing)quake()从DuckcM分离出去定义形成接口Q有需求的子类中自行去实现

    public void swim() {
        System.out.println("All ducks float, even decoys.");      
    }

    public abstract void display();
}

//变化?fly() 行ؓ(f)定义形成的接?br /> public interface FlyBehavior {
    void fly();
}

//变化?quack() 行ؓ(f)定义形成的接?br /> public interface QuackBehavior {
    void quack();
}

//野鸭子会(x)飞以?qing)叫Q所以实现接?nbsp; FlyBehavior, QuackBehavior
public class MallardDuck extends Duck implements FlyBehavior, QuackBehavior{
    public void display() {
        System.out.println("Green head.");
    }

    public void fly() {
        System.out.println("Fly.");              
    }

    public void quack() {
        System.out.println("Quack.");              
    }
}

//U头鸭子?x)飞以?qing)叫,所以也实现接口  FlyBehavior, QuackBehavior
public class RedHeadDuck extends Duck implements FlyBehavior, QuackBehavior{
    public void display() {
        System.out.println("Red head.");
    }  

    public void fly() {
        System.out.println("Fly.");              
    }

    public void quack() {
        System.out.println("Quack.");              
    }  
}

//皮鸭不?x)飞Q但?x)吱吱叫Q所以只实现接口QuackBehavior
public class RubberDuck extends Duck implements QuackBehavior{
    //皮鸭叫Cؓ(f)吱吱?br />     public void quack() {
        System.out.println("Squeak");
    }

    //皮鸭显CZؓ(f)黄头
    public void display() {
        System.out.println("Yellow head.");
    }
}

上述代码虽然解决了一部分问题Q让子类型可以有选择地提供一些行?例如 fly() Ҏ(gu)不?x)出现在皮鸭?.但我们也看到Q野鸭子MallardDuck.java和红头鸭子RedHeadDuck.java的一些相同行Z码不能得到重复用。很大程度上q是从一个火坑蟩到另一个火坑?br />
在一D늨序之后,让我们从l节中蟩出来Q关注一些共性问题。不用什么语aQ构Z么应用,在Y件开发上Q一直伴随着的不变的真理是:(x)需要一直在变化。不当初Y件设计得多好Q一D|间之后,L需要成长与改变Q否则Y件就?x)死亡?br />     我们知道Q承在某种E度上可以实C码重用,但是父类(例如鸭子cDuck)的行为在子类型中是不断变化的Q让所有子cd都有q些行ؓ(f)是不恰当的。我们可以将q些行ؓ(f)定义为接口,让Duck的各U子cdd玎ͼ但接口不h实现代码Q所以实现接口无法达C码复用。这意味着Q当我们需要修Ҏ(gu)个行为,必须往下追tƈ在每一个定义此行ؓ(f)的类中修改它Q一不小心,?x)造成新的错误?br />
设计原则Q把应用中变化的地方独立出来Q不要和那些不需要变化的代码混在一赗这样代码变化引L(fng)不经意后果变,pȝ变得更有Ҏ(gu)?br />
按照上述设计原则Q我们重新审视之前的Duck代码?br />
1) 分开变化的内容和不变的内?br />
DuckcM的行?fly(), quack(), 每个子类型可能有自己Ҏ(gu)的表玎ͼq就是所谓的变化的内宏V?br /> DuckcM的行?swim() 每个子类型的表现均相同,q就是所谓不变的内容?br />
我们变化的内容从Duck()cM剥离出来单独定义形成接口以及(qing)一pd的实现类型。将变化的内容定义Ş成接口可实现变化内容和不变内容的剥离。其实现cd可实现变化内容的重用。这些实现类qDuck.java的子cdQ而是专门的一l实现类Q称之ؓ(f)"行ؓ(f)c?。由行ؓ(f)c而不是Duck.java的子cd来实现接口。这P才能保证变化的行为独立于不变的内宏V于是我们有Q?br />
变化的内容:(x)

//变化?fly() 行ؓ(f)定义形成的接?br /> public interface FlyBehavior {
    void fly();
}

//变化?fly() 行ؓ(f)的实现类之一
public class FlyWithWings implements FlyBehavior {
    public void fly() {
        System.out.println("I'm flying.");
    }
}

//变化?fly() 行ؓ(f)的实现类之二
public class FlyNoWay implements FlyBehavior {
    public void fly() {
        System.out.println("I can't fly.");
    }
}

-----------------------------------------------------------------

//变化?quack() 行ؓ(f)定义形成的接?br /> public interface QuackBehavior {
    void quack();
}

//变化?quack() 行ؓ(f)实现cM一
public class Quack implements QuackBehavior {
    public void quack() {
        System.out.println("Quack");
    }
}

//变化?quack() 行ؓ(f)实现cM?br /> public class Squeak implements QuackBehavior {
    public void quack() {
        System.out.println("Squeak.");
    }
}

//变化?quack() 行ؓ(f)实现cM?br /> public class MuteQuack implements QuackBehavior {
    public void quack() {
        System.out.println("<< Slience >>");
    }
}

通过以上设计Qfly()行ؓ(f)以及(qing)quack()行ؓ(f)已经和Duck.java没有什么关p,可以充分得到复用。而且我们很容易增加新的行?既不影响现有的行为,也不影响Duck.java。但是,大家可能有个疑问Q就是在面向对象中行Z是体Cؓ(f)Ҏ(gu)吗?Z么现在被定义形成c?例如Squeak.java)Q在OO中,cM表的"东西"一般是既有状?实例变量Q又有方法。只是在本例中碰?东西"是个行ؓ(f)。既使是行ؓ(f)Q也有属性及(qing)Ҏ(gu)Q例如飞行行为,也需要一些属性记录飞行的状态,如飞行高度、速度{?br />
2) 整合变化的内容和不变的内?br />
Duck.java?fly()以及(qing)quack()的行为委拖给行ؓ(f)cd理?br />
不变的内容:(x)

public abstract class Duck {

    //行为类声明为接口类型,降低对行为实现类型的依赖
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public void performFly() {
    //不自行处理fly()行ؓ(f)Q而是委拖l引用flyBehavior所指向的行为对?br />         flyBehavior.fly();
    }

    public void performQuack() {
        quackBehavior.quack();
    }

    public void swim() {
        System.out.println("All ducks float, even decoys.");      
    }

    public abstract void display();
}

Duck.java不关心如何进?fly()以及(qing)quack(), q些l节交由具体的行为类完成?br />
public class MallardDuck extends Duck{
    public MallardDuck() {
        flyBehavior=new FlyWithWings();
        quackBehavior=new Quack();      
    }

    public void display() {
        System.out.println("Green head.");
    }
}

试c:(x)

public class DuckTest {
    public static void main(String[] args) {
        Duck duck=new MallardDuck();
        duck.performFly();
        duck.performQuack();      
    }
}

在Duck.java子类型MallardDuck.java的构造方法中Q直接实例化行ؓ(f)cdQ在~译的时侯便指定具体行ؓ(f)cd。当Ӟ我们可以Q?br />
1) 我们可以通过工厂模式或其它模式进一步解?可参考后l模式讲?;
2) 或做到在q行时动态地改变行ؓ(f)?br />
3) 动态设定行?br />
在父cDuck.java中增加设定行为类型的setterҎ(gu)Q接受行为类型对象的参数传入。ؓ(f)了降藕,行ؓ(f)参数被声明ؓ(f)接口cd。这P既便在运行时Q也可以通过调用q二个方法以改变行ؓ(f)?br />
public abstract class Duck {
    //在刚才Duck.java中加入以下二个方法?br />     public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior=flyBehavior;
    }

    public void setQuackBehavior(QuackBehavior quackBehavior) {
        this.quackBehavior=quackBehavior;
    }

//其它Ҏ(gu)同,省略...
}

试c:(x)

public class DuckTest {
    public static void main(String[] args) {
        Duck duck=new MallardDuck();
        duck.performFly();
        duck.performQuack();
        duck.setFlyBehavior(new FlyNoWay());
        duck.performFly();
    }
}

如果Q我们要加上火箭助力的飞行行为,只需再新建FlyBehavior.java接口的实现类型。而子cd可通过调用setQuackBehavior(...)Ҏ(gu)动态改变。至此,在Duck.java增加新的行ؓ(f)l我们代码所带来的困l已不复存在?br />
该是ȝ的时侯了Q让我们从代码的水中出来,做一只在水面上自由游动的鸭子?

3.  解决Ҏ(gu)

MallardDuck l承  Duck抽象c;          -> 不变的内?br /> FlyWithWings 实现 FlyBehavior接口Q?nbsp;    -> 变化的内?行ؓ(f)或算?br /> 在Duck.java提供setterҎ(gu)以装配关p;    -> 动态设定行?br />
以上是{略模式的实C步曲。接下来Q让我们透过步骤看本?

1) 初始Q我们通过l承实现行ؓ(f)的重用,D了代码的l护问题?nbsp;         -> l承, is a
2) 接着Q我们将行ؓ(f)剥离成单独的cdq声明ؓ(f)不变内容的实例变量ƈ通过  -> l合, has a
setterҎ(gu)以装配关p;

l承Q可以实现静态代码的复用Q组合,可以实现代码的弹性维护;使用l合代替l承Q可以代码更好地适应软g开发完后的需求变化?br />
{略模式的本质:(x)用l承Q多用组?br />

Eric_jiang 2010-10-16 21:21 发表评论
]]>
备忘录模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331546.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331546.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331546.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331546.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331546.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">一?模式定义:<br /> 在不破坏装的前提下Q捕获一个对象的内部状态,q在该对象之外保存这个状态。这样就可以该对象恢复到原先保存前的状态?br /> 二?模式解说<br /> 在程序运行过E中Q某些对象的状态处在{换过E中Q可能由于某U原因需要保存此时对象的状态,以便E序q行到某个特定阶D,需要恢复到对象之前处于某个Ҏ(gu)的状态。如果用一些公有接口让其它对象来得到对象的状态,便会(x)暴露对象的实现细节?br /> <br /> 三?l构?br />  <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?Memento.gif" width="561" height="104" /><br /> 1) 备忘录(MementoQ角Ԍ(x)备忘录角色存?#8220;备忘发v角色”的内部状态?#8220;备忘发v角色”Ҏ(gu)需要决定备忘录角色存储“备忘发v角色”的哪些内部状态。ؓ(f)了防?#8220;备忘发v角色”以外的其他对象访问备忘录。备忘录实际上有两个接口Q?#8220;备忘录管理者角?#8221;只能看到备忘录提供的H接口——对于备忘录角色中存攄属性是不可见的?#8220;备忘发v角色”则能够看C个宽接口——能够得到自己放入备忘录角色中属性?<br /> 2) 备忘发vQOriginatorQ角Ԍ(x)“备忘发v角色”创徏一个备忘录Q用以记录当前时d的内部状态。在需要时使用备忘录恢复内部状态?<br /> 3) 备忘录管理者(CaretakerQ角Ԍ(x)负责保存好备忘录。不能对备忘录的内容q行操作或检查?/font></p> <font style="background-color: #cce8cf"> <p><font style="background-color: #cce8cf">class WindowsSystem{</font></p> <p><font style="background-color: #cce8cf"> private String state;<br />  <br />  public Memento createMemento(){ //创徏pȝ备䆾<br />       return new Memento(state);<br />  }<br />  <br />  public void restoreMemento(Memento m){ //恢复pȝ<br />       this.state=m.getState();<br />  }<br />  <br />  public String getState() {<br />   return state;<br />  }<br />  <br />  public void setState(String state) {<br />   this.state = state;<br />   System.out.println("当前pȝ处于"+this.state);<br />  }</font></p> <p><font style="background-color: #cce8cf">}</font></p> <p><font style="background-color: #cce8cf">class Memento{<br />  private String state;</font></p> <p><font style="background-color: #cce8cf"> public Memento(String state) {<br />   this.state = state;<br />  }</font></p> <p><font style="background-color: #cce8cf"> public String getState() {<br />   return state;<br />  }<br />  <br />  public void setState(String state) {<br />   this.state = state;<br />  }<br /> }</font></p> <p><font style="background-color: #cce8cf">class User{</font></p> <p><font style="background-color: #cce8cf"> private Memento memento;</font></p> <p><font style="background-color: #cce8cf"> public Memento retrieveMemento() {  //恢复pȝ<br />   return this.memento;<br />  }</font></p> <p><font style="background-color: #cce8cf"> public void saveMemento(Memento memento){  //保存pȝ<br />   this.memento = memento;<br />  }<br />  <br /> }</font></p> <p><font style="background-color: #cce8cf">public class Test{</font></p> <p><font style="background-color: #cce8cf"> public static void main(String[] args) {<br />  <br />    WindowsSystem Winxp = new WindowsSystem(); //Winxppȝ<br />    User user = new User();   //某一用户<br />    Winxp.setState("好的状?);   //Winxp处于好的q行状?br />    user.saveMemento(Winxp.createMemento()); //用户对系l进行备份,W(xu)inxppȝ要生备份文?br />    Winxp.setState("坏的状?);   //Winxp处于不好的运行状?br />    Winxp.restoreMemento(user.retrieveMemento());   //用户发恢复命令,pȝq行恢复<br />    System.out.println("当前pȝ处于"+Winxp.getState());<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">在本例中QW(xu)indowsSystem是发起h角色(Orignation),Memento是备忘录角色(Memento),User是备忘录理角色(Caretaker)。Memento提供了两个接口(注意q里的接?q不是java中的接口Q它指的是可被外界调用的Ҏ(gu)Q:(x)一个是为WindowsSystem cȝ宽接口,能够得到WindowsSystem攑օMemento的state属性,代码见WindowsSystem的createMementoҎ(gu)和restoreMementoҎ(gu)QcreateMementoҎ(gu)向Memento攑օstate属性,restoreMementoҎ(gu)获得攑օ的state属性。另一个是为UsercL供的H接口,只能理Memento而不能对它的内容q行M操作Q见Userc)?br /> 五?优缺?br /> 1Q?保持装边界 使用备忘录可以避免暴露一些只应由原发器管理却又必d储在原发器之外的信息。该模式把可能很复杂的Originator内部信息对其他对象屏蔽v来,从而保持了装边界?<br /> 2Q?它简化了原发?在其他的保持装性的设计中,Originator负责保持客户hq的内部状态版本。这把所有存储管理的重Q交给了Originator。让客户理它们h的状态将?x)简化OriginatorQƈ且得客户工作结束时无需通知原发器?<br /> 3Q?使用备忘录可能代价很?如果原发器在生成备忘录时必须拯q存储大量的信息Q或者客户非帔RJ地创徏备忘录和恢复原发器状态,可能?x)导致非常大的开销。除非封装和恢复Originator状态的开销不大Q否则该模式可能q不合适?<br /> 4Q?l护备忘录的潜在代h(hun) 理器负责删除它所l护的备忘录。然而,理器不知道备忘录中有多个状态。因此当存储备忘录时Q一个本来很的理器,可能?x)生大量的存储开销?br /> 六?适用?br /> 1Q必M存一个对象在某一个时ȝQ部分)状态,q样以后需要时它才能恢复到先前的状态?br /> 2Q如果一个用接口来让其它对象直接得到q些状态,会(x)暴露对象的实现细节ƈ破坏对象的封装性?/font></p> <p><font style="background-color: #cce8cf"><br />  </font></p> <p><font style="background-color: #cce8cf"> </font></p> <p><br />  </font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331546.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 16:35 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331546.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中介者模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331528.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331528.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331528.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331528.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331528.html</trackback:ping><description><![CDATA[<font style="background-color: #cce8cf">中介者模式(MediatorQ:(x)用一个中介对象来装一pd的对象交互。中介者各对象不需要显式地怺引用Q从而其耦合松散Q而且可以独立地改变它们之间的交互?br />  <br /> 通用cdQ?br />  <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?215125946.jpg" width="516" height="335" /><br />         举例Q在一个公叔R面,有很多部门、员工(我们l称他们互相为Colleague“同事”Q,Z完成一定的dQ?#8220;同事”之间肯定有许多需要互盔R合、交的q程。如果由各个“同事”频繁地到处去与自己有关的“同事”沟通,q样肯定?x)Ş成一个多对多的杂q联系|络而造成工作效率低下?br />  <br />         此时需要一位专门的“中介?#8221;l各?#8220;同事”分配dQ以?qing)统一跟进大家的进度ƈ?#8220;同事”之间实时地进行交互,保证“同事”之间必须的沟通交。很明显我们知道此时?#8220;中介?#8221;担Q了沟?#8220;同事”彼此之间的重要角色了Q?#8220;中介?#8221;使得每个“同事”都变成一对一的联pL式,减轻了每?#8220;同事”的负担,增强工作效率?br />  <br />         大概理清上面单例子中的意图之后,l出中介者模式适用场景Q?br /> 1、一l对象以定义良好但是复杂的方式进行通信。生的怺依赖关系l构混ؕ且难以理解?br /> 2、一个对象引用其他很多对象ƈ且直接与q些对象通信,D难以复用该对象?br /> 3、想定制一个分布在多个cM的行为,而又不想生成太多的子cR?br />  <br />         其实Q中介者模式又被称?#8220;调停?#8221;模式Q我们可以理解ؓ(f)一小孩子Q同事)吉|了,q时很需要一位大人(调停者)q来处理好小孩子们的关系Q以免发生不必要的冲H?#8220;中介?#8221;?#8220;调停?#8221;只不q是同一个英语单?#8220;Mediator”的不同翻译Ş了。反正最最重要的是Q中介者就是一个处于众多对象,q恰当地处理众多对象之间怺之间的联pȝ角色?br />  <br />         下面l出具体的代码例子,Ҏ(gu)通用cd增加了AbstractColleague抽象同事cdAbstractMediator抽象中介者,另外是两个具体同事cd一个具体中介者,代码中有较多注释Q相应类图也不给ZQ应该不隄解的Q?/font> <br /> <font style="background-color: #cce8cf"> <p><br /> 同事cLQ?br />  //抽象同事c?nbsp; <br />  abstract class AbstractColleague {    <br />   protected AbstractMediator mediator;          <br />   /**既然有中介者,那么每个具体同事必然要与中介者有联系Q?br />   * 否则没必要存在?q个pȝ当中Q这里的构造函数相?<br />   * 于向该系l中注册一个中介者,以取得联p?nbsp;      <br />   */    <br />   public AbstractColleague(AbstractMediator mediator) {<br />    this.mediator = mediator;      <br />   }<br />   // 在抽象同事类中添加用于与中介者取得联p(x册)的方?br />   public void setMediator(AbstractMediator mediator) {<br />    this.mediator = mediator; <br />   }</p> <p> } <br />  <br />   //具体同事A  <br />   class ColleagueA extends AbstractColleague { <br />    <br />    //每个具体同事都通过父类构造函C中介者取得联p?<br />    public ColleagueA(AbstractMediator mediator) {super(mediator);}  <br />    <br />    //每个具体同事必然有自己分内的事,没必要与外界相关?<br />    public void self(){<br />   System.out.println("同事A --> 做好自己分内的事?...");<br />    }<br />    <br />    //每个具体同事L需要与外界交互的操作,通过中介者来处理q些逻辑q安排工?br />    public void out() {<br />     System.out.println("同事A --> h同事B做好分内工作 ...");<br />     super.mediator.execute("ColleagueB", "self");<br />    } <br />    <br />   }<br />   <br />   //具体同事B  <br />   class ColleagueB extends AbstractColleague {     <br />  <br />    public ColleagueB(AbstractMediator mediator) {   <br />   super(mediator);     <br />    }    <br />    <br />    public void self() {     <br />   System.out.println("同事B --> 做好自己分内的事?...");  <br />    }  <br />    <br />    public void out() {    <br />   System.out.println("同事B --> h同事A做好分内工作  ...");     <br />   super.mediator.execute("ColleagueA", "self");  <br />    } <br />   } <br /> <font style="background-color: #cce8cf">//抽象中介?nbsp; <br />  abstract class AbstractMediator {           <br />    //中介者肯定需要保持有若干同事的联pL?nbsp;     <br />    protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>();            <br />    //中介者可以动态地与某个同事徏立联p?nbsp;     <br />    public void addColleague(String name, AbstractColleague c) {          <br />    this.colleagues.put(name, c);      <br />    }              <br />    //中介者也可以动态地撤销与某个同事的联系     <br />    public void deleteColleague(String name) {<br />    this.colleagues.remove(name);     <br />    }            <br />    //中介者必d备在同事之间处理逻辑、分配Q务、促q交的操作     <br />    public abstract void execute(String name, String method);<br />   }  <br />  //具体中介?<br />  class Mediator extends AbstractMediator{<br />   //中介者最重要的功能,来回奔L与各个同事之?<br />   public void execute(String name, String method) {<br />    if("self".equals(method)){  <br />     //各自做好分内?<br />     if("ColleagueA".equals(name)) {      <br />      ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");          <br />      colleague.self();           <br />     }else {                <br />      ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");           <br />      colleague.self();         <br />     }  <br />     <br />    }else { //与其他同事合?nbsp;       <br />      if("ColleagueA".equals(name)) {     <br />       ColleagueA colleague = (ColleagueA)super.colleagues.get("ColleagueA");            <br />       colleague.out();        <br />      }else {            <br />       ColleagueB colleague = (ColleagueB)super.colleagues.get("ColleagueB");         <br />       colleague.out();        <br />      }     <br />    }  <br />   } <br />  } <br /> <br /> </p> <p><font style="background-color: #cce8cf"> //试c?<br />  public class Client {     <br />   public static void main(String[] args) {     </font></p> <p><font style="background-color: #cce8cf">  //创徏一个中介?nbsp;       <br />   AbstractMediator mediator = new Mediator();       </font></p> <p><font style="background-color: #cce8cf">  //创徏两个同事       <br />   ColleagueA colleagueA = new ColleagueA(mediator);  <br />   ColleagueB colleagueB = new ColleagueB(mediator);        </font></p> <p><font style="background-color: #cce8cf">  //中介者分别与每个同事建立联系    <br />   mediator.addColleague("ColleagueA", colleagueA);       <br />   mediator.addColleague("ColleagueB", colleagueB);    <br />   <br />   //同事们开始工?nbsp;        <br />   colleagueA.self();        <br />   colleagueA.out();    <br />   System.out.println("======================合作愉快QQ务完成!\n");   <br />   <br />   colleagueB.self();       <br />   colleagueB.out();        <br />   System.out.println("======================合作愉快QQ务完成!");  <br />   } <br />  } <br />  试l果Q?<br />  同事A --> 做好自己分内的事?...  <br />  同事A --> h同事B做好分内工作 ...  <br />  同事B --> 做好自己分内的事?...  <br />  ======================合作愉快QQ务完成! <br />  同事B --> 做好自己分内的事?...  <br />  同事B --> h同事A做好分内工作  ... <br />  同事A --> 做好自己分内的事?...<br />  ======================合作愉快QQ务完成!  </font></p> <p><font style="background-color: #cce8cf"> 虽然以上代码中只有两个具体同事类Qƈ且测试类中也只是创徏了两个同事,但是q些我们都可以根据中介者模式的宗旨q行适当地扩展,卛_加具体同事类Q然后中介者就得担负更加重的Q务了。ؓ(f)啥?我们看到上面具体中介者类Mediator中的execute()Ҏ(gu)中现在就有一堆冗长的判断代码了。虽然可以把它分解ƈ增加到MediatorcM的其它privateҎ(gu)中,但是具体的业务逻辑是少不了的?br />  <br /> 所以,在解耦同事类之间的联pȝ同时Q中介者自w也不免dq重Q因为几乎所有的业务逻辑都交代到中介者n上了Q可谓是“万众期待”的一个角色了。这是中介者模式的不之处??<br /> 此外Q上面这个代码例子是相当理想的了Q有时候我们根本抽取不?#8220;同事”之间的共性来形成一个AbstractColleague抽象同事c,q也大大增加了中介者模式的使用隑ֺ?nbsp;  </font></p> <p><font style="background-color: #cce8cf"></font></p> <p><font style="background-color: #cce8cf">׃上面代码实现中存?双向兌暴露在App?的不之?修改上面代码Q如下:(x)</font></p> <p><font style="background-color: #cce8cf"> </font></p> <p><font style="background-color: #cce8cf">修改后的同事cLQ?/font></p> <p><font style="background-color: #cce8cf"> //抽象同事c?<br />  abstract class AbstractColleague {     <br />  <br />   protected AbstractMediator mediator;    <br />   <br />   //舍去在构造函C建立起与中介者的联系 <br />   //public AbstractColleague(AbstractMediator mediator) { <br />   //      this.mediator = mediator;  <br />   //}  <br />   <br />   // 在抽象同事类中添加用于与中介者取得联p(x册)的方?nbsp;  <br />   public void setMediator(AbstractMediator mediator) {    <br />    this.mediator = mediator;    <br />   } <br />  } <br />  <br />  //具体同事A <br />  <br />   class ColleagueA extends AbstractColleague { <br />   <br />    //舍去在构造函C建立起与中介者的联系 <br />    // public ColleagueA(AbstractMediator mediator) { <br />    //  super(mediator); <br />    // }  <br />    <br />    //每个具体同事必然有自己分内的事,没必要与外界相关?nbsp;  <br />    public void self() {     <br />    System.out.println("同事A --> 做好自己分内的事?...");   <br />    } <br />    <br />    //每个具体同事L需要与外界交互的操作,通过中介者来处理q些逻辑q安排工?nbsp;     <br />    public void out() {       <br />    System.out.println("同事A --> h同事B做好分内工作 ...");     <br />    super.mediator.execute("ColleagueB", "self");  <br />    } <br />   <br />   }   <br />   <br />  //具体同事B  <br />  <br />  class ColleagueB extends AbstractColleague {   </font></p> <p><font style="background-color: #cce8cf">  //舍去在构造函C建立起与中介者的联系  <br />   // public ColleagueB(AbstractMediator mediator) {<br />   //      super(mediator);  <br />   // }      <br />   <br />   public void self() {       <br />    System.out.println("同事B --> 做好自己分内的事?...");   <br />   }  <br />   <br />   public void out() {    <br />    System.out.println("同事B --> h同事A做好分内工作  ...");     <br />    super.mediator.execute("ColleagueA", "self");    <br />   } <br />  } </font></p> <p> </p> <p><font style="background-color: #cce8cf">  修改后的中介者:(x)</font></p> <p><font style="background-color: #cce8cf">  //抽象中介?<br />   abstract class AbstractMediator {    <br />   //中介者肯定需要保持有若干同事的联pL?nbsp;   </font></p> <p><font style="background-color: #cce8cf">  protected Hashtable<String, AbstractColleague> colleagues = new Hashtable<String, AbstractColleague>();    <br />   <br />   //中介者可以动态地与某个同事徏立联p?nbsp;   <br />   public void addColleague(String name, AbstractColleague c) {  <br />    // 在中介者这里帮助具体同事徏立v于中介者的联系    <br />    c.setMediator(this);    <br />    this.colleagues.put(name, c);  <br />   }  <br />   <br />   //中介者也可以动态地撤销与某个同事的联系    <br />   public void deleteColleague(String name) {  <br />    this.colleagues.remove(name);   <br />   }  <br />         <br />   //中介者必d备在同事之间处理逻辑、分配Q务、促q交的操作  <br />   public abstract void execute(String name, String method);  <br />   } <br />   <br />   //试c?<br />   public class Client {  <br />    <br />    public static void main(String[] args) {  <br />    <br />     //创徏一个中介?nbsp;    <br />     AbstractMediator mediator = new Mediator();    <br />     <br />     //不用构造函Cؓ(f)具体同事注册中介者来取得联系?<br />     // ColleagueA colleagueA = new ColleagueA(mediator); <br />     // ColleagueB colleagueB = new ColleagueB(mediator);   <br />     <br />     ColleagueA colleagueA = new ColleagueA();  <br />     ColleagueB colleagueB = new ColleagueB();  <br />     <br />     //中介者分别与每个同事建立联系  <br />     mediator.addColleague("ColleagueA", colleagueA);  <br />     mediator.addColleague("ColleagueB", colleagueB);   <br />     <br />     //同事们开始工?nbsp;      <br />     colleagueA.self();      <br />     colleagueA.out();    <br />     System.out.println("======================合作愉快QQ务完成!\n");   <br />     <br />     colleagueB.self();        <br />     colleagueB.out();       <br />     System.out.println("======================合作愉快QQ务完成!");   <br />     <br />    } <br />   }   试之后的结果与修改前一栗?br /> </font></p> <p><br /> </font><br /> </font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331528.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 15:56 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331528.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解释器模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331527.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331527.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331527.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331527.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331527.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">Interpreter模式也叫解释器模式,是由GoF提出?3U设计模式中的一U。Interpreter是行为模式之一Q它是一U特D的设计模式Q它建立一个解释器Q对于特定的计算机程序设计语aQ用来解释预先定义的文法?br /> 本文介绍设计模式中的解释器(InterpreterQ模式的概念Q用法,以及(qing)实际应用中怎么样用Interpreter模式q行开发?/font></p> <p><font style="background-color: #cce8cf">Interpreter模式的概?/font></p> <p><font style="background-color: #cce8cf">Interpreter是一U特D的设计模式Q它建立一个解释器Q对于特定的计算机程序设计语aQ用来解释预先定义的文法。简单地_(d)Interpreter模式是一U简单的语法解释器构架?/font></p> <p><font style="background-color: #cce8cf">Interpreter模式有很多种实现Ҏ(gu)Q下面我们给出Interpreter模式的一U类图来说明Interpreter模式Q?/font></p> <p><font style="background-color: #cce8cf"></font> <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?080624104128.jpg" width="377" height="177" /></p> <p><font style="background-color: #cce8cf">在上图中Q我们假N要在Client中解释某文法QClient调用Context来存储文法规则,q调用解释器AbstractionExpressioncL(wi)来对该文法加以解释。注意,上图只是Interpreter模式的一U实现方式的cd?/font></p> <font style="background-color: #cce8cf"> <p><br /> Context<br />     解释器上下文环境cR用来存储解释器的上下文环境Q比如需要解释的文法{?br /> AbstractExpression<br />     解释器抽象类?br /> ConcreteExpression<br />     解释器具体实现类?/p> <p> </p> <p><br /> Interpreter模式的实现范?br /> Z帮助大家理解Interpreter模式的基本概念,我们在这里只举一个最单的例子?br /> 让一个表辑ּal过PlusExpression解释器处理后使该表达?1Q经qMinusExpression解释器处理后使该表达?1?/p> <p><br /> 代码Q?/p> <p>import java.util.ArrayList;<br /> import java.util.List;</p> <p>public class Client {<br />     public static void main(String []args) {<br />         String inputExpr = "10";<br />         <br />         Context context = new Context(inputExpr);<br />         <br />         List list = new ArrayList();</p> <p>        list.add(new PlusExpression());<br />         list.add(new PlusExpression());<br />         list.add(new MinusExpression());<br />         list.add(new MinusExpression());<br />         list.add(new MinusExpression());</p> <p>        for (int i=0;i<list.size();i++) {<br />           AbstractExpression expression = (AbstractExpression)list.get(i);<br />           expression.interpret(context);<br />         }<br />         <br />         System.out.println(context.getOutput());<br />     }<br /> }</p> <p><br /> /**<br /> * Context<br /> *<br /> */<br /> class Context {<br />     private String input;<br />     private int output;</p> <p>    public Context (String input) {<br />         this. input = input;<br />     }</p> <p>    public String getInput() {<br />         return input;<br />     }</p> <p>    public void setInput(String input) {<br />         this.input = input;<br />     }</p> <p>    public int getOutput() {<br />         return output;<br />     }</p> <p>    public void setOutput(int output) {<br />         this.output = output;<br />     }<br /> }</p> <p><br /> /**<br /> * Expression & subclass<br /> *<br /> */<br /> abstract class AbstractExpression {<br />     public abstract void interpret(Context context);<br /> }</p> <p>class PlusExpression extends AbstractExpression {<br />     public void interpret(Context context) {<br />         System.out.println("PlusExpression ++");<br />         String input = context.getInput();<br />         int parsedResult = Integer.parseInt(input);<br />         parsedResult ++;<br />         context.setInput(String.valueOf(parsedResult));<br />         context.setOutput(parsedResult);<br />     }<br /> }</p> <p>class MinusExpression extends AbstractExpression {<br />     public void interpret(Context context) {<br />         System.out.println("PlusExpression --");<br />         String input = context.getInput();<br />         int parsedResult = Integer.parseInt(input);<br />         parsedResult --;<br />         context.setInput(String.valueOf(parsedResult));<br />         context.setOutput(parsedResult);<br />     }<br /> }</p> <p> </p> <p>q行q显CClientQ?/p> <p>C:\Interpreter>javac *.java<br /> C:\Interpreter>java Client<br /> PlusExpression ++<br /> PlusExpression ++<br /> PlusExpression --<br /> PlusExpression --<br /> PlusExpression --<br /> 9<br /> C:\Interpreter></font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331527.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 15:40 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331527.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>命o(h)模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331526.htmlEric_jiangEric_jiangThu, 09 Sep 2010 07:29:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331526.htmlhttp://www.tkk7.com/jjshcc/comments/331526.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331526.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331526.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331526.html1.q一节我们的d是创Z个类似智能家居的万能遥控器,控制各种家电(sh)。我们需要将“h”装成对象(一个命令对象通过在特定接收者上l定一l动作来装hQ,以便使用不同的请求、队列、或者日志来参数化其对象——这是命o(h)模式?/font>

2.我们具体来看一个例子:(x)

首先我们要完成对命o(h)的对象封装:(x)

public interface Command {
    public void execute();
}

只有一个方法,所有的具体命o(h)的对象都要实现这个接口,q就做到了封装,比如对于灯这个对象,

public class Light {

    public Light() {
    }

    public void on() {
        System.out.println("Light is on");
    }

    public void off() {
        System.out.println("Light is off");
    }
}

我们可以通过上述接口装“开?#8221;q个命o(h)Q这个就是所谓的命o(h)对象Q它把动作和接收者包q对象之中,只暴露一个executeҎ(gu)Q?/font>

public class LightOnCommand implements Command {
    Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
}

而我们的遥控器对于上q封装要一无所知,q样才能做到解耦:(x)

public class SimpleRemoteControl {
    Command slot;
    public SimpleRemoteControl() {}
    public void setCommand(Command command) {
        slot = command;
    }
    public void buttonWasPressed() {
        slot.execute();
    }
}

我们现在试着用一下这个遥控器Q我们首先创Z个遥控器Q然后创建开灯这个命令ƈ|于其中Q最后按下按键,q样Q遥控器不知道是哪个对象Q实际上是灯Q进行了哪个动作Q实际上是开灯这个动作)可以完成请求的发出。如此一来,遥控器和灯之间的耦合性就非常低了Q?/font>

public class RemoteControlTest {
    public static void main(String[] args) {
        SimpleRemoteControl remote = new SimpleRemoteControl();
        Light light = new Light();
        LightOnCommand lightOn = new LightOnCommand(light);
        remote.setCommand(lightOn);
        remote.buttonWasPressed();
        }
}

很简单的Q我们想要在一个遥控机中实现控制多个家늚能力可以用一个数l来l护q样的一l命令,可以看做提供了多个命令的插槽Q?/font>

public class RemoteControl {
    Command[] onCommands;
    Command[] offCommands;
    public RemoteControl() {
        onCommands = new Command[7];
        offCommands = new Command[7];
        Command noCommand = new NoCommand();
        for (int i = 0; i < 7; i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
    }
    public void setCommand(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
    }
    public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
    }
    public String toString() {
    }
}

你可能会(x)注意C个叫做noCommand的对象出现在初始化遥控器对象时。这个是个小技巧,我们q不xơ都查某个插槽是不是都绑定了命o(h)Q那么我们就引入了这个东东,实现一个不做事情的命o(h)Q?/font>

public class NoCommand implements Command {
    public void execute() { }
}

q样初始化就让每一个插槽都有命令了Q以后若不进一步指明命令的插槽Q那么就是默认这个noCommand对象。这是一个典型的“I对?#8221;例子Q当你不惌回一个有意义的对象时Q空对象十分有用,此时I对象可以做成判断NULL或者提C?#8220;未绑?#8221;信息的工作?/font>

3.我们在命令模式中也可以设|类似undo的撤销命o(h)来撤销发出的命令请求:(x)

public interface Command {
    public void execute();
    public void undo();
}

我们q是拿开늁q个操作来说明,毕竟q够简单:(x)对于一个开灯命令,其对应的撤销命o(h)自然?#8220;关电(sh)?#8221;Q?/font>

public class LightOnCommand implements Command {
    Light light;
    public LightOnCommand(Light light) {
        this.light = light;
    }
    public void execute() {
        light.on();
    }
    public void undo() {
        light.off();
    }
}

虽然q简单之极,q还没完Q我们必让遥控器记住上ơ到底做了什么操作,才可能去撤销Q?/font>

package headfirst.command.undo;

import java.util.*;

//
// This is the invoker
//
public class RemoteControlWithUndo {
    Command[] onCommands;
    Command[] offCommands;
    Command undoCommand;
    public RemoteControlWithUndo() {
        onCommands = new Command[7];
        offCommands = new Command[7];
        Command noCommand = new NoCommand();
        for(int i=0;i<7;i++) {
            onCommands[i] = noCommand;
            offCommands[i] = noCommand;
        }
        undoCommand = noCommand;
    }
    public void setCommand(int slot, Command onCommand, Command offCommand) {
        onCommands[slot] = onCommand;
        offCommands[slot] = offCommand;
    }
    public void onButtonWasPushed(int slot) {
        onCommands[slot].execute();
        undoCommand = onCommands[slot];//记录操作动作
    }
    public void offButtonWasPushed(int slot) {
        offCommands[slot].execute();
        undoCommand = offCommands[slot];//记录操作动作
    }
    public void undoButtonWasPushed() {
        undoCommand.undo();//发出撤销命o(h)
    }
    public String toString() {
    }
}

对于늁Q我们只有两U状态,但是要是多个状态呢Q我们D一个吊扇的例子Q吊扇有多个转速,高中低关Q四个状态:(x)

public class CeilingFan {
    String location = "";
    int level;
    public static final int HIGH = 2;
    public static final int MEDIUM = 1;
    public static final int LOW = 0;
    public CeilingFan(String location) {
        this.location = location;
    }
    public void high() {
        // turns the ceiling fan on to high
        level = HIGH;
        System.out.println(location + " ceiling fan is on high");
    }

    public void medium() {
        // turns the ceiling fan on to medium
        level = MEDIUM;
        System.out.println(location + " ceiling fan is on medium");
    }

    public void low() {
        // turns the ceiling fan on to low
        level = LOW;
        System.out.println(location + " ceiling fan is on low");
    }
    public void off() {
        // turns the ceiling fan off
        level = 0;
        System.out.println(location + " ceiling fan is off");
    }
    public int getSpeed() {
        return level;
    }
}

那么在实现风扇各个{速命令时Q就要去记录在执行这个命令前风扇的{速,其撤销命o(h)中则Ҏ(gu)记录的部分完成undo操作?/font>

public class CeilingFanHighCommand implements Command {
    CeilingFan ceilingFan;
    int prevSpeed;

    public CeilingFanHighCommand(CeilingFan ceilingFan) {
        this.ceilingFan = ceilingFan;
    }
    public void execute() {
        prevSpeed = ceilingFan.getSpeed();
        ceilingFan.high();
    }
    public void undo() {
        switch (prevSpeed) {
            case CeilingFan.HIGH:     ceilingFan.high(); break;
            case CeilingFan.MEDIUM: ceilingFan.medium(); break;
            case CeilingFan.LOW:     ceilingFan.low(); break;
            default:                 ceilingFan.off(); break;
        }
    }
}

当然你也可以实现诸如多个命o(h)扚w执行和完成多个撤销操作?/font>

命o(h)模式可以用于工作队列和日志操作等斚w?/font>

 

 



Eric_jiang 2010-09-09 15:29 发表评论
]]>
责Q链模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331514.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331514.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331514.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331514.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331514.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf"></font> </p> <p><font style="background-color: #cce8cf"> 昄Q击鼓传q合责任链模式的定义。参加游戏的人是一个个的具体处理者对象,击鼓的h便是客户端对象。花代表酒o(h)Q是传向处理者的hQ每一个参加游戏的人在接到传来的花Ӟ可选择的行为只有两个:(x)一是将花向下传Q一是执行酒?--喝酒。一个h不能既执行酒令,又向下家传花Q当某一个h执行了酒令之后,游戏重新开始。击鼓的人ƈ不知道最l是由哪一个做游戏的h执行酒o(h)Q当然执行酒令的人必然是做游戏的Z中的一个?/font></p> <p><font style="background-color: #cce8cf">  击鼓传花的类囄构如下:(x)</font></p> <p><font style="background-color: #cce8cf"></font> <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?jt-2002-4-15-flowerpassing0.gif" width="339" height="239" /></p> <p><font style="background-color: #cce8cf">?、击鼓传ql的cd定义?/font></p> <p><font style="background-color: #cce8cf">  单独考虑击鼓传花pȝQ那么像贾母、贾赦、贾ѝ贾宝玉和贾环等传花者均应当?#8220;具体传花?#8221;的对象,而不应当是单独的c;但是责Q链模式往往是徏立在现有pȝ的基之上的,因此铄l构和组成不p任链模式本n军_?/font></p> <font style="background-color: #cce8cf"> <p><br />   pȝ的分?br />   在《红楼梦》第七十五回里生动地描述了贾府里的一场击鼓传花游戏:(x)“贾母坐下Q左垂首贾Q贾珍,贄Q贾蓉,叛_首贾政,宝玉Q贾环,贑օQ团团围坐?..贾母便命折一枝桂花来Q命一媛_在屏后击鼓传花。若花到谁手中,饮酒一?..于是先从贾母Pơ贾赦,一一接过。鼓C转,恰恰在贾政手中住了,只得饮了酒?#8221;q场游戏接着又把׃C宝玉和贾赦手里,接着又传C在贾环手?..</p> <p><br />   如果用一个对象系l描q贾府,那么贾母、贾赦、贾ѝ贾宝玉和贾环等{就应当分别׃个个具体cM表,而这场击鼓传花游戏的cdQ按照责任链模式Q应当如下图所C:(x)</p> <p> <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?jt-2002-4-15-flowerpassing2.gif" width="583" height="305" /><br /> </p> <p></font> <font style="background-color: #cce8cf">?、红楼梦中的击鼓传花游戏的示意性类图?<br />  换言之,在击鼓传花游戏里面,有下面的几种角色Q?br />  抽象传花者,或Handler角色、定义出参加游戏的传׃h要遵守的规则Q也是一个处理请求的接口 和对下家的引用;<br />  具体传花者,或ConcreteHandler角色、每一个传p都知道下家是谁Q要么执行酒令,要么把花 向下传。这个角色由贾母、贾赦、贾珍、贾琏、贾蓉、贾ѝ宝玉、贾环、贾兰等扮演。 击鼓人,或Client角色、即行酒令的击鼓之h。《红楼梦》没有给出此人的具体姓名Q只是说?#8220;一 媛_”扮演?/font><br /> <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?jt-2002-4-15-flowerpassing3.gif" width="522" height="184" /><br /> </p> <p><font style="background-color: #cce8cf">?、贾府这ơ击鼓传qC意性对象图?</font></p> <p><font style="background-color: #cce8cf">  可以看出Q击鼓传花游戏满任链模式的定义,是纯的责任链模式的例?<br /> Javapȝ的解下面的类囄Zq些cȝ具体接口设计。读者不隄出,DrumBeaterQ击鼓者)、PlayerQ传p)、JiaMuQ贾母)、JiaSheQ贾赦)、JiaZhengQ贾政)、JiaBaoYuQ宝玉)、JiaHuanQ贾环){组成这个系l?br /> </font></p> <p><br /> <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?jt-2002-4-15-flowerpassing.gif" width="520" height="412" /><br /> </p> <p><font style="background-color: #cce8cf">?、击鼓传qcd完全W合责Q链模式的定义?</font></p> <p><font style="background-color: #cce8cf">  下面是客L(fng)cDrumBeater的源代码Q?/font></p> <p><font style="background-color: #cce8cf"> //DrumBeater的源代码<br />  public class DrumBeater <br />  {<br />    private static Player player;<br />    static public void main(String[] args) <br />     { <br />      player = new JiaMu( new JiaShe( new JiaZheng( new JiaBaoYu(new JiaHuan(null))))); <br />      player.handle(4);<br />     } <br />  }  </font></p> <p><font style="background-color: #cce8cf"> //抽象传花者Playcȝ源代?br />  abstract class Player <br />  {<br />   abstract public void handle(int i);<br />   private  Player successor; <br />   public   Player() { successor = null;}</font></p> <p><font style="background-color: #cce8cf">  protected void setSuccessor(Player aSuccessor) <br />   {<br />     successor = aSuccessor;<br />   }</font></p> <p><font style="background-color: #cce8cf">  public void next(int index)<br />   { <br />     if( successor != null ) <br />      { <br />       successor.handle(index);<br />      }<br />     else <br />      { <br />       System.out.println("Program terminated."); <br />      }<br />     }<br />   }  <br />  }<br />   </font></p> <p><font style="background-color: #cce8cf">  抽象cPlayerl出了两个方法的实现Q以格式setSuccessor()Q另一个是next()。前者用来设|一个传p对象的下家Q后者用来将酒o(h)传给下家。PlayercȝZ一个抽象方法handle()Q代表执行酒令?/font></p> <p><font style="background-color: #cce8cf">  下面的这些具体传p类给出handle()Ҏ(gu)的实现?/font></p> <p><font style="background-color: #cce8cf"> //贾母的JiaMuc?br />  class JiaMu extends Player <br />  {<br />     public JiaMu(Player aSuccessor)<br />     { <br />      this.setSuccessor(aSuccessor);<br />     }<br />     public void handle(int i)<br />     { <br />      if( i == 1 )<br />      { <br />       System.out.println("Jia Mu gotta drink!"); <br />      }<br />      else<br />      { <br />     System.out.println("Jia Mu passed!");<br />     next(i);<br />      }<br />     }<br />  }  </font></p> <p><font style="background-color: #cce8cf">  <br />    //贾的JiaShec?br />    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 />   }  </font></p> <p><font style="background-color: #cce8cf">   <br />    //贾政的JiaZhengc?br />    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 />   }  </font></p> <p><font style="background-color: #cce8cf">  <br />  //贑֮玉的JiaBaoYuc?br />    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 />   }  </font></p> <p><font style="background-color: #cce8cf">   <br />  //JiaHuanc?br />  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 />   }  </font></p> <p><font style="background-color: #cce8cf"> </font></p> <p><font style="background-color: #cce8cf">  可以看出QDrumBeater讑֮了责任链的成员和他们的顺序:(x)责Q铄贾母开始到贄Q周而复始。JiaMucRJiaShecRJiaZhengcRJiaBaoYucMJiaHuancd是抽象传pPlayercȝ子类?/font></p> <p><font style="background-color: #cce8cf">  本节所实现的DrumBeatercd把请求传l贾母时Q实际上指定了由4号传p处理酒令。虽然DrumBeaterq不知道哪一个传p类持有L(fng)4Q但是这个号码在本系l一开始就写死的。这当然q不W合击鼓传花游戏的精,因ؓ(f)q个游戏实际上要求有两个同时q行的过E:(x)击鼓q程和传pE。击鼓应当是定时停止的,当击鼓停止时Q执行酒令者就定了。但是本节这样做可以佉K题得到简化ƈ读者的_֊攑֜责Q链模式上Q而不是两个过E的处理上?br />  <br /> 在什么情况下使用责Q链模?/font></p> <p><font style="background-color: #cce8cf">  在下面的情况下用责任链模式Q?/font></p> <p><font style="background-color: #cce8cf">  W一、系l已l有一个由处理者对象组成的链。这个链可能由复合模式给出,</font></p> <p><font style="background-color: #cce8cf">  W一、当有多于一个的处理者对象会(x)处理一个请求,而且在事先ƈ不知道到底由哪一个处理者对象处理一个请求。这个处理者对象是动态确定的?/font></p> <p><font style="background-color: #cce8cf">  W二、当pȝ惛_Z个请求给多个处理者对象中的某一个,但是不明显指定是哪一个处理者对象会(x)处理此请求?/font></p> <p><font style="background-color: #cce8cf">  W三、当处理一个请求的处理者对象集合需要动态地指定时?/font></p> <p><font style="background-color: #cce8cf">  使用责Q链模式的长处和短?/font></p> <p><font style="background-color: #cce8cf">  责Q链模式减低了发出命o(h)的对象和处理命o(h)的对象之间的耦合Q它允许多与一个的处理者对象根据自q逻辑来决定哪一个处理者最l处理这个命令。换a之,发出命o(h)的对象只是把命o(h)传给铄构的起始者,而不需要知道到底是链上的哪一个节点处理了q个命o(h)?/font></p> <p><font style="background-color: #cce8cf">  昄Q这意味着在处理命令上Q允许系l有更多的灵zL。哪一个对象最l处理一个命令可以因为由那些对象参加责Q链、以?qing)这些对象在责Q链上的位|不同而有所不同?/font></p> <p><font style="background-color: #cce8cf">  责Q链模式的实现</font></p> <p><font style="background-color: #cce8cf">  铄构的由来</font></p> <p><font style="background-color: #cce8cf">  值得指出的是Q责任链模式q不创徏任链。责任链的创建必Lpȝ的其它部分完成?/font></p> <p><font style="background-color: #cce8cf">  责Q链模式减低了h的发送端和接收端之间的耦合Q多个对象都有Z(x)处理q个h。一个链可以是一条线Q一个树(wi)Q也可以是一个环。链的拓扑结构可以是单连通的或多q通的Q责任链模式q不指定责Q铄拓扑l构。但是责任链模式要求在同一个时间里Q命令只可以被传l一个下Ӟ或被处理掉)Q而不可以传给多于一个下家。在下面的图中,责Q链是一个树(wi)l构的一部分?/font></p> <p><font style="background-color: #cce8cf"> <img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?jt-2002-4-15-tree.gif" width="482" height="221" /></font></p> <p><font style="background-color: #cce8cf">?、责任链是系l已有的?wi)结构的一部分。图中有阴媄的对象给Z一个可能的命o(h)传播路径?/font></p> <p><font style="background-color: #cce8cf">  责Q铄成员往往是一个更大的l构的一部分。比如在前面所讨论的《红楼梦》中击鼓传花的游戏中Q所有的成员都是贑ֺ的成员。如果责任链的成员不存在Q那么ؓ(f)了用责任链模式Q就必须创徏它们Q责任链的具体处理者对象可以是同一个具体处理者类的实例?/font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331514.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 14:44 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331514.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SingletonQ单态)模式 ?Double-Checked LockingQ双重检查锁定)模式 http://www.tkk7.com/jjshcc/archive/2010/09/09/331511.htmlEric_jiangEric_jiangThu, 09 Sep 2010 06:21:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331511.htmlhttp://www.tkk7.com/jjshcc/comments/331511.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331511.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331511.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331511.html保一个特定的cd有一个对象被实例化?/font>

SingletonQ用于单U程应用E序
public class Singleton {

  private Singleton(){}

  //在自己内部定义自׃个实例,是不是很奇怪?
  //注意q是private 只供内部调用

  private static Singleton instance = new Singleton();

  //q里提供了一个供外部讉K本class的静态方法,可以直接讉K  
  public static Singleton getInstance() {
    return instance;   
   }

 

Double-Checked LockingQ用于多U程应用E序

public class Singleton {
  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

  //q个Ҏ(gu)比上面有所改进Q不用每ơ都q行生成对象Q只是第一ơ     
  //使用时生成实例,提高了效率!
  if (instance==null)
    instanceQnew Singleton();
  return instance;   }
}
 



Eric_jiang 2010-09-09 14:21 发表评论
]]>
原型模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331509.htmlEric_jiangEric_jiangThu, 09 Sep 2010 06:13:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331509.htmlhttp://www.tkk7.com/jjshcc/comments/331509.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331509.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331509.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331509.html原型模式QPrototypeQ属于创建型模式Q实C对象的创建;具体而言Q它实现了对象的复制Q拷贝)?/font>

关于对象的复Ӟ我们需要考虑以下两个问题Q?/font>

1.对象实时状态的复制Q?/font>

2.对象引用成员变量的复制?/font>

如果通过new方式来实例化对象Q只能得到对象的初始状态,q显然不行。在Java中,所有类都承于Objectc,而Object有一个clone()Ҏ(gu)。通过查看JDK文Q该clone()Ҏ(gu)虽然能够实现实时状态的复制Q解决了问题1Q,但是只能实现“拷?#8221;Q即只能实现基本数据cdQ包含StringQ的拯Q不能实现引用数据类型的拯Qƈ不能满原型模式的要求(问题2不能得到解决Q?/font>


怎么办?重写cȝclone()Ҏ(gu)Q通过对象的写入写出来实现“深拷?#8221;和实时状态复制。重写(OverrideQ需要遵循的条g是:(x)Ҏ(gu)名,参数列表和父cM_(d)q回值是父类q回值的子类。重写cloneҎ(gu)完全满了条件。(无参敎ͼҎ(gu)名一_(d)q回的所有类都是Object的子c;当然可以不重写,Ҏ(gu)名改用其它,但是不徏议。)

可以惌Q若一个类含有若干个引用数据类型(c)Q而该引用数据cdQ类Q中又含有若q个引用数据cd…q样嵌套下去Q需要复制的׃是一个类Q而是一?#8220;cL(wi)”Q树(wi)l构Q。Java通过对象序列化到文件或内存Q底层封装了对类?wi)的遍历和复制过E。这个机制已l封装,我们无需了解?/p>

考虑q样一个应用场景:(x)

一个RPG游戏Q英雄类含有两个成员变量Q一个是英雄名字Qؓ(f)普通成员变量;一个是英雄属性,为引用成员变量(装了英雄的状态,如生命倹{魔法|。ؓ(f)了实现对象实时拷贝的高效率,我们选择对象序列化到内存(不是文gQ硬盘)Q。通过输入输出实现对象的“深拷?#8221;?/p>

具体的实C码如下:(x)


package com.csufox.Prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

class Property implements java.io.Serializable{
    int blood = 100;  //生命?br />     int magic = 100;  //法?br /> }

class Hero implements java.io.Serializable{ //需要实现序列化接口
    String name = "英雄";
    Property property = new Property(); //含有引用成员Q需?#8220;?#8221;拯

    public Hero clone(){
        Hero copy = null;
        try{
            //实例化ObjectOutputStreamQ写入字节数l输出流
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(this);
            byte[] data = baos.toByteArray();  //data是字节数l,存储着对象的拷?/p>


            //实例化ObjectInputStreamQ从字节数组输入中d对象
            ByteArrayInputStream bais = new ByteArrayInputStream(data);
            ObjectInputStream ois = new ObjectInputStream(bais);
            copy = (Hero)ois.readObject();
        }catch(Exception ex){ex.printStackTrace();}
        return copy;
    }
}

public class Prototype {
    public static void main(String[] args) throws Exception {
        Hero hero = new Hero();
        hero.property.blood -= 20;  //原英雄状态发生改变,生命值减?0
        Hero copy = hero.clone();
        System.out.println(copy.property.blood);  //输出“80”Q说明实C实时拯和深拯
    }
}
 

׃qC码可知,原型模式h以下特点Q?/p>

实现Serializable序列化接口;
在类中重写clone()Ҏ(gu)Q由O(jin)bjectl承而来Q;
通过Java I/0Q将对象写入内存Q然后再从内存读取(反序列化Q?



Eric_jiang 2010-09-09 14:13 发表评论
]]>
建造者模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331506.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331506.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331506.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331506.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331506.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">Builder模式定义:<br /> 一个复杂对象的构徏与它的表C分?使得同样的构E可以创Z同的表示.</font></p> <p><font style="background-color: #cce8cf">Builder模式是一步一步创Z个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容可以构建它?用户不知道内部的具体构徏l节.Builder模式是非常类似抽象工厂模?l微的区别大概只有在反复使用中才能体?x)?</font></p> <p><font style="background-color: #cce8cf">Z使用?<br /> 是ؓ(f)了将构徏复杂对象的过E和它的部g解?注意: 是解耦过E和部g.</font></p> <p><font style="background-color: #cce8cf">因ؓ(f)一个复杂的对象,不但有很多大量组成部?如汽?有很多部?车轮 方向?发动有各U小零g{等,部g很多,但远不止q些,如何这些部件装配成一辆汽?q个装配q程也很复杂(需要很好的l装技?,Builder模式是Z部件和l装q程分开.</font></p> <p><font style="background-color: #cce8cf">如何使用?<br /> 首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部g的创建分别开?分别用BuildercdDirectorcL表示.</font></p> <p><font style="background-color: #cce8cf">首先,需要一个接?它定义如何创建复杂对象的各个部g:<br />   <br /> public interface Builder { </font></p> <p><font style="background-color: #cce8cf">  //创徏部gA  比如创徏汽R车轮<br />   void buildPartA(); <br />   //创徏部gB 比如创徏汽R方向?br />   void buildPartB(); <br />   //创徏部gC 比如创徏汽R发动?br />   void buildPartC(); </font></p> <p><font style="background-color: #cce8cf">  //q回最后组装成品结?(q回最后装配好的汽?<br />   //成品的组装过E不在这里进?而是转移C面的DirectorcMq行.<br />   //从而实C解耦过E和部g<br />   Product getResult(); </font></p> <p><font style="background-color: #cce8cf">} <br />  </font></p> <p><font style="background-color: #cce8cf">用Director构徏最后的复杂对象,而在上面Builder接口中封装的是如何创Z个个部g(复杂对象是由q些部gl成?,也就是说Director的内Ҏ(gu)如何部件最后组装成成品:<br />    <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 />   //q里是将车轮 方向盘和发动机组装成汽R的过E?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">} <br />  </font></p> <p><font style="background-color: #cce8cf">Builder的具体实现ConcreteBuilder:<br /> 通过具体完成接口Builder来构建或装配产品的部?<br /> 定义q明它所要创建的是什么具体东?<br /> 提供一个可以重新获取品的接口:</font></p> <p><font style="background-color: #cce8cf"> <br /> public class ConcreteBuilder implements Builder { </font></p> <p><font style="background-color: #cce8cf">  Part partA, partB, partC; <br />   public void buildPartA() {<br />     //q里是具体如何构建partA的代?/font></p> <p><font style="background-color: #cce8cf">  }; <br />   public void buildPartB() { <br />     //q里是具体如何构建partB的代?br />   }; <br />    public void buildPartC() { <br />     //q里是具体如何构建partB的代?br />   }; <br />    public Product getResult() { <br />     //q回最后组装成品结?br />   }; </font></p> <font style="background-color: #cce8cf"> <p><br /> }<br />  </p> <p>复杂对象:产品Product:</p> <p>public interface Product { }  </p> <p><br /> 复杂对象的部?</p> <p>public interface Part { } </p> <p> </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实际使用?我们l常用到"?(Pool)的概?当资源提供者无法提供够的资源,q且q些资源需要被很多用户反复׃n?需要用池.</p> <p>"?实际是一D内?当池中有一些复杂的资源?断肢"(比如数据库的q接?也许有时一个连接会(x)中断),如果循环再利用这?断肢",提高内存用效?提高池的性能.修改Builder模式中DirectorcM之能诊断"断肢"断在哪个部g?再修复这个部?</p> <p> </p> <p> </font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 13:58 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>工厂Ҏ(gu)设计模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331496.htmlEric_jiangEric_jiangThu, 09 Sep 2010 04:08:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331496.htmlhttp://www.tkk7.com/jjshcc/comments/331496.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331496.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331496.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331496.html在设计模式中,Factory Method也是比较单的一?但应用非常广?EJB,RMI,COM,CORBA,Swing中都可以看到此模式的影子,它是最重要的模式之一.在很多地Ҏ(gu)们都?x)看到xxxFactoryq样命名的类,那么,什么是Factory Method,Z么要用这个模?如何用Java语言来实现该模式,q就是本文想要带l大家的内容.
基本概念

FactoryMethod是一U创建性模?它定义了一个创建对象的接口,但是却让子类来决定具体实例化哪一个类.当一个类无法预料要创建哪U类的对象或是一个类需要由子类来指定创建的对象时我们就需要用到Factory Method 模式?单说?Factory Method可以Ҏ(gu)不同的条件生不同的实例,当然q些不同的实例通常是属于相同的cd,h共同的父c?Factory Method把创些实例的具体q程装h?化了客户端的应用,也改善了E序的扩展?使得来可以做最的改动可以加入新的待创徏的类. 通常我们Factory Method作ؓ(f)一U标准的创徏对象的方?当发现需要更多的灉|性的时?开始考虑向其它创建型模式转化

 

单分?/p>

?是Factory Method 模式的结构图,q里提供了一些术?让我们可以进行更方便的描q?


Product: 需要创建的产品的抽象类.
ConcreteProduct: Product的子c?一pd具体的?
Creator: 抽象创徏器接?声明q回Productcd对象的Factory Method.
ConcreteCreator: 具体的创建器,重写C(j)reator中的Factory Method,q回ConcreteProductcd的实?

?: Factory Method 模式l构
 

由此可以清楚的看L(fng)q对应关系: Product <====> Creator ; ConreteProduct <====> ConreteCreator

抽象产品对应抽象创徏?具体产品对应具体创徏?q样做的好处是什么呢?Z么我们不直接用具体的产品和具体的创徏器完成需求呢?实际上我们也可以q样?但通过Factory Method模式来完?客户(client)只需引用抽象的Product和Creater,对具体的ConcreteProduct和ConcreteCreator可以毫不兛_,q样做我们可以获得额外的好处:

首先客户端可以统一从抽象创建器获取产生的实?Creator的作用将client和品创E分d?客户不用操心q回的是那一个具体的产品,也不用关心这些品是如何创徏?同时,ConcreteProduct也被隐藏在Product后面,ConreteProductl承了Product的所有属?q实CProduct中定义的抽象Ҏ(gu),按照Java中的对象造型(cast)原则,通过ConcreteCreator产生的ConcreteProduct可以自动的上溯造型成Product.q样一?实质内容不同的ConcreteProduct可以在形式上统一为Product,通过Creator提供lclient来访?
其次,当我们添加一个新的ConcreteCreator?׃Creator所提供的接口不?客户端程序不?x)有丝毫的改?不会(x)带来动一发而牵全n的灾? q就是良好封装性的体现.但如果直接用ConcreteProduct和ConcreteCreator两个cL无论如何也做不到q点? 优良的面向对象设计鼓׃用封?encapsulation)和委?delegation),而Factory Method模式是使用了封装和委托的典型例?q里装是通过抽象创徏器Creator来体现的,而委托则是通过抽象创徏器把创徏对象的责d全交l具体创建器ConcreteCreator来体现的.
现在,请再回头看看基本概念中的那段?开始也许觉得生涩难?现在是不是已l明朗化了很?

下面让我们看看在 Java 中如何实现Factory Method模式,q一步加深对它的认识.

 

具体实施

先说明一?用Factory Method模式创徏对象q不一定会(x)让我们的代码更短,实事上往往更长,我们也用了更多的类,真正的目的在于这样可以灵zȝ,有弹性的创徏不确定的对象.而且,代码的可重用性提高了,客户端的应用化了,客户E序的代码会(x)大大减少,变的更具可读?

标准实现: q里我采用Bruce Eckel 用来描述OO思想的经怾?Shape.q样大家?x)比较熟?zhn)一?我完全按照图1中所定义的结构写了下面的一D|CZ?q段代码的作用是创徏不同的Shape实例,每个实例完成两个操作:draw和erase.具体的创E委托ShapeFactory来完?
1.a 首先定义一个抽象类Shape,定义两个抽象的方?

abstract class Shape {
  // 勄shape
  public abstract void draw();
  // 擦去 shape
  public abstract void erase();
  public String name;
  public Shape(String aName){
    name = aName;
  }
}


1.b 定义 Shape的两个子c? Circle, Square,实现Shape中定义的抽象Ҏ(gu)

// 圆Ş子类
class Circle extends Shape {
  public void draw() {
    System.out.println("It will draw a circle.");
  }
  public void erase() {
    System.out.println("It will erase a circle.");
  }
  // 构造函?br />   public Circle(String aName){
    super(aName);
  }
}
// 方Ş子类
class Square extends Shape {
  public void draw() {
    System.out.println("It will draw a square.");
  }
  public void erase() {
    System.out.println("It will erase a square.");
  }
  // 构造函?br />   public Square(String aName){
    super(aName);
  }
}
 


1.c 定义抽象的创建器,anOperation调用factoryMethod创徏一个对?q对该对象进行一pd操作.

abstract class ShapeFactory { 
  protected abstract Shape factoryMethod(String aName);
  // 在anOperation中定义Shape的一pd行ؓ(f)
public void anOperation(String aName){
    Shape s = factoryMethod(aName);
    System.out.println("The current shape is: " + s.name);
    s.draw();
    s.erase();
  }
}


1.d 定义与circle和square相对应的两个具体创徏器CircleFactory,SquareFactory,实现父类的methodFactoryҎ(gu)

// 定义q回 circle 实例?CircleFactory
class CircleFactory extends ShapeFactory {
  // 重蝲factoryMethodҎ(gu),q回Circle对象
  protected Shape factoryMethod(String aName) {
    return new Circle(aName + " (created by CircleFactory)");
  }
}
 
// 定义q回 Square 实例?SquareFactory
class SquareFactory extends ShapeFactory {
  // 重蝲factoryMethodҎ(gu),q回Square对象
protected Shape factoryMethod(String aName) {
    return new Square(aName + " (created by SquareFactory)");
  }
}
 


1.e 试c?h意这个客L(fng)E序多么z?既没有罗嗦的条g判断语句,也无需兛_ConcreteProduct和ConcreteCreator的细?因ؓ(f)q里我用anOperation装了Product里的两个Ҏ(gu),所以连Product的媄子也没看?当然把Product里方法的具体调用攑ֈ客户E序中也是不错的).

class Main {
  public static void main(String[] args){
    ShapeFactory sf1 = new SquareFactory();
    ShapeFactory sf2 = new CircleFactory();
    sf1.anOperation("Shape one");
    sf2.anOperation("Shape two");
  }

 


q行l果如下:

The current shape is: Shape one (created by SquareFactory)

It will draw a square.

It will erase a square.

The current shape is: Shape two (created by CircleFactory)

It will draw a circle.

It will erase a circle.

参数化的Factory Method: q种方式依靠指定的参C为标志来创徏对应的实?q是很常见的一U办?比如JFC中的BorderFactory是个很不错的例? 以下的这个例子是用字W串作ؓ(f)标记来进行判断的,如果参数的类型也不一?那就可以用到q蝲函数来解册个问?定义一pd参数和方法体不同的同名函?q里java.util.Calendar.getInstance()又是个极好的例子.参数化的创徏方式克服了Factory Method模式一个最显著的缺?是当具体品比较多?我们不得不也建立一pd与之对应的具体构造器. 但是在客L(fng)我们必须指定参数来决定要创徏哪一个类.
2.a 我们在第一U方法的基础上进行修?首先自定义一个的异常,q样当传入不正确的参数时可以得到更明昄报错信息.

class NoThisShape extends Exception {
  public NoThisShape(String aName) {
    super(aName);
  }
}
 


2.bL了ShapeFactory的两个子c?改ؓ(f)由ShapeFactory直接负责实例的创? ShapeFactory自己变成一个具体的创徏?直接用参数化的方法实现factoryMethodq回多种对象.

abstract class ShapeFactory { 
  private static Shape s;
  private ShapeFactory() {}
   
  static Shape factoryMethod(String aName, String aType) throws NoThisShape{
    if (aType.compareTo("square")==0)
      return new Square(aName);
    else if (aType.compareTo("circle")==0)
      return new Circle(aName);
    else throw new NoThisShape(aType); 
  }
 
  // 在anOperation中定义Shape的一pd行ؓ(f)
  static void anOperation(String aName, String aType) throws NoThisShape{
    s = factoryMethod(aName, aType);
    System.out.println("The current shape is: " + s.name);
    s.draw();
    s.erase();
  }
}
 


2.c 试c?q里客户端必L定参数来军_具体创徏哪个c?q个例子里的anOperation是静态函?可以直接引用.

class Main {
  public static void main(String[] args) throws NoThisShape{
    ShapeFactory.anOperation("Shape one","circle");
    ShapeFactory.anOperation("Shape two","square");
    ShapeFactory.anOperation("Shape three", "delta");
  }
}
 


q行l果如下:

The current shape is: Shape one
It will draw a circle.
It will erase a circle.
The current shape is: Shape two
It will draw a square.
It will erase a square.
Exception in thread "main" NoThisShape: delta
        at ShapeFactory.factoryMethod(ShapeFactory.java:10)
        at ShapeFactory.anOperation(ShapeFactory.java:15)
        at Main.main(Main.java:5)
 


动态装载机?
有的时候我们会(x)把ConcreteProduct的实例传l创建器作ؓ(f)参数,q种情况?如果在创建器里完成创E?必d断参数的具体cd(用instanceof),然后才能产生相应的实?那么比较好的做法是利用Java的动态装载机制来完成qg?比如:

我们得到一个Shape的子cs,但不知道具体是那个子c?可以利用Classc自带的Ҏ(gu)newInstance()得到实例

return (Shape)s.getClass().newInstance();

q种Ҏ(gu)有兴得读者可以自己尝?限于幅,不写具体代码出来?

 

 


 回页?
 

 

后话:

看完q篇文章?怿读者对Factory Method模式有一个比较清楚的了解?我想说的?我们不仅应该兛_一个具体的模式有什么作?如何d现这个模?更应该透过现象看本?不但知其?q要知其所以然.要通过Ҏ(gu)式的学习(fn)加深寚w向对象思想的理?让自q认识得到升华.Factory Method模式看似?实则深刻.抽象,装,l承,委托,多?针对接口~程{面向对象中的概念都在这里得C一一的体?只有抓住了它的本?我们才能够不拘于形式的灵z运?而不是ؓ(f)了用模式而用模?



Eric_jiang 2010-09-09 12:08 发表评论
]]>
代理模式Q静态代理和动态代理)http://www.tkk7.com/jjshcc/archive/2010/09/09/331488.htmlEric_jiangEric_jiangThu, 09 Sep 2010 03:47:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331488.htmlhttp://www.tkk7.com/jjshcc/comments/331488.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331488.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331488.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331488.html

一?Proxy模式定义:
为其他对象提供一U代理以控制q个对象的访问?br /> 二?模式解说
Proxy代理模式是一U结构型设计模式Q主要解决的问题是:(x)在直接访问对象时带来的问题,比如_(d)(x)要访问的对象在远E的机器上。在面向对象pȝ中,有些对象׃某些原因Q比如对象创建开销很大Q或者某些操作需要安全控Ӟ或者需要进E外的访问)Q直接访问会(x)l用者或者系l结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的讉K?q个讉K层也叫代理。Proxy模式是最常见的模式,在我们生zM处处可见Q例如我们买火R不一定非要到火R站去乎ͼ可以C些火车票的代售点M。寄信不一定是自己dQ可以把信委托给邮局Q由邮局把信送到目的圎ͼ现实生活中还有很多这L(fng)例子Q就不一一列D了?
三?l构?br /> Proxy模式l构囑֦?


 四?一个例?br /> 举一个比较俗的例子,一个男孩boy喜欢上了一个女孩girlQ男孩一直想认识奛_Q直接去和女孩打招呼吧,又觉得不好意思(q个男孩比较害羞Q。于是男孩想Z一个办法,委托奛_的室友Proxyd他搞定这件事Q获得一些关于女孩的信息Q如有没有BF{?q就叫知q|才能百战不殆Q。下面给个例子的E序实现Q?/p>

 interface GirlInfo{
  public void hasBoyFriend();
 }
 
 class Girl implements GirlInfo{

  public void hasBoyFriend(){
   System.out.println("q没有男朋友");
  }

 }
 
 class Proxy implements GirlInfo{
  
  private GirlInfo girl;
  
  public Proxy(GirlInfo girl){
   this.girl=girl;
  }
  public void hasBoyFriend(){
   this.girl.hasBoyFriend();
  }

 }
 
 public class ProxyClient {

 public static void main(String[] args) {
  GirlInfo girl=new Girl();
  Proxy proxy=new Proxy(girl);
  proxy.hasBoyFriend();
 }

 }
 从这个例子我们可以看出,Proxy模式是不是和Adapter模式差不多,都是调用一个已有对象的Ҏ(gu)来完成功能。但是他们之间还是有区别的,那就是Proxy模式的目标类必须要实现某个接口,代理cL有必要实现该接口Q模式是ȝQ它的实现是zȝQ如果一味的怿某些书上的实玎ͼ学习(fn)模式也就失去了意义。有的书上称q种实现为静态代理,之所以这hZ区别于Proxy模式在jdk中的另一U实?jdk中的实现UCؓ(f)动态代理。下面用jdk中的Ҏ(gu)l出q个例子的实现。代码如?

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

 interface GirlInfo{
  public void hasBoyFriend();
 }
 
 class Girl implements GirlInfo{

  public void hasBoyFriend(){
   System.out.println("q没有男朋友");
  }

 }
 
 class GirlProxy implements InvocationHandler{
  private Object delegate;
  public Object bind(Object delegate){
   this.delegate=delegate;
   return Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(),this);
  }

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

   method.invoke(delegate, args);
   return null;
  }
 
 }
 
 public class ProxyClient {

  public static void main(String[] args) {
   GirlProxy girlProxy=new GirlProxy();
   GirlInfo girl=(GirlInfo)girlProxy.bind(new Girl());
   girl.hasBoyFriend();
  }

 }

五?适用?br /> 1Q?假如有一个外部组件包Q不允许实现其接口,则就只能使用其动态代理了?br /> 2Q?直接讉K一个对象很困难Q或者说不能讉KQ此时只能是找个代理去访问,然后把结果反馈给自己?br /> 六?优缺?br /> 1) 优点: 向客L(fng)隐藏了访问某个对象的l节?qing)复杂性;可以动态地调用一个对象中的方法,且无需实现固定的接口?br /> 2) ~点Q暂时没发现


 



Eric_jiang 2010-09-09 11:47 发表评论
]]>
抽象工厂模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331487.htmlEric_jiangEric_jiangThu, 09 Sep 2010 03:34:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331487.htmlhttp://www.tkk7.com/jjshcc/comments/331487.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331487.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331487.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331487.html抽象工厂模式QAbstract FactoryQ:(x)为创Zl相x者互怾赖的对象提供一个接口,而无需指定它们对应的具体类?br /> 通用cd如下Q?

例如Q我们现在有两种产品A和BQ而品A和B分别都有两个厂商1?q行生Q在q里我们把不同的厂商1、厂?理解为牌?和牌?Q那么厂?q产A1、B1Q厂?生A2、B2?br /> 此时Q不同的厂商肯定要生产自q产品Q如A1、B1Q,每个厂商都有自己的一pd产品Q这׃上面抽象工厂模式的描q类g?br /> 该例子的cd如下Q?

具体代码实现如下Q?br /> //定义不同的品之间的一定具备的标准Q用interface实现
//其中的method()Ҏ(gu)可看作提取出不同产品的共性,如手机都有类似的功能
interface IProductA{
  public void method();
}

interface IProductB{
  public void method();
}

//实现了品标准实现的一pd具体产品
//׃已经设计好A1由厂?生Q故以下输出代码?#8220;厂商x”
class ProductA1 implements IProductA{
  public void method() {
    System.out.println("厂商1    生ProductA1 ...");
  }
}

class ProductA2 implements IProductA{
  public void method() {
    System.out.println("厂商2    生ProductA2 ...");
  }
}

class ProductB1 implements IProductB{
  public void method() {
    System.out.println("厂商1    生ProductB1 ...");
  }
}

class ProductB2 implements IProductB{
  public void method() {
    System.out.println("厂商2    生ProductB2 ...");
  }
}

//每一U牌子的产品生工厂Q即不同的厂商负责自q子品的生
abstract class Factory1{
  abstract IProductA getProductA1();
  abstract IProductB getProductB1();
}

abstract class Factory2{
  abstract IProductA getProductA2();
  abstract IProductB getProductB2();
}

//具体的工厂用来生产相关的产品
class ConcreteFactory1 extends Factory1{
  public IProductA getProductA1() {
    return new ProductA1();
  }
  public IProductB getProductB1() {
    return new ProductB1();
  }
}

class ConcreteFactoryB extends Factory2{
  public IProductA getProductA2() {
    return new ProductA2();
  }
  public IProductB getProductB2() {
    return new ProductB2();
  }
}

//试c?
public class Client {
  public static void main(String[] args) {
    //厂商1负责生产品A1、B1
    Factory1 factory1 = new ConcreteFactory1();
    IProductA productA1 = factory1.getProductA1();
    IProductB productB1 = factory1.getProductB1();
    
    productA1.method();
    productB1.method();
    
    //厂商2负责生产品A2、B2
    Factory2 factory2 = new ConcreteFactoryB();
    IProductA productA2 = factory2.getProductA2();
    IProductB productB2 = factory2.getProductB2();
    
    productA2.method();
    productB2.method();
  }
}
q行l果Q?br /> 厂商1  生ProductA1 ...
厂商1  生ProductB1 ...
厂商2  生ProductA2 ...
厂商2  生ProductB2 ...

 
其实Q上例中本来可以不用C两个抽象工厂Q只剩一个也可,但是q样子与我们现实生活中不同厂商各自生产自q产品有点不同Q所以就其分开Z个了Q也是两个厂商完全地分离开?br /> ׃面类囑֏以知道,一旦Q何一个厂商开发出了品C的话Q那么这个厂商肯定需要扩展自q工厂来投入到C产品的生产中Q那么此时工?和工?需要进行一定的改变了,q很明显不符合开闭原则?/font>



Eric_jiang 2010-09-09 11:34 发表评论
]]>
外观模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331484.htmlEric_jiangEric_jiangThu, 09 Sep 2010 03:22:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331484.htmlhttp://www.tkk7.com/jjshcc/comments/331484.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331484.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331484.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331484.htmlFacade模式是这hq的:
       为子pȝ中的一l接口提供一个统一接口。Facade模式定义了一个更高层的接口,使子pȝ更加Ҏ(gu)使用?/font>

       大致意思是_(d)(x)使用一U比原有方式更简单的办法与系l交互。例如,我们拿一个文Ӟq个文g攑֜了第二抽屉里Q而第二个抽屉的钥匙放在了W一个抽屉里Q我们要惛_个文ӞW一步肯定要拿到W一个抽屉的钥匙Q然后打开它再拿出W二个抽屉的钥匙Q最后打开W二个抽屉取出文件?br />  我就上面说的那个情Ş写一下实C?/font>

class DrawerOne {

    public void open(){

       System.out.println("W一个抽屉被打开?);

       getKey();

    }

    public void getKey(){

       System.out.println("得到W二个抽屉的钥匙");

    }

}

class DrawerTwo{

    public void open(){

       System.out.println("W二个抽屉被打开?);

       getFile();

    }

    public void getFile(){

       System.out.println("得到q个重要文g");

    }

}

public class Client{

    public static void main(String []args){

       DrawerOne darwerOne=new DrawerOne();

       DrawerTwo darwerTwo=new DrawerTwo();

       darwerOne.open();

       darwerTwo.open();

    }

}

׃没有使用Fa?ade模式Q可以看到要惛_到这个文件要首先打开W一个抽屉,然后再打开W二个抽屉,在我们实际所开发的pȝ中,有时候客戯实现某一操作Qƈ不需要知道实现这一操作的详l步骤,而是单地点击某一个按钮就可以得到自己惌的结果。下面对上面的代码用Fa?ade模式q行改进Q徏立一个FacadeDrawerc:(x)

class DrawerFacade{

    DrawerOne darwerOne=new DrawerOne();

    DrawerTwo darwerTwo=new DrawerTwo();

    public void open(){

       darwerOne.open();

       darwerTwo.open();

    }

}

修改Clientc:(x)

public class DrawerClient{

    public static void main(String []args){

       DrawerFacade drawer=new DrawerFacade();

       drawer.open();

    }

}

输出l果如下Q?/font>

W一个抽屉被打开?/font>

得到W二个抽屉的钥匙

W二个抽屉被打开?/font>

得到q个重要文g

正如上面所_(d)客户端clientQ它q不需要关心子pȝQ而是兛_DrawerFacade所留下来的和外部交互的接口Q而子pȝ在DrawerFacade的聚合?/font>

以上只是个h拙见Q哪里有不正的地方Q希望大家多多批评指正。^_^

Facade模式主要适用于以下几U情?

1)不需要用一个复杂系l的所有功能,而且可以创徏一个新的类Q包含访问系l的所有规则。如果只需要用系l的部分功能Q那么你为新cL创徏的API比原系l的API单的多?/font>

2)希望装或者隐藏系l原pȝ?/font>

3)希望使用原系l的功能Q而且q希望增加一些新的功能?/font>

4) ~写新类的成本小于所有h学会(x)使用或者未来维护原pȝ上所需的成本?/font>

 

 



Eric_jiang 2010-09-09 11:22 发表评论
]]>
享元模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331481.htmlEric_jiangEric_jiangThu, 09 Sep 2010 03:13:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331481.htmlhttp://www.tkk7.com/jjshcc/comments/331481.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331481.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331481.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331481.html一、FlyWeight模式定义:

q用׃n技术有效地支持大量l粒度对象?/font>

二、模式解?/font>

也就是说在一个系l中如果有多个相同的对象Q那么只׃n一份就可以了,不必每个都去实例化一个对象。在Flyweight模式中,׃要生各U各L(fng)对象Q所以在Flyweight(享元)模式中常出现Factory模式。Flyweight的内部状态是用来׃n?Flyweight factory负责l护一个对象存储池QF(tun)lyweight PoolQ来存放内部状态的对象。Flyweight模式是一个提高程序效率和性能的模??x)大大加快程序的q行速度?/font>

三、结构图

 

享元模式所涉及(qing)的角色有抽象享元角色、具体(单纯Qn元角艌Ӏ复合n元角艌Ӏn员工厂角Ԍ以及(qing)客户端角色等?/font>

抽象享元角色QF(tun)lyweightQ:(x)此角色是所有的具体享元cȝ类Qؓ(f)q些c规定出需要实现的公共接口或抽象类。那些需要外蕴状?External State)的操作可以通过Ҏ(gu)的参C入。抽象n元的接口使得享元变得可能Q但是ƈ不强制子cd行共享,因此q所有的享元对象都是可以׃n的?/font>

具体享元(ConcreteFlyweight)角色Q实现抽象n元角色所规定的接口。如果有内蕴状态的话,必须负责为内蕴状态提供存储空间。n元对象的内蕴状态必M对象所处的周围环境无关Q从而得n元对象可以在pȝ内共享。有时候具体n元角色又叫做单纯具体享元角色Q因为复合n元角色是由单U具体n元角色通过复合而成的?/font>

复合享元(UnsharableFlyweight)角色Q复合n元角色所代表的对象是不可以共享的Q但是一个复合n元对象可以分解成为多个本w是单纯享元对象的组合。复合n元角色又U做不可׃n的n元对象。这个角色一般很用?/font>

享元工厂(FlyweightFactoiy)角色Q本角色负责创徏和管理n元角艌Ӏ本角色必须保证享元对象可以被系l适当地共享。当一个客L(fng)对象h一个n元对象的时候,享元工厂角色需要检查系l中是否已经有一个符合要求的享元对象Q如果已l有了,享元工厂角色应当提供这个已有的享元对象Q如果系l中没有一个适当的n元对象的话,享元工厂角色应当创Z个新的合适的享元对象?/font>

客户?Client)角色Q本角色q需要自行存储所有n元对象的外蕴状态?/font>

四、一个例?/font>

 

import java.util.Hashtable;


/**
 *
 * @author <a href="mailto:flustar2008@163.com">flustar</a>
 * @version 1.0
 * Creation date: Jan 25, 2008 1:33:49 PM
 */

  // "Flyweight"

  abstract class Character
  {
    protected char symbol;
    protected int width;
    protected int height;
    protected int ascent;
    protected int descent;
    protected int pointSize;

    public abstract void Display(int pointSize);
  }

  // "ConcreteFlyweight"

  class CharacterA extends Character
  {
    // Constructor
    public CharacterA()
    {
      this.symbol = 'A';
      this.height = 100;
      this.width = 120;
      this.ascent = 70;
      this.descent = 0;
    }

    public  void Display(int pointSize)
    {
      this.pointSize = pointSize;
     System.out.println(this.symbol +
        " (pointsize " + this.pointSize + ")");
    }
  }

  // "ConcreteFlyweight"

  class CharacterB extends Character
  {
    // Constructor
    public CharacterB()
    {
      this.symbol = 'B';
      this.height = 100;
      this.width = 140;
      this.ascent = 72;
      this.descent = 0;
    }

    public  void Display(int pointSize)
    {
      this.pointSize = pointSize;
     System.out.println(this.symbol +
        " (pointsize " + this.pointSize + ")");
    }

  }

  //  C, D, E, etc.

  // "ConcreteFlyweight"

  class CharacterZ extends Character
  {
    // Constructor
    public CharacterZ()
    {
      this.symbol = 'Z';
      this.height = 100;
      this.width = 100;
      this.ascent = 68;
      this.descent = 0;
    }

    public  void Display(int pointSize)
    {
      this.pointSize = pointSize;
      System.out.println(this.symbol +
        " (pointsize " + this.pointSize + ")");
    }
  }
  // "FlyweightFactory"

  class CharacterFactory
  {
    private Hashtable characters = new Hashtable();

    public Character GetCharacter(char key)
    {
      // Uses "lazy initialization"
      Character character = (Character)characters.get(key);
      if (character == null)
      {
        switch (key)
        {
          case 'A': character = new CharacterA(); break;
          case 'B': character = new CharacterB(); break;
            //
          case 'Z': character = new CharacterZ(); break;
        }
        characters.put(key, character);
      }
      return character;
    }
  }
// test application
  public class Test
  {
    public static void main(String []args)
    {
      // Build a document with text
      String document = "AAZZBBZB";
      char[] chars = document.toCharArray();

      CharacterFactory f = new CharacterFactory();

      // extrinsic state
      int pointSize = 10;

      // For each character use a flyweight object
      for(char c : chars)
      {
        pointSize++;
        Character character = f.GetCharacter(c);
        character.Display(pointSize);
      }
    }
  }

 

五?适用?/p>

Flyweight模式的有效性很大程度上取决于如何用它以及(qing)在何处用它。当以下情况都成立时使用Flyweight模式?/p>

1Q一个应用程序用了大量的对象?/p>

2Q完全由于用大量的对象Q造成很大的存储开销?/p>

3Q对象的大多数状态都可变为外部状态?/p>

4Q如果删除对象的外部状态,那么可以用相对较?yu)的׃n对象取代很多l对象?/p>

5Q应用程序不依赖对象标识?/p>

六、优~点

1Qn元模式得系l更加复杂。ؓ(f)了对象可以׃nQ需要将一些状态外部化Q这使得E序的逻辑复杂化?

2Qn元模式将享元对象的状态外部化Q而读取外部状态得运行时间稍微变ѝ?br />



Eric_jiang 2010-09-09 11:13 发表评论
]]>
l合模式http://www.tkk7.com/jjshcc/archive/2010/09/09/331478.htmlEric_jiangEric_jiangThu, 09 Sep 2010 02:59:00 GMThttp://www.tkk7.com/jjshcc/archive/2010/09/09/331478.htmlhttp://www.tkk7.com/jjshcc/comments/331478.htmlhttp://www.tkk7.com/jjshcc/archive/2010/09/09/331478.html#Feedback0http://www.tkk7.com/jjshcc/comments/commentRss/331478.htmlhttp://www.tkk7.com/jjshcc/services/trackbacks/331478.html 

设计模式之Composite(l合)

Composite定义:
对象以?wi)Şl构l织h,以达?#8220;部分Q整?#8221; 的层ơ结构,使得客户端对单个对象和组合对象的使用h一致?

Composite比较Ҏ(gu)理解Q想到Composite应该想到树(wi)形结构图。组合体内这些对象都有共同接?当组合体一个对象的Ҏ(gu)被调用执行时QComposite遍?Iterator)整个?wi)Şl构,L同样包含q个Ҏ(gu)的对象ƈ实现调用执行。可以用牵一动百来Ş宏V?/p>

所以Composite模式使用到Iterator模式Q和Chain of Responsibility模式cM?/p>

Composite好处:
1.使客L(fng)调用单,客户端可以一致的使用l合l构或其中单个对象,用户׃必关p自己处理的是单个对象还是整个组合结构,q就化了客户端代码?br /> 2.更容易在l合体内加入对象部g. 客户端不必因为加入了新的对象部g而更改代码?/p>

如何使用Composite?
首先定义一个接口或抽象c,q是设计模式通用方式了,其他设计模式Ҏ(gu)口内部定义限制不多,Composite却有个规定,那就是要在接口内部定义一个用于访问和理Compositel合体的对象们(或称部gComponentQ?

下面的代码是以抽象类定义Q一般尽量用接口interface,

public abstract class Equipment
{
  private String name;
  //|络h
  public abstract double netPrice();
  //折扣h
  public abstract double discountPrice();
  //增加部gҎ(gu)  
  public boolean add(Equipment equipment) { return false; }
  //删除部gҎ(gu)
  public boolean remove(Equipment equipment) { return false; }
  //注意q里Q这里就提供一U用于访问组合体cȝ部gҎ(gu)?br />   public Iterator iter() { return null; }
  
  public Equipment(final String name) { this.name=name; }
}


抽象cEquipment是Component定义Q代表着l合体类的对象们,Equipment中定义几个共同的Ҏ(gu)?/p>

public class Disk extends Equipment
{
  public Disk(String name) { super(name); }
  //定义Disk|络h?
  public double netPrice() { return 1.; }
  //定义了disk折扣h?.5 Ҏ(gu)?br />   public double discountPrice() { return .5; }
}


Disk是组合体内的一个对象,或称一个部Ӟq个部g是个单独元素(Primitive)?br /> q有一U可能是Q一个部件也是一个组合体Q就是说q个部g下面q有'儿子'Q这是树(wi)形结构中通常的情况,应该比较Ҏ(gu)理解。现在我们先要定义这个组合体Q?/p>

abstract class CompositeEquipment extends Equipment
{
  private int i=0;
  //定义一个Vector 用来存放'儿子'
  private Lsit equipment=new ArrayList();

  public CompositeEquipment(String name) { super(name); }

  public boolean add(Equipment equipment) {
     this.equipment.add(equipment);
     return true;
   }

  public double netPrice()
  {
    double netPrice=0.;
    Iterator iter=equipment.iterator();
    for(iter.hasNext())
      netPrice+=((Equipment)iter.next()).netPrice();
    return netPrice;
  }

  public double discountPrice()
  {
    double discountPrice=0.;
    Iterator iter=equipment.iterator();
    for(iter.hasNext())
      discountPrice+=((Equipment)iter.next()).discountPrice();
    return discountPrice;
  }
  

  //注意q里Q这里就提供用于讉K自己l合体内的部件方法?br />   //上面dIsk 之所以没有,是因为Disk是个单独(Primitive)的元?
  public Iterator iter()
  {
    return equipment.iterator() ;
  {
  //重蝲IteratorҎ(gu)
   public boolean hasNext() { return i<equipment.size(); }
  //重蝲IteratorҎ(gu)
   public Object next()
   {
    if(hasNext())
       return equipment.elementAt(i++);
    else
        throw new NoSuchElementException();
   }
  

}


上面CompositeEquipmentl承了Equipment,同时己里面的对象们提供了外部讉K的方?重蝲了Iterator,Iterator是Java的Collection的一个接口,是Iterator模式的实?

我们再看看CompositeEquipment的两个具体类:盘盒Chassis和箱子CabinetQ箱子里面可以放很多东西Q如底板Q电(sh)源盒Q硬盘盒{;盘盒里面可以放一些小讑֤Q如盘 软驱{。无疑这两个都是属于l合体性质的?/p>

public class Chassis extends CompositeEquipment
{
   public Chassis(String name) { super(name); }
   public double netPrice() { return 1.+super.netPrice(); }
   public double discountPrice() { return .5+super.discountPrice(); }
}

public class Cabinet extends CompositeEquipment
{
   public Cabinet(String name) { super(name); }
   public double netPrice() { return 1.+super.netPrice(); }
   public double discountPrice() { return .5+super.discountPrice(); }
}


x我们完成了整个Composite模式的架构?/p>

我们可以看看客户端调用Composote代码:

Cabinet cabinet=new Cabinet("Tower");

Chassis chassis=new Chassis("PC Chassis");
//PC Chassis装到Tower?(盘盒装到箱子里)
cabinet.add(chassis);
//一?0GB的硬盘装?PC Chassis (硬盘装到盘盒里)
chassis.add(new Disk("10 GB"));

//调用 netPrice()Ҏ(gu);
System.out.println("netPrice="+cabinet.netPrice());
System.out.println("discountPrice="+cabinet.discountPrice());

上面调用的方法netPrice()或discountPrice()Q实际上Composite使用Iterator遍历了整个树(wi)形结?L同样包含q个Ҏ(gu)的对象ƈ实现调用执行.

Composite是个很y妙体现智慧的模式Q在实际应用中,如果到?wi)Şl构Q我们就可以试是否可以使用q个模式?/p>

以论坛ؓ(f)例,一个版(forum)中有很多帖子(message),q些帖子有原始脓(chung)Q有对原始脓(chung)的回应脓(chung)Q是个典型的?wi)Şl构Q那么当然可以用Composite模式Q那么我们进入Jive中看看,是如何实现的.

Jive解剖
在Jive?ForumThread是ForumMessages的容器container(l合?.也就是说QForumThreadcM我们上例中的 CompositeEquipment.它和messages的关pd图:(x)
[thread]
   |- [message]
   |- [message]
      |- [message]
      |- [message]
         |- [message]

我们在ForumThread看到如下代码Q?/p>

public interface ForumThread {
   ....
   public void addMessage(ForumMessage parentMessage, ForumMessage newMessage)
         throws UnauthorizedException;

   public void deleteMessage(ForumMessage message)
         throws UnauthorizedException;

  
   public Iterator messages();
      ....

}
cMCompositeEquipment, 提供用于讉K自己l合体内的部件方? 增加 删除 遍历.

? 试E序与源E序的组l结构,“分离但等?#8221;原则
? junit.jar加入到classpath中,可以被javacd扑ֈQ但不能j(lu)avad识别?/p>

junit与ant构徏工具的集?/p>

如果junitd下面没有讄<formatter>子元素,那将无法打印l的信息?br /> 一个junitd下可以有多个<formatter>子元?<formatter>的usefile属性决定是否生成文件?br /> junitreportd首先把多个test-....xml文g合ƈ成一个汇ȝxml文gQ其todir属性指定该文g的存储目?其report子元素用于指定生成的html文g的目录。在用junitreport之前Q要心junit的haltonfaiure?/p>

batchtest指定的java源文件或class文gQ而不是要q行的测试类名称Qjunit从这些文件中扑և要运行的试cd?/p>

? junit与ant构徏工具的集成的例子,
<project name="junitlesson" default="run">

<property name="src.java.dir" value="src/java"/><!--被测试的java源文件的路径-->
<property name="src.test.dir" value="src/test"/><!--试的java源文件的路径-->

<property name="classes.java.dir" value="classes/java"/><!--被测试的class文g的\?->
<property name="classes.test.dir" value="classes/test"/><!--试的class文g的\?->

<target name="init">
   <mkdir dir="${classes.java.dir}"/>
   <mkdir dir="${classes.test.dir}"/>
</target>

<target name="compileJava" depends="init">
   <javac srcdir="${src.java.dir}/cn/itcast" destdir="${classes.java.dir}"/>
</target>

<target name="compileTest" depends="init">
   <javac srcdir="${src.test.dir}/cn/itcast" destdir="${classes.test.dir}">
    <classpath>
     <pathelement path="."/>
     <pathelement path="${classes.java.dir}"/>
    </classpath>
   </javac>
</target>

<target name="compile" depends="compileJava,compileTest"/>

<target name="run" depends="compile">
   <mkdir dir="testResult"/>
   <junit fork="true" printsummary="on"><!-- haltonfailure="true"--><!--注意:q句一加上ȝ话如果程序里面出错了后面的junitreport׃执行?->
    <classpath>
     <pathelement path="${classes.test.dir}"/>
     <pathelement path="${classes.java.dir}"/>
    </classpath>
    <test name="cn.itcast.TestCalculator" todir=".\testResult" outfile="result"/>
    <formatter type="xml" />
   </junit>
 
   <junitreport todir=".\testResult"> 
       <fileset dir=".\testResult"> 
           <include name="result.xml"/> 
       </fileset> 
       <report format="frames" todir=".\testResult"/> 
     </junitreport> 
</target>

</project>
<!--正确执行的话打开src所在的目录׃(x)看到一个新建的testResult目录,里面已经生成了一大堆试报告的网?:) -->

 



Eric_jiang 2010-09-09 10:59 发表评论
]]>
观察者模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331468.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331468.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331468.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331468.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331468.html</trackback:ping><description><![CDATA[<p><font style="background-color: #cce8cf">一、要完成的Q?/font></p> <p><font style="background-color: #cce8cf">此系l中的三个部分是气象站(获取实际气象数据的物理装|)、WeatherData对象Q追t来自气象站的数据,q更新布告板Q和布告板(昄目前天气状况l用L(fng)Q?/font></p> <p><font style="background-color: #cce8cf"></font>  <div align="center"><img border="0" alt="" src="http://www.tkk7.com/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"> </font></p> <p><font style="background-color: #cce8cf">1、定义观察者模?/font></p> <p><font style="background-color: #cce8cf">观察者模式定义了对象之间的一对多依赖Q这样一来,当一个对象改变状态时Q它的所有依赖者都?x)收到通知q自动更新?/font></p> <p><font style="background-color: #cce8cf"></font>  <div align="center"><img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/DesignPattern-observer-2.gif" width="421" height="344" /></div> </p> <p><font style="background-color: #cce8cf">  <br /> 2.设计气象?/font></p> <p><font style="background-color: #cce8cf"></font>  <div align="center"><img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?DesignPattern-observer-3.gif" width="599" height="312" /></div> <font style="background-color: #cce8cf"><br />   <br /> 三、代码实?/p> <p> </p> <p>1Q定义接?/p> <p> </p> <p>Q?QSubject接口</p> <p>Subject.java</p> <p>package com.leanhuadeng.DesignPattern.Observer;</p> <p>public interface Subject {<br />     public void registerObserver(Observer o);<br />     public void removeObserver(Observer o);<br />     public void notifyObservers();<br /> }</p> <p>  <br /> Q?QObserver接口</p> <p>Observer.java<br /> package com.leanhuadeng.DesignPattern.Observer;</p> <p>public interface Observer {<br />     public void update(float temp,float humidity,float pressure);<br /> }<br />   <br /> Q?QDisplayment接口</p> <p>Displayment.java</p> <p>package com.leanhuadeng.DesignPattern.Observer;</p> <p>public interface Displayment {<br />     public void display();<br /> }</p> <p> </p> <p>  </p> <p>2Q实现接?/p> <p> </p> <p>Q?QWeatherData</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 />     private ArrayList observers;<br />     private float temperature;<br />     private float humidity;<br />     private float pressure;<br />     <br />     public WeatherData(){<br />         observers=new ArrayList();<br />     }<br />     <br />     public void notifyObservers() {<br />         for(int i=0;i<observers.size();i++){<br />             Observer observer=(Observer)observers.get(i);<br />             observer.update(temperature, humidity, pressure);<br />         }<br />     }</p> <p>    public void registerObserver(Observer o) {<br />         observers.add(o);<br />     }</p> <p>    public void removeObserver(Observer o) {<br />         int i=observers.indexOf(o);<br />         if(i>=0){<br />             observers.remove(i);<br />         }<br />     }<br />     public void measurementsChanged(){<br />         notifyObservers();<br />     }<br />     public void setMeasurements(float temperature,float humidity,float pressure){<br />         this.temperature=temperature;<br />         this.humidity=humidity;<br />         this.pressure=pressure;<br />         measurementsChanged();<br />     }<br /> }</p> <p>  <br /> Q?QCurrentConditionsDisplay</p> <p>CurrentConditionsDisplay.java</p> <p>package com.leanhuadeng.DesignPattern.Observer;</p> <p>public class CurrentConditionsDisplay implements Observer, Displayment {<br />     private float temperature;<br />     private float humidity;<br />     private Subject weatherData;<br />     <br />     public CurrentConditionsDisplay(Subject weatherData){<br />         this.weatherData=weatherData;<br />         weatherData.registerObserver(this);<br />     }<br />     <br />     public void update(float temp, float humidity, float pressure) {<br />         this.temperature=temp;<br />         this.humidity=humidity;<br />         display();<br />     }</p> <p>    public void display() {<br />         System.out.println("Current conditions:"+temperature+"F degrees and "+humidity+"% humidity");<br />     }</p> <p>}</p> <p>  <br /> Q?QStatisticsDisplay</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 />     private float maxTemp = 0.0f;<br />     private float minTemp = 200;<br />     private float tempSum= 0.0f;<br />     private int numReadings;<br />     private WeatherData weatherData;</p> <p>    public StatisticsDisplay(WeatherData weatherData) {<br />         this.weatherData = weatherData;<br />         weatherData.registerObserver(this);<br />     }</p> <p>    public void update(float temp, float humidity, float pressure) {<br />         tempSum += temp;<br />         numReadings++;</p> <p>        if (temp > maxTemp) {<br />             maxTemp = temp;<br />         }<br />  <br />         if (temp < minTemp) {<br />             minTemp = temp;<br />         }</p> <p>        display();<br />     }</p> <p>    public void display() {<br />         System.out.println("Avg/Max/Min temperature = " + (tempSum / numReadings)+ "/" + maxTemp + "/" + minTemp);<br />     }<br /> }</p> <p>  <br /> Q?QForecastDisplay</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 />     private float currentPressure = 29.92f;  <br />     private float lastPressure;<br />     private WeatherData weatherData;</p> <p>    public ForecastDisplay(WeatherData weatherData) {<br />         this.weatherData = weatherData;<br />         weatherData.registerObserver(this);<br />     }</p> <p>    public void update(float temp, float humidity, float pressure) {<br />                 lastPressure = currentPressure;<br />         currentPressure = pressure;</p> <p>        display();<br />     }</p> <p>    public void display() {<br />         System.out.print("Forecast: ");<br />         if (currentPressure > lastPressure) {<br />             System.out.println("Improving weather on the way!");<br />         } else if (currentPressure == lastPressure) {<br />             System.out.println("More of the same");<br />         } else if (currentPressure < lastPressure) {<br />             System.out.println("Watch out for cooler, rainy weather");<br />         }<br />     }<br /> }</p> <p>  <br /> 3Q实现气象站</p> <p>WeatherStation.java</p> <p>package com.leanhuadeng.DesignPattern.Observer;</p> <p>public class WeatherStation {<br />     public static void main(String[] args){<br />         WeatherData weatherData=new WeatherData();<br />         <br />         CurrentConditionsDisplay currentDisplay=new CurrentConditionsDisplay(weatherData);<br />         StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);<br />         ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);<br />         <br />         weatherData.setMeasurements(80, 65, 30.4f);<br />         weatherData.setMeasurements(82, 70, 29.2f);<br />         weatherData.setMeasurements(78, 90, 29.2f);        <br />         <br />     }<br /> }<br /> </font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 10:08 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>装饰者模?/title><link>http://www.tkk7.com/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.tkk7.com/jjshcc/archive/2010/09/09/331457.html</guid><wfw:comment>http://www.tkk7.com/jjshcc/comments/331457.html</wfw:comment><comments>http://www.tkk7.com/jjshcc/archive/2010/09/09/331457.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/jjshcc/comments/commentRss/331457.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/jjshcc/services/trackbacks/331457.html</trackback:ping><description><![CDATA[<p><strong><span style="font-family: 宋体; color: black; font-size: 12pt">一、要完成的Q?/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">Q是以扩张速度最快而闻名的咖啡q锁店。如果你在街角看到它的店Q在寚w街上肯定q会(x)看到另一家。因为扩张速度实在太快了,他们准备更新订单pȝQ以合乎他们的饮料供应要求。他们原先的c设计是q样?#8230;…</span></p>   <div align="center"><img border="0" alt="" src="http://www.tkk7.com/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">购买咖啡Ӟ也可以要求在其中加入各种调料Q例如:(x)蒸奶Q?/span><span style="font-family: Arial; color: black">Steamed Milk</span><span style="font-family: 宋体; color: black">Q、豆(</span><span style="font-family: Arial; color: black">Soy</span><span style="font-family: 宋体; color: black">Q、摩卡(</span><span style="font-family: Arial; color: black">Mocha</span><span style="font-family: 宋体; color: black">Q也是巧克力风呻I或覆盖奶泡。星巴兹?x)根据所加入的调料收取不同的费用。所以订单系l必考虑到这些调料部分?/span></p>   <font style="background-color: #cce8cf">二、Decorator模式</font> <p><font style="background-color: #cce8cf">1、一个原?/font></p> <p><font style="background-color: #cce8cf">cd该对扩展开放,对修改关?/font></p> <p><font style="background-color: #cce8cf">2、定义装饰者模?/font></p> <p><font style="background-color: #cce8cf">装饰者模式动态地责任附加到对象上。若要扩展功能,装饰者提供了比承更有弹性的替代Ҏ(gu)?br /> <div align="center"><img border="0" alt="" src="http://www.tkk7.com/images/blogjava_net/jjshcc/技术截?DesignPattern-Decorator-2-define.gif" width="549" height="382" /></div> <font style="background-color: #cce8cf">3.分析d</font><br /> </font> <p> <div align="center"><img border="0" alt="" src="http://www.tkk7.com/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.tkk7.com/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.tkk7.com/images/blogjava_net/jjshcc/DesignPattern-Decorator-5-analys.gif" width="816" height="525" /></div> <font style="background-color: #cce8cf">4.设计d</font><br /> <div align="center"><img border="0" alt="" src="http://www.tkk7.com/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"> </font></p> <p><font style="background-color: #cce8cf">1Q定义抽象类</font></p> <p><font style="background-color: #cce8cf"> </font></p> <p><font style="background-color: #cce8cf">Q?Q饮料抽象类Beverage</font></p> <p><font style="background-color: #cce8cf">Beverage.java<br /> </p> <p><font style="background-color: #cce8cf"> package com.leanhuadeng.DesignPattern.Decorator;</font></p> <p><font style="background-color: #cce8cf">/* <br />  * Beverage是一个抽象类,有两个方?br />  */<br /> public abstract class Beverage {<br />         public String description="Unknown Beverage";<br />         <br />         /* <br />          * getDescription()已经在此实现?但是cost()必须在子cM实现<br />          */<br />         public String getDescription() {<br />             return description;<br />         }<br />         <br />         public abstract double cost();<br /> }</font></p> <p><font style="background-color: #cce8cf"></font> </p> <p><font style="background-color: #cce8cf">三、代码实?br />  <br /> (2)调料抽象cCondimentDecorator<br /> CondimentDecorator.java<br /> package com.leanhuadeng.DesignPattern.Decorator;<br /> /* <br />  * 首先,必须让CondimentDecorator能够取代Beverage,所以将CondimentDecorator扩展自Beveragec?br />  */<br /> public abstract class CondimentDecorator extends Beverage {</font></p> <p><font style="background-color: #cce8cf">    //所有的调料装饰者都必须重新实现getDescription()Ҏ(gu).<br />     public abstract String getDescription();<br /> }<br />   <br /> 2Q饮料实?/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 />  * 首先,必须让CondimentDecorator能够取代Beverage,所以将CondimentDecorator扩展自Beveragec?br />  */<br /> public abstract class CondimentDecorator extends Beverage {</font></p> <p><font style="background-color: #cce8cf">    //所有的调料装饰者都必须重新实现getDescription()Ҏ(gu).<br />     public abstract String getDescription();<br /> }</font></p> <p><font style="background-color: #cce8cf">  <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 />     <br />     <br />     public HouseBlend() {<br />         description="House Blend Coffee";<br />     }</font></p> <p><font style="background-color: #cce8cf">    @Override<br />     public double cost() {<br />         return 0.89;<br />     }</font></p> <p><font style="background-color: #cce8cf">}<br />   <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 />     <br />     <br />     public DarkRoast() {<br />         description="Dark Roast Coffee";<br />     }</font></p> <p><font style="background-color: #cce8cf">    @Override<br />     public double cost() {<br />         return 0.99;<br />     }<br /> }<br />   <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 />     <br />     <br />     public Decaf() {<br />         description="Decaf Coffee";<br />     }</font></p> <p><font style="background-color: #cce8cf">    @Override<br />     public double cost() {<br />         return 1.05;<br />     }<br /> }</font></p> <p><font style="background-color: #cce8cf">  <br /> 3Q调料实?/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 />     /* <br />      * 要让Mocha能够引用一个Beverage,做法如下:一是用一个实例变量记录饮?也就是被装饰?<br />      * 二是惛_法让装饰?饮料)记录到实例变量中,x饮料当作构造器的参?再由构造器此饮料记录在实例变量中<br />      */<br />     Beverage beverage;</font></p> <p><font style="background-color: #cce8cf">    public Mocha(Beverage beverage) {<br />         this.beverage = beverage;<br />     }</font></p> <p><font style="background-color: #cce8cf">    @Override<br />     public String getDescription() {<br />         /* <br />          * 我们希望叙述不只是描q饮?而是完整的连调料都描q出?br />          */<br />         return beverage.getDescription()+",Mocha";<br />     }<br />             <br />     @Override<br />     public double cost() {<br />         /* <br />          * 要计带Mocha饮料的h(hun)?首先把调用委托给装饰对象,以计h(hun)?然后再加上Mocha的h(hun)?得到最后结?br />          */<br />         return 0.20+beverage.cost();<br />     }<br /> }</font></p> <p><font style="background-color: #cce8cf">  <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 />     Beverage beverage;</font></p> <p><font style="background-color: #cce8cf">    public Soy(Beverage beverage) {<br />         this.beverage = beverage;<br />     }</font></p> <p><font style="background-color: #cce8cf">    public String getDescription() {<br />         return beverage.getDescription() + ", Soy";<br />     }</font></p> <p><font style="background-color: #cce8cf">    public double cost() {<br />         return .15 + beverage.cost();<br />     }<br /> }</font></p> <p><font style="background-color: #cce8cf">  <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 />  <br /> public class Whip extends CondimentDecorator {<br />     Beverage beverage;<br />  <br />     public Whip(Beverage beverage) {<br />         this.beverage = beverage;<br />     }<br />  <br />     public String getDescription() {<br />         return beverage.getDescription() + ", Whip";<br />     }<br />  <br />     public double cost() {<br />         return .10 + beverage.cost();<br />     }<br /> }</font></p> <p><font style="background-color: #cce8cf">  <br /> 4Q测试类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 />     public static void main(String args[]){<br />         /* <br />          * 订一杯Espresso,不需要调?打印出它的描q和价钱.<br />          */<br />         Beverage beverage=new Espresso();<br />         System.out.println(beverage.getDescription()+" $"+beverage.cost());<br />         <br />         /* <br />          * 刉一个DarkRoast对象,用Mocha,Whip装饰?br />          */<br />         Beverage beverage2=new DarkRoast();<br />         beverage2=new Mocha(beverage2);<br />         beverage2=new Mocha(beverage2);<br />         beverage2=new Whip(beverage2);<br />         System.out.println(beverage2.getDescription()+" $"+beverage2.cost());    <br />         <br />         /* <br />          * 最?再来一杯调料ؓ(f)豆浆,摩卡\奶的HouseBlend咖啡<br />          */<br />         Beverage beverage3=new HouseBlend();<br />         beverage3=new Soy(beverage3);<br />         beverage3=new Mocha(beverage3);<br />         beverage3=new Whip(beverage3);<br />         System.out.println(beverage3.getDescription()+" $"+beverage3.cost());    <br />     }<br /> }<br /> </font></p> <p><br /> </font></p> <img src ="http://www.tkk7.com/jjshcc/aggbug/331457.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/jjshcc/" target="_blank">Eric_jiang</a> 2010-09-09 09:32 <a href="http://www.tkk7.com/jjshcc/archive/2010/09/09/331457.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://9196528.com" target="_blank">vvvv99պƷ</a>| <a href="http://takiku.com" target="_blank">޹Ʒav</a>| <a href="http://df8848.com" target="_blank">avһùŴ</a>| <a href="http://w6446.com" target="_blank">þƵվ</a>| <a href="http://6000cpkj.com" target="_blank">컶ëƬ</a>| <a href="http://sdkjkj.com" target="_blank">AVרһ</a>| <a href="http://bjycxy88.com" target="_blank">޾Ʒ˳</a>| <a href="http://128313.com" target="_blank">Ƶ</a>| <a href="http://91xx8.com" target="_blank">AVר</a>| <a href="http://56v6.com" target="_blank">ѹۿ+ձ</a>| <a href="http://zhongxueping888.com" target="_blank">һ</a>| <a href="http://blcvs.com" target="_blank">޹ۺ </a>| <a href="http://276194.com" target="_blank">tsƵ</a>| <a href="http://sewuji.com" target="_blank">պһһ</a>| <a href="http://yeshenghuowang.com" target="_blank">Ļwww˳</a>| <a href="http://grjeans.com" target="_blank">Ƶѹۿվ</a>| <a href="http://mt181.com" target="_blank">޾Ʒרþþ</a>| <a href="http://by3142.com" target="_blank">2015պƵ</a>| <a href="http://www999973.com" target="_blank">޶Ƶ</a>| <a href="http://w9366.com" target="_blank">ˬˬƵѿԿ</a>| <a href="http://w6626.com" target="_blank">žžþùƷ6</a>| <a href="http://svvnn.com" target="_blank">av뾫Ʒ</a>| <a href="http://www-188588.com" target="_blank">㽶Ƶ</a>| <a href="http://ziguang1688.com" target="_blank">˳վɫ7799</a>| <a href="http://shiliuvip.com" target="_blank">þþƷ5555</a>| <a href="http://1992zyzp.com" target="_blank">ҹþþƷ</a>| <a href="http://yhanalati.com" target="_blank">޾ƷĻ鶹</a>| <a href="http://hbqueena.com" target="_blank">AëƬ߲Ųշ</a>| <a href="http://lyczyb.com" target="_blank">ĻƷ</a>| <a href="http://89kino.com" target="_blank">avۺ߹ۿ</a>| <a href="http://liexion.com" target="_blank">½һëƬƵۿ </a>| <a href="http://yw762.com" target="_blank">jzzijzzij߹ۿ츾</a>| <a href="http://qqc46.com" target="_blank">һ߲</a>| <a href="http://zhidianzh.com" target="_blank">AVһ</a>| <a href="http://nn227.com" target="_blank">ɫվwwwþþ</a>| <a href="http://www66913.com" target="_blank">þۺɫHEZYO</a>| <a href="http://mhysf.com" target="_blank">ͤͤѸ</a>| <a href="http://5shitou.com" target="_blank">žžþùƷ6</a>| <a href="http://22222xxx.com" target="_blank">Ʒ˿߲</a>| <a href="http://88533066.com" target="_blank">鵺̳Ʒ</a>| <a href="http://bqjonline.com" target="_blank">ѵƵݮ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>