??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲国产精品无码久久一区二区,久久精品国产精品亚洲艾,亚洲av片在线观看http://m.tkk7.com/renyangok/category/11736.html回归blogjavazh-cnFri, 14 May 2010 09:39:21 GMTFri, 14 May 2010 09:39:21 GMT60InterpreterQ解释器Q模?/title><link>http://m.tkk7.com/renyangok/articles/61157.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Tue, 01 Aug 2006 03:45:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/articles/61157.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/61157.html</wfw:comment><comments>http://m.tkk7.com/renyangok/articles/61157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/61157.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/61157.html</trackback:ping><description><![CDATA[ <p>Interpreter解释器模式定?<br />定义语言的文?,q且建立一个解释器来解释该语言中的句子.Q后面不用看了)</p> <p>Interpreterg使用面不是很q?它描qC一个语a解释器是如何构成?在实际应用中,我们可能很少L造一个语a的文?我们q是来简单的了解一?</p> <p>首先要徏立一个接?用来描述共同的操?</p> <p>public interface AbstractExpression { <br />   void interpret( Context context ); <br />} </p> <p>再看看包含解释器之外的一些全局信息</p> <p>public interface Context { } </p> <p>AbstractExpression的具体实现分两种:l结W表辑ּ和非l结W表辑ּ:</p> <p>public class TerminalExpression implements AbstractExpression { <br />   public void interpret( Context context ) { }<br />} </p> <p>对于文法中每一条规?非终l符表达式都必须?<br />public class NonterminalExpression implements AbstractExpression { <br />   private AbstractExpression successor; <br />  <br />   public void setSuccessor( AbstractExpression successor ) { <br />     this.successor = successor; <br />   } <br /><br />   public AbstractExpression getSuccessor() { <br />     return successor; <br />   }<br /><br />   public void interpret( Context context ) { } <br />} </p> <img src ="http://m.tkk7.com/renyangok/aggbug/61157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2006-08-01 11:45 <a href="http://m.tkk7.com/renyangok/articles/61157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MementoQ备望录Q模?/title><link>http://m.tkk7.com/renyangok/articles/61141.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Tue, 01 Aug 2006 02:28:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/articles/61141.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/61141.html</wfw:comment><comments>http://m.tkk7.com/renyangok/articles/61141.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/61141.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/61141.html</trackback:ping><description><![CDATA[ <p>Memento备望录模式定?<br />memento是一个保存另外一个对象内部状态拷贝的对象.q样以后可以将该对象恢复到原先保存的状?</p> <p>Memento模式相对也比较好理解,我们看下列代?</p> <table cellspacing="3" cellpadding="3" width="80%" border="0"> <tbody> <tr> <td bgcolor="#cccccc">public class Originator { <br /><br />   private int number; <p>  private File file = null;</p><p>  public Originator(){}</p><p>  // 创徏一个Memento<br />  public Memento getMemento(){<br />    return new Memento(this);<br />  }</p><p>  // 恢复到原始?br />  public void setMemento(Memento m){<br />     number = m.number;<br />     file = m.file;<br />  }</p><p>}</p><p> </p></td> </tr> </tbody> </table> <p>我们再看看Mementoc?</p> <table cellspacing="3" cellpadding="3" width="80%" border="0"> <tbody> <tr> <td bgcolor="#cccccc"> <p>private class Memento implements java.io.Serializable{</p> <p>  private int number;</p> <p>  private File file = null;</p> <p>  public Memento( Originator o){</p> <p>    number = o.number;<br />    file = o.file;</p> <p>  }</p> <p>}</p> <p> <br /> </p> </td> </tr> </tbody> </table> <p>可见 Memento中保存了Originator中的number和file的? 通过调用Originator中number和file值改变的?通过调用setMemento()Ҏ(gu)可以恢复.</p> <p>Memento模式的缺Ҏ(gu)耗费?如果内部状态很?再保存一?无意要浪费大量内?</p> <p> <b>Memento模式在Jsp+Javabean中的应用</b> <br />在Jsp应用?我们通常有很多表单要求用戯?比如用户注册,需要输入姓名和Email{? 如果一些表用h有填写或者填写错?我们希望在用h"提交Submit"?通过JspE序?发现实有未填写目,则在该项目下U字昄警告或错?同时,q要昄用户刚才已经输入的表?</p> <p>如下图中 First Name是用户已l输?Last Name没有输入,我们则提C红字警?:</p> <p> <img height="500" src="http://www.jdon.com/designpatterns/images/memento.gif" width="425" /> </p> <p>q种技术的实现,是利用了Javabean的scope="request"或scope="session"Ҏ(gu)?也就是Memento模式.<br />Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-<br />实例Q?br />l常使用计算机的人恐怕对pȝ备䆾QMementoQ不?x)陌生,当你的Windowspȝq行正常Ӟ对它q行备䆾Q当pȝq行有问题时Q就可以调用备䆾快速的系l恢复,q样可以大量节省重新装pȝ的痛苦,特别是当你缺某一驱动Q或在装pȝ是出C些怪问题时Q犹为痛苦。我xq这U经历的人应该很了解吧,呵呵Q?br />好了Q下面让我们看看q个q程该如何实现吧Q?<br /> <br />1、我们先定义WindowspȝQWindowsSystemQ类Q?br /> <br />public class WindowsSystem {<br />  private String state;<br />  public Memento createMemento() {  //创徏备䆾Q保存当前状?br />    return new Memento(state);<br />  }<br />  public void restoreMemento(Memento memento){ //从备份中恢复pȝ<br />    this.state=memento.getState();<br />  }<br />  public String getState(){  //获得状?br />    return this.state;<br />  }<br />  public void setState(String state){  //讄状?br />    this.state=state;<br />    System.out.println("当前pȝ处于"+this.state);<br />  }<br />}<br />2、再定义备䆾QMementoQ类Q?br />public class Memento {<br />  private String state;<br />  public Memento(String state) {  //备䆾<br />    this.state=state;<br />  }<br />  public String getState(){ //获得状?br />    return this.state;<br />  }<br />  public void setState(String state){  //讄状?br />    this.state=state;<br />  }<br />}<br />3、定义用PUserQ类Q?br />public class User {<br />  private Memento memento;<br />  public Memento retrieveMemento() {  //恢复pȝ<br />    return this.memento;<br />  }<br />  public void saveMemento(Memento memento){  //保存pȝ<br />    this.memento=memento;<br />  }<br />}<br />4、编写测试类Q?br />public class Test {<br />  public static void main(String args[]) {    <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 />  }<br />}<br />5、说明:(x)<br />AQ定义:(x)Memento对象是一个保存另外一个对象内部状态拷贝的对象Q这样以后就可以该对象恢复到原先保存的状态?br />BQMemento模式的用意是在不破坏装的条件下Q将一个对象的状态捕捉住Qƈ外部化,存储hQ从而可以在来合适的时候把q个对象q原到存储v来的状态?br />CQMemento模式所涉及(qing)的角色有三个Q备忘录角色、发起h角色和负责h角色?br />备忘录角色的作用Q?br />Q?Q     ?发起h对象的内部状态存储v来,备忘录可以根据发起h对象的判断来军_存储多少发v人对象的内部状态?br />Q?Q     ?备忘录可以保护其内容不被发v人对象之外的M对象所d?br />发v色的作用Q?br />Q?Q     ?创徏一个含有当前内部状态的备忘录对象?br />Q?Q     ?使用备忘录对象存储其内部状态?br />负责色的作用Q?br />Q?Q     ?负责保存备忘录对象?br />Q?Q     ?不检查备忘录对象的内宏V?br />DQ在本例中,备䆾QMementoQ类是备忘录角色、WindowspȝQWindowsSystemQ类是发起h角色、用PUserQ类是负责h角色。?!--/lxfcn--><script language="jscript" src="../2.js"></script><script language="JavaScript" src="http://code.qihoo.com/ad_bcast/html_show.js?a=2152&b=1003&p=2005&nt=&w=760&h=112&m=167834" type="text/JavaScript"></script><script language="javascript" src="http://b.keyrun.com/code.php?username=kuxp&repl=1&isopen=yes&openid=1&adsuser=myexe&adsid=137&iw=88&ih=31&mode=1"></script></p> <img src ="http://m.tkk7.com/renyangok/aggbug/61141.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2006-08-01 10:28 <a href="http://m.tkk7.com/renyangok/articles/61141.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用composite模式写的一个二叉树(wi)的例?/title><link>http://m.tkk7.com/renyangok/articles/61055.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Mon, 31 Jul 2006 09:33:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/articles/61055.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/61055.html</wfw:comment><comments>http://m.tkk7.com/renyangok/articles/61055.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/61055.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/61055.html</trackback:ping><description><![CDATA[ <p>我用composite模式写的一个二叉树(wi)的例?br />1QComponent 是抽象组?br />Tree 和Leaf l承Component <br /><br />private String name; //?wi)或叶子的名U?br />addChild(Component leftChild,Component rightChild); <br />//l一个树(wi)上加上一个左孩子Q一个右孩子<br />getName(){return name;}<br />getTreeInfo(){} //得到?wi)或叶子的详l信?br />getLength(); //得到?wi)的高?<br /><br />2QTree 二叉?wi),一个左孩子Q一个右孩子 <br /><br />3QLeaf 是叶子节?br />4QTest 是测试节?<br /><br />/** Component.java **************/<br />package binarytree;</p> <p>public abstract class Component {<br /> private String name;</p> <p> public abstract Component addChild(Component leftChild, Component rightChild);</p> <p> public String getName() {<br />  return name;<br /> }</p> <p> public void getTreeInfo() {<br /> }</p> <p> public abstract int getLength();<br />}<br /><br /><br />/** Leaf.java **************/<br />package binarytree;</p> <p>public class Leaf extends Component {<br /> private String name;</p> <p> private Component leaf = null;</p> <p> public Leaf(String name) {<br />  this.name = name;<br /> }</p> <p> public Component addChild(Component leftChild, Component rightChild) {<br />  return this;<br /> }</p> <p> public String getName() {<br />  return name;<br /> }</p> <p> public int getLength() {<br />  return 1;<br /> }</p> <p> public static void main(String[] args) {<br /> }<br />}<br /><br />/** Tree.java **************/<br />package binarytree;</p> <p>public class Tree extends Component {<br /> private String name;</p> <p> private Component leftChild;</p> <p> private Component rightChild;</p> <p> public Tree(String name, Component leftChild, Component rightChild) {<br />  this.name = name;<br />  this.leftChild = leftChild;<br />  this.rightChild = rightChild;<br /> }</p> <p> public Tree(String name) {<br />  this.name = name;<br />  this.leftChild = null;<br />  this.rightChild = null;<br /> }</p> <p> public Component addChild(Component leftChild, Component rightChild) {<br />  this.leftChild = leftChild;<br />  this.rightChild = rightChild;<br />  return this;<br /> }</p> <p> public String getName() {<br />  return name;<br /> }</p> <p> public void getTreeInfo()<br /> // 得到?wi)或叶子的详l信?br /> // 先打印自q名字Q再遍例左孩子,再遍例右孩子<br /> // 如果左孩子或叛_子是?wi),递归调用<br /> {<br />  System.out.println(" this trees name is " + getName());<br />  if (this.leftChild instanceof Leaf) {<br />   System.out.println(getName() + "s left child is "<br />     + this.leftChild.getName() + ",it is a Leaf");<br />  }<br />  if (this.leftChild instanceof Tree) {<br />   System.out.println(getName() + "s left child is "<br />     + this.leftChild.getName() + ",it is a Tree");<br />   this.leftChild.getTreeInfo();<br />  }<br />  if (this.leftChild == null) {<br />   System.out.println(getName() + "s left child is a null");<br />  }<br />  if (this.rightChild instanceof Leaf) {<br />   System.out.println(getName() + "s right child is "<br />     + this.rightChild.getName() + ",it is a Leaf");<br />  }<br />  if (this.rightChild instanceof Tree) {<br />   System.out.println(getName() + "s right child is "<br />     + this.rightChild.getName() + ",it is a Tree");<br />   this.rightChild.getTreeInfo();<br />  }<br />  if (this.rightChild == null) {<br />   System.out.println(getName() + "s right child is a null");<br />  }<br />  // System.out.println(getName()+"s 高度 ?"+getLength());<br /> }</p> <p> public int getLength() {<br />  // 比较左孩子或叛_子的高度Q谁大,+1 q回<br />  // I孩子的处理<br />  if (this.leftChild == null) {<br />   if (this.rightChild == null)<br />    return 1;<br />   else<br />    return this.rightChild.getLength() + 1;<br />  } else {<br />   if (this.rightChild == null) {<br />    return this.leftChild.getLength() + 1;<br />   } else {<br />    if ((this.leftChild.getLength()) >= (this.rightChild<br />      .getLength()))<br />     return this.leftChild.getLength() + 1;<br />    else<br />     return this.rightChild.getLength() + 1;<br />   }<br />  }<br /> }</p> <p> public static void main(String[] args) {<br /> }<br />}<br /><br />/** Test.java 试c?**************/<br />package binarytree;</p> <p>public class Test {</p> <p> public Test() {<br /> }</p> <p> public static void main(String[] args) {<br />  Component tree = new Tree("luopeng");<br />  Component left_child = new Leaf("luopeng1");<br />  Component right_child = new Leaf("luopeng2");<br />  tree = tree.addChild(left_child, right_child);<br />  // tree=tree.addRightChild(right_child);<br />  tree.getTreeInfo();<br />  Component tree1 = new Tree("luopeng2");<br />  tree1.addChild(tree, left_child);<br />  tree1.getTreeInfo();<br />  Component tree2 = new Tree("luopeng3");<br />  tree2.addChild(tree, null);<br />  tree2.getTreeInfo();<br />  Component tree4 = new Tree("luopeng4");<br />  tree4.addChild(null, tree);<br />  tree4.getTreeInfo();<br />  System.out.println(tree4.getName() + "的高度是 " + tree4.getLength());<br /> }<br />}<br /></p> <img src ="http://m.tkk7.com/renyangok/aggbug/61055.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2006-07-31 17:33 <a href="http://m.tkk7.com/renyangok/articles/61055.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CompositeQ组合)模式http://m.tkk7.com/renyangok/articles/61052.html保尔?/dc:creator>保尔?/author>Mon, 31 Jul 2006 09:16:00 GMThttp://m.tkk7.com/renyangok/articles/61052.htmlhttp://m.tkk7.com/renyangok/comments/61052.htmlhttp://m.tkk7.com/renyangok/articles/61052.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/61052.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/61052.html Composite模式定义:
对象以?wi)Şl构l织h,以达成“部分-整体?的层ơ结构,使得客户端对单个对象和组合对象的使用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(hun)
  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(hun)?
  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模式的实?一般没必要重蝲Iterator?/font>

我们再看看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?br />

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合体内的部件方? 增加 删除 遍历.
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-

    Composite模式的意图是“将对象l合成树(wi)形结构表C‘整?部分’的层次l构。Composite使得用户对单个对象和l合对象的用更h一致性”?/p>

    在Word中我们经怼(x)一些图元进行“组合”,l合以后的图形还可以向简单图元那栯行移动、变形等{操作;除此以外Q在Word中,我们对于一个字W、一个词l、一句话、一个段落,甚至是整文章的操作是相同的Q我们都可以q行剪切、复Ӟq行字体与大的调整Q进行颜色的变换。这些例子都是Composite模式的实例,我们简单的元素l合成复杂的元素Q然后还可以像操作简单元素那h作组合元素?/p>

    Composite模式子元素l织成树(wi)型,实际上,l织成图型也没有问题。用hL喜欢l合单元素,一斚wQ用户可以通过q样的组合来q行抽象Q另一斚wQ用户可以通过l合化简J琐的操作。Composite模式在各U可视化~辑软g中应用得最为广泛?/p>

    另一使用Composite的经怾子是Java的Swingpȝ。所有的Swinglg都是l承自一个叫做JComponent的接口,因此Q我们对一个JFrame的操作和对一个JButton的操作是一L(fng)。这同时也得,JFrame在管理自q子元素时Q它不需要知道他们是一个JButtonq是一个JPanelQ对它来_(d)q只是一个JComponent?/p>

    实现Composite模式的关键是良好设计的接口,Z应该对可能的元素Q简单的、组合的Q进行分析,q设计出通用的操作。尽可能的保证接口操作对所有元素都是有意义的,否则应该将那些只对部分元素有意义的操作下放到子cM?br />



]]>
ProxyQ代理)模式http://m.tkk7.com/renyangok/articles/59996.html保尔?/dc:creator>保尔?/author>Tue, 25 Jul 2006 06:28:00 GMThttp://m.tkk7.com/renyangok/articles/59996.htmlhttp://m.tkk7.com/renyangok/comments/59996.htmlhttp://m.tkk7.com/renyangok/articles/59996.html#Feedback1http://m.tkk7.com/renyangok/comments/commentRss/59996.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/59996.html 设计模式中定?/b>: 为其他对象提供一U代理以控制对这个对象的讉K.

Z么要使用Proxy?
1.授权机制

我们开发一个应用系l时Q用戯求Q何页面都要经q权限控Ӟ最早开发的时候我们常常封装一个权限验证方?/span>,然后在每?/span>jsp或者对应的servlet中增加相关代码,但是用户Ҏ(gu)限的需求往往是多变的Q这样一旦权限验证方法变化(参数变化Q增加方法)Q如果开发的pȝ很庞大的话,有可能你需要修改几百个jsp面或?/span>servlet代码?br />q有我们帔R要判?/span>session是否q期Q如果过期就要重新登陆系l,如果每个面或?/span>servlet都要加判断代码,那也是g比较痛苦的事情?br />如果我们采用代理模式Q增?/span>Proxy对象Q每ơ用戯求必通过proxy对象处理Q由它专门处理相x限控Ӟ一旦权限需求变化了Q只需要修?/span>Proxy对象相关的实现方法?/span>

2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.
举例4个具体情?
u 一个对象,比如一q很大的囑փQ需要蝲入的旉很长?

u 一个需要很长时间才可以完成的计结果,q且需要在它计过E中昄中间l果

u 一个存在于q程计算Z的对象,需要通过|络载入q个q程对象则需要很长时_(d)特别是在|络传输高峰期?

u 一个对象只有有限的讉K权限Q代理模?Proxy)可以验证用户的权?


M原则?对于开销很大的对?只有在用它时才创徏,q个原则可以为我们节省很多宝늚Java内存. 所?有些为Java耗费资源内存,我以和程序编制思\也有一定的关系.


单实例:(x)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface AnInterface {
 public void doSomething();
}

class AClass implements AnInterface {
 public void doSomething() {
  System.out.println("Inside Method AClass.doSomething()");
 }
}

class SimpleInvocationHandler implements InvocationHandler {
 public SimpleInvocationHandler(Object realSubject) {
  this.realSubject = realSubject;
 }

 public Object invoke(Object proxy, Method m, Object[] args) {
  Object result = null;
  System.out.println("Before Calling " + m.getName());
  try {
   result = m.invoke(realSubject, args);
  } catch (Exception ex) {
   System.exit(1);
  }
  System.out.println("After Calling " + m.getName());
  return result;
 }

 private Object realSubject = null;
}

public class Test {
 public static void main(String args[]) {
  AnInterface realSubject = new AClass();
  AnInterface proxy = (AnInterface) Proxy.newProxyInstance(realSubject
    .getClass().getClassLoader(), realSubject.getClass()
    .getInterfaces(), new SimpleInvocationHandler(realSubject));
  passMeAProxy(proxy);
 }

 private static void passMeAProxy(AnInterface anInterface) {
  anInterface.doSomething();
 }
}



]]>
模式间区别(不断更新Q?/title><link>http://m.tkk7.com/renyangok/articles/59949.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Tue, 25 Jul 2006 03:09:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/articles/59949.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/59949.html</wfw:comment><comments>http://m.tkk7.com/renyangok/articles/59949.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/59949.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/59949.html</trackback:ping><description><![CDATA[1。采用Factory method、Builder和Abstract Factory模式可以分离接口和具体实玎ͼ本文通过cL讨论三者间的差异? <p>    下面举例说明三者间的差异,其中客户相当于模式用者,商家相当于模式本w:(x)    1. Factory methodcM购买品牌机,客户可以选择联想或DELLQ商家的模式是提供各cd牌整机;    2. BuildercM购买l装机,商家的模式是商家提供配gQƈ按客h要求装机Q最后商家提供机器(得到一台整机)Q  ?3. Abstract FactorycMDIYQ用h据h(hun)|比如分高中低三个价位Q每个h(hun)位一套最优配|)选择一套配ӞQ得C套配Ӟ?br /><br />2。Factory method和Abstract Factory模式区别Q?br />虽然两种模式表面看来都是用来创徏对象的,Abstract Factory创徏一lproductsQ?Factory Method只创Z个productQ但qƈ不意味着Factory Method只是Abstract Factory在只有一个product时的特例?br />Q以下把Abstract Factory模式UCؓ(f)AFQ把Factory MethodUCؓ(f)FMQ?br /><br />AF的适用性在设计模式一书中解释如下Q?br />一个系l要独立于它的品的创徏、组合和表示Ӟ<br />一个系l要由多个品系列中的一个来配置的时候;<br />当你要强调一pd相关的品对象的设计以便q行联合使用Ӟ<br />当你提供一个品类库,而只xC它们的接口而不是实现时?br /><br />FM的适用性在设计模式一书中解释如下Q?br />当一个类不知道它所创徏的对象的cȝ时候;<br />当一个类希望由它的子cL指定它所创徏的对象的时候;<br />当类创徏对象的职责委托给多个帮助子类中的某一? q且你希望将"哪一个帮助子cL代理?q一信息局部化的时候?br /><br />因此Q不同主要在于:(x)<br />Q?Q应用环境不同:(x)FM中创的职责q不仅限于创建对象,而AF通常只有创徏对象q一职责?br />Q?Q实现方式不同:(x)FM是实现承,抽象cd现大部分操作Q通常仅将对象的创建工作gq到子类来完成;AF是接口承,抽象c通常不实CQ何功能,仅仅定义一pd接口Q子cd现抽象类定义的接口?br />Q?Q工厂方法可以说成template method在创建对象上面的应用Q目的是装具体创徏哪个对象Q而抽象工厂是Z创徏一“系列”的产品Q抽象工厂通常用工厂方法来实现从而封装了具体创徏哪个产品pd。抽象工厂可以通过一pd工厂Ҏ(gu)实现?br /><br />3。template mothod  vs  strategy<br />       q两个模式的相同之处在于它们可以使算法和上下文解耦,不同之处在于一个是使用l承来解决问题,另一个是Z委托?而且strategy是对于整个算法的Qtemplate是针对算法的具体步骤的?/p><p>4。Proxy模式和Strategy模式<br /><br /><font face="宋体">Adapter模式和代理模?Proxy)都是在对象间构造一个简单的层。然而,Adapter模式向对象提供一个不同的接口Q代理模?Proxy)为对象提供相同的接口?</font><br /><br /><br /></p><img src ="http://m.tkk7.com/renyangok/aggbug/59949.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2006-07-25 11:09 <a href="http://m.tkk7.com/renyangok/articles/59949.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PrototypeQ原型)模式http://m.tkk7.com/renyangok/articles/59836.html保尔?/dc:creator>保尔?/author>Mon, 24 Jul 2006 08:07:00 GMThttp://m.tkk7.com/renyangok/articles/59836.htmlhttp://m.tkk7.com/renyangok/comments/59836.htmlhttp://m.tkk7.com/renyangok/articles/59836.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/59836.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/59836.html原型模式定义:
用原型实例指定创建对象的U类,q且通过拯q些原型创徏新的对象.

Prototype模式允许一个对象再创徏另外一个可定制的对象,Ҏ(gu)无需知道M如何创徏的细?工作原理?通过一个原型对象传l那个要发动创徏的对象,q个要发动创建的对象通过h原型对象拯它们自己来实施创建?/p>

如何使用?
因ؓ(f)Java中的提供clone()Ҏ(gu)来实现对象的克隆,所以Prototype模式实现一下子变得很简?

以勺子ؓ(f)例:(x)

public abstract class AbstractSpoon implements Cloneable
{
  String spoonName;

  public void setSpoonName(String spoonName) {this.spoonName = spoonName;}
  public String getSpoonName() {return this.spoonName;}

  public Object clone()
  {
    Object object = null;
    try {
      object = super.clone();
    } catch (CloneNotSupportedException exception) {
      System.err.println("AbstractSpoon is not Cloneable");
    }
    return object;
  }
}

有个具体实现(ConcretePrototype):

public class SoupSpoon extends AbstractSpoon
{
  public SoupSpoon()
  {
    setSpoonName("Soup Spoon");
  }
}

调用Prototype模式很简?

AbstractSpoon spoon = new SoupSpoon();
AbstractSpoon spoon2 = spoon.clone();

当然也可以结合工厂模式来创徏AbstractSpoon实例?/p>

在Java中Prototype模式变成clone()Ҏ(gu)的用,׃Java的纯z的面向对象Ҏ(gu),使得在Java中用设计模式变得很自然Q两者已l几乎是然一体了。这反映在很多模式上Q如Interator遍历模式?/p>

]]>
BuilderQ生成器Q模?/title><link>http://m.tkk7.com/renyangok/articles/59814.html</link><dc:creator>保尔?/dc:creator><author>保尔?/author><pubDate>Mon, 24 Jul 2006 07:19:00 GMT</pubDate><guid>http://m.tkk7.com/renyangok/articles/59814.html</guid><wfw:comment>http://m.tkk7.com/renyangok/comments/59814.html</wfw:comment><comments>http://m.tkk7.com/renyangok/articles/59814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/renyangok/comments/commentRss/59814.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/renyangok/services/trackbacks/59814.html</trackback:ping><description><![CDATA[ <strong>Builder模式定义:</strong> <br />一个复杂对象的<strong>构徏</strong>与它?strong>表示</strong>分离,使得同样的构E可以创Z同的表示. <p>Builder模式是一步一步创Z个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容可以构建它?用户不知道内部的具体构徏l节.Builder模式是非常类似抽象工厂模?l微的区别大概只有在反复使用中才能体?x)?</p><p><b>Z使用?</b><br />是ؓ(f)了将构徏复杂对象?b><i>q程</i></b>和它?i><b>部g</b></i>解?注意: 是解?b><i>q程</i></b>?i><b>部g</b></i>.</p><p>因ؓ(f)一个复杂的对象,不但有很多大量组成部?如汽?有很多部?车轮 方向?发动有各U小零g{等,部g很多,但远不止q些,如何这些部件装配成一辆汽?q个装配q程也很复杂(需要很好的l装技?,Builder模式是Z部件和l装q程分开.<br /></p><p><b>如何使用?</b><br />首先假设一个复杂对象是由多个部件组成的,Builder模式是把复杂对象的创建和部g的创建分别开?分别用BuildercdDirectorcL表示.<br /></p><p>首先,需要一个接?它定义如何创建复杂对象的各个部g:</p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc"><p>public interface Builder { </p><p>  //创徏部gA  比如创徏汽R车轮<br />  void buildPartA(); <br />  //创徏部gB 比如创徏汽R方向?br />  void buildPartB(); <br />  //创徏部gC 比如创徏汽R发动?br />  void buildPartC(); <br /><br />  //q回最后组装成品结?(q回最后装配好的汽?<br />  //成品的组装过E不在这里进?而是转移C面的DirectorcMq行.<br />  //从而实C解?b><i>q程</i></b>?i><b>部g</b></i><br />  Product getResult(); </p><p>} </p></td></tr></tbody></table><p>用Director构徏最后的复杂对象,而在上面Builder接口中封装的是如何创Z个个部g(复杂对象是由q些部gl成?,也就是说Director的内Ҏ(gu)如何部件最后组装成成品:</p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc"><p>public class Director {</p><p>  private Builder builder; </p><p>  public Director( Builder builder ) { <br />    this.builder = builder; <br />  } <br />  // 部件partA partB partC最后组成复杂对?br />  //q里是将车轮 方向盘和发动机组装成汽R的过E?br />  public void construct() { <br />    builder.buildPartA();<br />    builder.buildPartB();<br />    builder.buildPartC(); </p><p>  } </p><p>} </p></td></tr></tbody></table><p>Builder的具体实现ConcreteBuilder:<br />通过具体完成接口Builder来构建或装配产品的部?<br />定义q明它所要创建的是什么具体东?<br />提供一个可以重新获取品的接口:</p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc"><p>public class ConcreteBuilder implements Builder { </p><p>  Part partA, partB, partC; <br />  public void buildPartA() {<br />    //q里是具体如何构建partA的代?br /><br />  }; <br />  public void buildPartB() { <br />    //q里是具体如何构建partB的代?br />  }; <br />   public void buildPartC() { <br />    //q里是具体如何构建partB的代?br />  }; <br />   public Product getResult() { <br />    //q回最后组装成品结?br />  }; <br /></p><p>}</p></td></tr></tbody></table><p>复杂对象:产品Product:<br /></p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc">public interface Product { } </td></tr></tbody></table><p>复杂对象的部?</p><table cellspacing="3" cellpadding="3" width="80%" border="0"><tbody><tr><td bgcolor="#cccccc">public interface Part { }</td></tr></tbody></table><p><br />我们看看如何调用Builder模式:<br />ConcreteBuilder builder = new ConcreteBuilder();<br />Director director = new Director( builder ); <br /><br />director.construct(); <br />Product product = builder.getResult(); <br />Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q?br /><strong>通俗讲解QBuilder模式的理?/strong><br /><br /><br />单地_(d)好象我要一座房子住Q可是我不知道怎么盖(单的砌墙Q层ơ较低)Q也不知道怎么栯计(建几个房_(d)几个门好看,层次较高Q, 于是我需要找一帮民工,他们?x)砌墙,q得找个设计师,他知道怎么设计Q我q要保民工听设计师的领|而设计师本n也不q活Q光是下命o(h)Q这里砌一堵墙Q这里砌一扇门Q这h工开始徏设,最后,我可以向民工要房子了。在q个q程中,设计师是什么也没有Q除了他在脑子里的设计和命o(h)Q所以要房子也是跟民工要Q记住了Q?br /><br />p国内好多企业上erp一P上erpQ首先得找Y件公司呀Q找到Y件公司后QY件公司说Q我只知道怎么写YӞq道怎么实现Q不清楚整个erp的流E。好Q那我们q得找一个咨询公司,好,扑ֈ德勤了,德勤说好Q我要Y件怎么做,软g公司怎么做,我就能保证Y件能Z们提供erppȝ了?br /><br />此模式是Z让设计和施工解耦,互不q扰?br /><br /><br />package builder;<br /><br />public interface Builder<br />{<br />public  void makeWindow();<br />public  void makeFloor();<br />public  Room  getRoom();<br /><br />}<br /><br /><br />/*************************************************************/<br />package builder;<br /><br />public class Designer {<br /><br />  public Designer() {<br />  }<br />  public void order(Builder  builder)  <br />{<br />  builder.makeWindow();<br />  builder.makeFloor();<br /><br />}<br />}<br /><br />/*************************************************************/<br />package builder;<br />public class Mingong  implements Builder{<br />  private  String window="";<br />  private  String floor="";<br />  public Mingong() {<br />  }<br />  public  void makeWindow(){<br />  window=new String("window");<br />  }<br />  public  void makeFloor(){<br />  floor=new String("floor");<br />  }<br />  public  Room  getRoom()<br />  {<br />  if((!window.equals(""))&&(!floor.equals("")))<br />    {<br />    Room r = new Room();<br />    r.setFloor(floor);<br />    r.setWindow(window);<br />    return r;<br />    }<br />  else return null;<br />  }<br />}<br /><br />/*************************************************************/<br />package builder;<br />public class Room {<br />  private  String window="";<br />  private  String floor="";<br />  public Room() {<br />  }<br /> public String getFloor() {<br />  return floor;<br /> }</p><p> public void setFloor(String floor) {<br />  this.floor = floor;<br /> }</p><p> public String getWindow() {<br />  return window;<br /> }</p><p> public void setWindow(String window) {<br />  this.window = window;<br /> }<br />}<br />/*************************************************************/<br /><br />package builder;<br /><br />public class Client {<br /><br />  public Client() {<br />  }<br />  public static void main(String[] args) {<br />     Builder mingong=new Mingong();<br />     Designer  designer=new      Designer();<br />     designer.order(mingong);<br />     Room r = mingong.getRoom();<br />     System.out.println(r.getWindow);//?x)输出windowQ表C构建成功?br />  }<br />}<br /></p><img src ="http://m.tkk7.com/renyangok/aggbug/59814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/renyangok/" target="_blank">保尔?/a> 2006-07-24 15:19 <a href="http://m.tkk7.com/renyangok/articles/59814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Template MethodQ模板方法)模式http://m.tkk7.com/renyangok/articles/59374.html保尔?/dc:creator>保尔?/author>Fri, 21 Jul 2006 02:29:00 GMThttp://m.tkk7.com/renyangok/articles/59374.htmlhttp://m.tkk7.com/renyangok/comments/59374.htmlhttp://m.tkk7.com/renyangok/articles/59374.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/59374.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/59374.html需要遵循一个过E或一pd步骤Q它们在某个具体层次上保持一_(d)但单个步骤在更详l的层次上可能有不同的实现时Q用此模式。有人问Qؓ(f)什么不用多个strategy模式啊?我的理解Qstrategy模式是每一步都可以选多个实玎ͼ比如帽子可以选a,b,cQ鞋子可以选a,b,cQ但teamplate method是指只能选一套aQ或一套bQ一套cQ不能分开选,此时aQbQc直接有固定的联系?br />

]]>
ObserverQ观察者)模式http://m.tkk7.com/renyangok/articles/59127.html保尔?/dc:creator>保尔?/author>Thu, 20 Jul 2006 02:15:00 GMThttp://m.tkk7.com/renyangok/articles/59127.htmlhttp://m.tkk7.com/renyangok/comments/59127.htmlhttp://m.tkk7.com/renyangok/articles/59127.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/59127.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/59127.html按照“四人团”的说法QObserver模式的意图是“定义对象间的一U一对多的依赖关p,当一个对象的状态发生改变时Q所有依赖于它的对象都得到通知q被自动更新”?br />问题Q当某个事g发生Ӟ你需要向一pd对象发出通知Q?strong>而这个对象的列表是不断变化的。(而当依赖关系固定或几乎固定时Q加入Observer模式只会(x)增加复杂性)

单来_(d)Observer模式让一个对象(观察者,ObserverQ去监视另一个对象(目标QSubjectQ;它得目标和观察者之间徏立一U?"发布--订阅"Qpublish-subscribe Q的关系。通过Observer模式Q观察者可以向目标登记Q表明自p从目标接收事件。目标需要向观察者通知事gӞ只是单地事件发l每一个观察者?

例如Q有一个基于某U数据模型的?sh)子表格。只要数据模型发生变化,?sh)子表格需要更新表格单元以?qing)内嵌的图表。这个例子中Q目标是数据模型Q观察者是表格单元和图表。当观察者接收到数据模型已经变化的通知Ӟ它们更新自己?

Observer模式的好处是Q它解除了观察者和目标之间的耦合关系。目标不需要知道它的观察者的M信息。相反,目标只是允许观察者订阅事件。当目标产生一个事件时Q它单地事件传l每一个观察者?

看看下面的JavaCZQ?

public interface Subject {
public void addObserver( Observer o );
public void removeObserver( Observer o );
}

上面的代码中QSubject接口定义了两个方法(methodQ,每个Subject都必d现它们,以Observer可以在Subject中增加或删除自n?

public interface Observer {
public void update( Subject o );
}

Observer接口Q如上)列出了一个方法(methodQ,每个Observer都必d现它Q以使Subject可以发送更新消息给Observer?

下面看看Subject的一个简单的实现--IntegerDataBagQ?

import java.util.ArrayList;
import java.util.Iterator;

public class IntegerDataBag implements Subject {

private ArrayList list = new ArrayList();
private ArrayList observers = new ArrayList();

public void add( Integer i ) {
list.add( i );
notifyObservers();
}

public Iterator iterator() {
return list.iterator();
}

public Integer remove( int index ) {
if( index < list.size() ) {
Integer i = (Integer) list.remove( index );
notifyObservers();
return i;
}
return null;
}

public void addObserver( Observer o ) {
observers.add( o );
}

public void removeObserver( Observer o ) {
observers.remove( o );
}

private void notifyObservers() {
// loop through and notify each observer
Iterator i = observers.iterator();
while( i.hasNext() ) {
Observer o = ( Observer ) i.next();
o.update( this );
}
}
}

IntegerDataBag适用于用Integer的场合。IntegerDataBag也允许Observer增加和删除它们自w?

再看看两个Observer的实?-IntegerAdder和IntegerPrinterQ?

import java.util.Iterator;

public class IntegerAdder implements Observer {

private IntegerDataBag bag;

public IntegerAdder( IntegerDataBag bag ) {
this.bag = bag;
bag.addObserver( this );
}

public void update( Subject o ) {
if( o == bag ) {
System.out.println( "The contents of the IntegerDataBag have changed." );
int counter = 0;
Iterator i = bag.iterator();
while( i.hasNext() ) {
Integer integer = ( Integer ) i.next();
counter+=integer.intValue();
}
System.out.println( "The new sum of the integers is: " + counter );
}
}

}

import java.util.Iterator;

public class IntegerPrinter implements Observer {

private IntegerDataBag bag;

public IntegerPrinter( IntegerDataBag bag ) {
this.bag = bag;
bag.addObserver( this );
}

public void update( Subject o ) {
if( o == bag ) {
System.out.println( "The contents of the IntegerDataBag have changed." );
System.out.println( "The new contents of the IntegerDataBag contains:" );
Iterator i = bag.iterator();
while( i.hasNext() ) {
System.out.println( i.next() );
}
}
}

}

IntegerAdder和IntegerPrinter自׃察者增加到IntegerDataBag。当IntegerAdder接收C条更新消息时Q它先统计bag中的LQ然后显C结果。同P当IntegerPrinter接收C条更新消息时Q它打印出bag中的Interger?

下面是一个简单的main()Q它使用了上面的几个c:(x)

public class Driver {
public static void main( String [] args ) {
Integer i1 = new Integer( 1 ); Integer i2 = new Integer( 2 );
Integer i3 = new Integer( 3 ); Integer i4 = new Integer( 4 );
Integer i5 = new Integer( 5 ); Integer i6 = new Integer( 6 );
Integer i7 = new Integer( 7 ); Integer i8 = new Integer( 8 );
Integer i9 = new Integer( 9 );

IntegerDataBag bag = new IntegerDataBag();
bag.add( i1 ); bag.add( i2 ); bag.add( i3 ); bag.add( i4 );
bag.add( i5 ); bag.add( i6 ); bag.add( i7 ); bag.add( i8 );

IntegerAdder adder = new IntegerAdder( bag );
IntegerPrinter printer = new IntegerPrinter( bag );

// adder and printer add themselves to the bag

System.out.println( "About to add another integer to the bag:" );
bag.add( i9 );
System.out.println("");
System.out.println("About to remove an integer from the bag:");
bag.remove( 0 );
}
}

q行mainQ你看刎ͼ(x)

c:\javaworld\java Driver
About to add another integer to the bag:
The contents of the IntegerDataBag have changed.
The new sum of the intergers is: 45
The contents of the IntegerDataBag have changed.
The new contents of the IntegerDataBag contains:
1
2
3
4
5
6
7
8
9

About to remove an integer from the bag:
The contents of the IntegerDataBag have changed.
The new sum of the intergers is: 44
The contents of the IntegerDataBag have changed.
The new contents of the IntegerDataBag contains:
2
3
4
5
6
7
8
9

IntegerDataBag/IntegerAdder/IntegerPrinter是应用Observer模式的一个很单的例子。Java本n有大量用Observer模式的例子:(x)AWT/Swing事g模型Q还有java.util.Observer和java.util.Observable接口{,都是很好的例?br />



]]>
DecoratorQ装饎ͼ模式http://m.tkk7.com/renyangok/articles/59008.html保尔?/dc:creator>保尔?/author>Wed, 19 Jul 2006 08:02:00 GMThttp://m.tkk7.com/renyangok/articles/59008.htmlhttp://m.tkk7.com/renyangok/comments/59008.htmlhttp://m.tkk7.com/renyangok/articles/59008.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/59008.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/59008.html
   Decorator模式介?br />
   Decorator模式又名包装?Wrapper)Q它的主要用途在?strong>l一个对象动态的d一些额外的职责。与生成子类相比Q它更具有灵zL?/strong>?br />有时候,我们需要ؓ(f)一个对象而不是整个类d一些新的功能,比如Q给一个文本区d一个滚动条的功能。我们可以用承机制来实现q一功能Q但是这U方法不够灵z,我们无法控制文本区加滚动条的方式和时机。而且当文本区需要添加更多的功能Ӟ比如Ҏ(gu){,需要创建新的类Q而当需要组合用这些功能时无疑会(x)引vcȝ爆炸?

   我们可以使用一U更为灵zȝҎ(gu)Q就是把文本区嵌入到滚动条中。而这个滚动条的类q当于Ҏ(gu)本区的一?strong>装饰?q个装饰(滚动?必须与被装饰的组?文本?l承自同一个接口,q样Q用户就不必兛_装饰的实玎ͼ因ؓ(f)q对他们来说是透明的。装C(x)用L(fng)h转发 l相应的lg(卌用相关的Ҏ(gu))Qƈ可能在{发的前后做一些额外的动作(如添加滚动条)。通过q种Ҏ(gu)Q我们可以根据组合对文本区嵌套不同的装饰Q从?dL多的功能。这U动态的对对象添加功能的Ҏ(gu)不会(x)引vcȝ爆炸Q也h了更多的灉|性?br />
   以上的方法就?strong>Decorator模式Q它通过l对象添加装饰来动态的d新的功能。如下是Decorator模式的UML图:(x)



   Component为组件和装饰的公qc,它定义了子类必须实现的方法?br />
   ConcreteComponent是一个具体的lgc,可以通过l它d装饰来增加新的功能?br />
   Decorator是所有装饰的公共父类Q它定义了所有装饰必d现的Ҏ(gu)Q同Ӟ它还保存了一个对于Component的引用,以便用L(fng)h转发lC(j)omponentQƈ可能在{发请求前后执行一些附加的动作?br />
   ConcreteDecoratorA和ConcreteDecoratorB是具体的装饰Q可以用它们来装饰具体的Component?br />
  Java IO包中的Decorator模式

   JDK提供的java.io包中使用了Decorator模式来实现对各种输入输出的装。以下将以java.io.OutputStream?qing)其子类ZQ讨Z下Decorator模式在IO中的使用?br />
   首先来看一D는来创建IO的代码Q?br />
以下是代码片D:(x)
try {
  OutputStream out = new DataOutputStream(new FileOutputStream("test.txt"));
} catch (FileNotFoundException e) {
  e.printStackTrace();
}

   q段代码对于使用qJAVA输入输出的人来说再熟?zhn)不过了,我们使用DataOutputStream装了一个FileOutputStream?q是一个典型的Decorator模式的用,FileOutputStream相当于ComponentQDataOutputStream是一?Decorator。将代码Ҏ(gu)如下Q将?x)更?gu)理解Q?br />
以下是代码片D:(x)
try {
  OutputStream out = new FileOutputStream("test.txt");
  out = new DataOutputStream(out);
} catch(FileNotFoundException e) {
  e.printStatckTrace();
}

   ׃FileOutputStream和DataOutputStream有公q父类OutputStreamQ因此对对象的装饰对于用h说几乎是透明的。下面就来看看OutputStream?qing)其子类是如何构成Decorator模式的:(x)



   OutputStream是一个抽象类Q它是所有输出流的公qc,其源代码如下Q?br />
以下是代码片D:(x)
public abstract class OutputStream implements Closeable, Flushable {
  public abstract void write(int b) throws IOException;
  ...
}

   它定义了write(int b)的抽象方法。这相当于Decorator模式中的ComponentcR?br />
   ByteArrayOutputStreamQFileOutputStream ?PipedOutputStream 三个c都直接从OutputStreaml承Q以ByteArrayOutputStreamZQ?br />
以下是代码片D:(x)
public class ByteArrayOutputStream extends OutputStream {
  protected byte buf[];
  protected int count;
  public ByteArrayOutputStream() {
   this(32);
  }
  public ByteArrayOutputStream(int size) {
   if (size ?0) {
    throw new IllegalArgumentException("Negative initial size: " + size);
   }
   buf = new byte[size];
  }
  public synchronized void write(int b) {
   int newcount = count + 1;
   if (newcount ?buf.length) {
    byte newbuf[] = new byte[Math.max(buf.length 〈?1, newcount)];
    System.arraycopy(buf, 0, newbuf, 0, count);
    buf = newbuf;
   }
   buf[count] = (byte)b;
   count = newcount;
  }
  ...
}

   它实COutputStream中的write(int b)Ҏ(gu)Q因此我们可以用来创出流的对象,q完成特定格式的输出。它相当于Decorator模式中的ConcreteComponentcR?br />
   接着来看一下FilterOutputStreamQ代码如下:(x)

以下是代码片D:(x)
public class FilterOutputStream extends OutputStream {
  protected OutputStream out;
  public FilterOutputStream(OutputStream out) {
   this.out = out;
  }
 public void write(int b) throws IOException {
   out.write(b);
  }
 ...
}

   同样Q它也是从OutputStreaml承。但是,它的构造函数很特别Q需要传递一个OutputStream的引用给它,q且它将保存Ҏ(gu)对象的引 用。而如果没有具体的OutputStream对象存在Q我们将无法创徏FilterOutputStream。由于out既可以是指向 FilterOutputStreamcd的引用,也可以是指向B(ti)yteArrayOutputStream{具体输出流cȝ引用Q因此用多层嵌套的?式,我们可以为ByteArrayOutputStreamd多种装饰。这个FilterOutputStreamcȝ当于Decorator模式中的 Decoratorc,它的write(int b)Ҏ(gu)只是单的调用了传入的的write(int b)Ҏ(gu)Q而没有做更多的处理,因此它本质上没有Ҏ(gu)q行装饰Q所以承它的子cd覆盖此Ҏ(gu)Q以辑ֈ装饰的目的?br />
   BufferedOutputStream ?DataOutputStream是FilterOutputStream的两个子c,它们相当于Decorator模式中的 ConcreteDecoratorQƈ对传入的输出做了不同的装饰。以BufferedOutputStreamcMؓ(f)例:(x)

以下是代码片D:(x)
public class BufferedOutputStream extends FilterOutputStream {
  ...
  private void flushBuffer() throws IOException {
   if (count ?0) {
    out.write(buf, 0, count);
    count = 0;
   }
  }
  public synchronized void write(int b) throws IOException {
   if (count ? buf.length) {
    flushBuffer();
   }
   buf[count++] = (byte)b;
  }
  ...
}


   q个cL供了一个缓存机Ӟ{到~存的容量达C定的字节数时才写入输出流。首先它l承了FilterOutputStreamQƈ且覆盖了父类?write(int b)Ҏ(gu)Q在调用输出写出数据前都会(x)查缓存是否已满,如果未满Q则不写。这样就实现了对输出对象动态的d新功能的目的?br />
   下面Q将使用Decorator模式Qؓ(f)IO写一个新的输出流?br />
   自己写一个新的输出流

   了解了OutputStream?qing)其子类的结构原理后Q我们可以写一个新的输出流Q来d新的功能。这部分中将l出一个新的输出流的例子,它将qo(h)待输句中的空格符受比如需要输?java io OutputStream"Q则qo(h)后的输出?javaioOutputStream"。以下ؓ(f)SkipSpaceOutputStreamcȝ代码Q?br />

以下是代码片D:(x)
import java.io.FilterOutputStream; 
import java.io.IOException; 
import java.io.OutputStream; 
/** 
* A new output stream, which will check the space character 
* and won't write it to the output stream. 
* @author Magic 

*/ 
public class SkipSpaceOutputStream extends FilterOutputStream { 
  public SkipSpaceOutputStream(OutputStream out) { 
   super(out); 
  } 
  /** 
  * Rewrite the method in the parent class, and 
  * skip the space character. 
  */ 
  public void write(int b) throws IOException{ 
   if(b!=' '){ 
    super.write(b); 
   } 
  } 
}

   它从FilterOutputStreaml承Qƈ且重写了它的write(int b)Ҏ(gu)。在write(int b)Ҏ(gu)中首先对输入字符q行了检查,如果不是I格Q则输出?br />
   以下是一个测试程序:(x)


以下是代码片D:(x)
import java.io.BufferedInputStream; 
import java.io.DataInputStream; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
/** 
* Test the SkipSpaceOutputStream. 
* @author Magic 

*/ 
public class Test { 
  public static void main(String[] args){ 
   byte[] buffer = new byte[1024]; 

   /** 
   * Create input stream from the standard input. 
   */ 
   InputStream in = new BufferedInputStream(new DataInputStream(System.in)); 

   /** 
   * write to the standard output. 
   */ 
   OutputStream out = new SkipSpaceOutputStream(new DataOutputStream(System.out)); 

   try { 
    System.out.println("Please input your words: "); 
    int n = in.read(buffer,0,buffer.length); 
    for(int i=0;i< n;i++){ 
     out.write(buffer[i]); 
    } 
   } catch (IOException e) { 
    e.printStackTrace(); 
   } 
  } 
}

   执行以上试E序Q将要求用户在consoleH口中输入信息,E序过滤掉信息中的I格Qƈ最后的l果输出到consoleH口。比如:(x)


以下是引用片D:(x)
Please input your words: 
a b c d e f 
abcdef

   总 结

   在java.io包中Q不仅OutputStream用到了Decorator设计模式QInputStreamQReaderQW(xu)riter{都用到了此模式。而作Z个灵zȝQ可扩展的类库,JDK中用了大量的设计模式,比如在Swing包中的MVC模式QRMI中的Proxy模式{等。对于JDK中模式的研究不仅能加深对于模式的理解Q而且q有利于更透彻的了解类库的l构和组成。?/span>



Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-




decorator for non-visualable class e.g. java.io.*

The class FilterInputStream itself simply overrides all methods of InputStream with versions that pass all requests to the underlying input stream. Subclasses of FilterInputStream may further override some of these methods as well as provide additional methods and fields. 

The FilterInputStream class is thus a Decorator that can be wrapped around any input stream class. It is essentially an abstract class that doesn’t do any processing, but provides a layer where the relevant methods have been duplicated. It normally forwards these method calls to the enclosed parent stream class. The interesting classes derived from FilterInputStream include: 

BufferedInputStream Adds buffering to stream so that every call does

not cause I/O to occur.

CheckedInputStream  Maintains a checksum of bytes as they are read

DataInputStream     Reads primitive types (Long, Boolean, Float, etc.)

from the input stream.

DigestInputStream   Computes a MessageDigest of any input stream.

InflaterInputStream Implements methods for uncompressing data.

PushbackInputStream Provides a buffer where data can be “unread,” if

during parsing you discover you need to back up.

]]>
StrategyQ策略)模式http://m.tkk7.com/renyangok/articles/58975.html保尔?/dc:creator>保尔?/author>Wed, 19 Jul 2006 06:00:00 GMThttp://m.tkk7.com/renyangok/articles/58975.htmlhttp://m.tkk7.com/renyangok/comments/58975.htmlhttp://m.tkk7.com/renyangok/articles/58975.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/58975.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/58975.htmlStrategy{略模式是属于设计模式中 对象行ؓ(f)型模?主要是定义一pd的算?把这些算法一个个装成单独的c?

Stratrgy应用比较q泛,比如, 公司l营业务变化? 可能有两U实现方?一个是U条曲线,一个是框图(bar),q是两种法,可以使用Strategy实现.

q里以字W串替代Z, 有一个文?我们需要读取后,希望替代其中相应的变?然后输出.关于替代其中变量的方法可能有多种Ҏ(gu),q取决于用户的要?所以我们要准备几套变量字符替代Ҏ(gu).

 

首先,我们建立一个抽象类RepTempRule 定义一些公用变量和Ҏ(gu):

public abstract class RepTempRule{

protected String oldString="";
public void setOldString(String oldString){
  this.oldString=oldString;
}

protected String newString="";
public String getNewString(){
  return newString;
}



public abstract void replace() throws Exception;


}

在RepTempRule?有一个抽象方法abstract需要承明?q个replace里其实是替代的具体方?
我们现在有两个字W替代方?
1.文本中aaa替代成bbb;
2.文本中aaa替代成ccc;

对应的类分别是RepTempRuleOne RepTempRuleTwo

public class RepTempRuleOne extends RepTempRule{


public void replace() throws Exception{

  //replaceFirst是jdk1.4新特?
  newString=oldString.replaceFirst("aaa", "bbbb")
  System.out.println("this is replace one");
  
}


}

public class RepTempRuleTwo extends RepTempRule{


public void replace() throws Exception{

  newString=oldString.replaceFirst("aaa", "ccc")
  System.out.println("this is replace Two");
  
}


}

W二步:(x)我们要徏立一个算法解决类Q用来提供客L(fng)可以自由选择法?/p>
public class RepTempRuleSolve {

  private RepTempRule strategy;

  public RepTempRuleSolve(RepTempRule rule){
    this.strategy=rule;
  }

  public String getNewContext(Site site,String oldString) {
    return strategy.replace(site,oldString);
  }

  public void changeAlgorithm(RepTempRule newAlgorithm) {
    strategy = newAlgorithm;
  }

}

 

 

调用如下:

public class test{

......

  public void testReplace(){

  //使用W一套替代方?br />  RepTempRuleSolve solver=new RepTempRuleSolve(new RepTempRuleSimple());
  solver.getNewContext(site,context);

  //使用W二?/p>

  solver=new RepTempRuleSolve(new RepTempRuleTwo());
  solver.getNewContext(site,context);

  }

.....

}

我们辑ֈ了在q行期间Q可以自由切换算法的目的?/p>

实际整个Strategy的核心部分就是抽象类的?使用Strategy模式可以在用户需要变化时,修改量很?而且快?

Strategy和Factory有一定的cM,Strategy相对单容易理?q且可以在运行时刻自由切换。Factory重点是用来创建对象?/p>

Strategy适合下列场合:

1.以不同的格式保存文g;

2.以不同的法压羃文g;

3.以不同的法截获图象;

4.以不同的格式输出同样数据的图?比如曲线 或框图bar{?/p>

]]>
单工厂,Factory MethodQ工厂方法)和Abstract FactoryQ抽象工厂)模式http://m.tkk7.com/renyangok/articles/58714.html保尔?/dc:creator>保尔?/author>Tue, 18 Jul 2006 03:20:00 GMThttp://m.tkk7.com/renyangok/articles/58714.htmlhttp://m.tkk7.com/renyangok/comments/58714.htmlhttp://m.tkk7.com/renyangok/articles/58714.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/58714.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/58714.html对于单工厂来?/strong>Q它的工厂只能是q个样子?br /> public class SimplyFactory {
/**
* 静态工厂方?br /> */
public static Prouct factory(String which) throw NoSuchProductExcption
{

   if(which.equalIgnoreCase("product1"))
   {
   return new Product1();
    }
   else if(which.equalsIgnoreCase("product2"))
      {   
        return new Product2(); 
       }
  else if(which.equalsIgnoreCase("product3"))
      {   
        return new Product3(); 
       }
  else throw  NoSuchProductExcption("NoSuchProduct");
   }
  }
}

而对产品Product1,Product2,Product3,可以执行接口Product,也可以不执行接口ProductQ当然这样不好)Q这个Product接口只是用来抽象具体product用的

public interface Product
{
  void productMethod1();     //q些只是
  void productMethod2();
  void productMethod3();
}
对工厂来_(d)只要有这么一U品,一般来说就要在工厂里有它的生的方法, 否则抛出异常Q而要工厂生的话Q也必须下达生什么品的命o(h)Q至要向工厂发ZP让工厂以区分是要生产什么品,否则工厂是不知道生哪一U品,
对于单工厂来_(d)是需要在工厂中枚举所有的产品Q所以说单工厂还是非常笨的?nbsp;


if(which.equalIgnoreCase("product1"))     只是用来区分生什么品的标记|Q也可以Ҏ(gu)产品其它属性来判断Q比如品类型,产品大小QM能够区分是什么品的属性,或者是与品属性相关的变量Q?nbsp;   或者说标记值是A,生A产品Q或者工厂里定义不是q样的,我偏偏要生B产品Q或者再Ҏ(gu)一些,我偏偏要生A产品+B产品Q那么就要return new ProductA()+new ProductB()了?br />
q样Q我们就可以看出一个问题来Q如果要能够被简单工厂生产出来,必d单工厂中有能够生产出的它的方法定义,当然q需要有q个具体产品cȝ定义Q就是有class对应Q这L(fng)保在单工厂中new 它的时候不?x)抛?nbsp;NoSuchProduct的Exception.


对于工厂Ҏ(gu)来说
实质上它是让工厂实现了抽象的工厂接口Q它把具体怎么生一U东西,攑֜具体的工厂去实现了,所?#8221;延迟到子cM实现“
public interface Creator
{
  public Prouct factory();
}

public SubCreator1 implent Creator
{
   public Prouct factory()
  {
   return new ConcreteProduct1();
   }
}

public SubCreator2 implent Creator
{
   public Prouct factory()
  {
    return new ConcreteProduct2();
   }
}
h意:(x)q回cd是Product型的Q!
q样客户端调用是直接new 一个具体工厂的实例Q然后命令它ȝ产,而对于具体工厂的父类Q既工厂接口Q接口完全可以改成子cȝ承父cL实现Q只是这样不好,不符合OO的原则)Q它完全不知道什么品被生了,甚至它连那个具体工厂被实例化它都不知?br />
抽象工厂模式 
抽象工厂模式意图?#8220;提供一个创Zpd相关或相互依赖对象的接口Q而无需指定他们具体的类”或ؓ(f)特定的客P或情况)提供特定pd的对象?br />
public interface Creator
{
   public ProuctA factoryA();
   public ProuctB factoryB();
}

public interface ProductA     //ProductA 接口
{
}

public interface ProductB     //ProductB 接口
{
}


public class ConCreator1 implent Creator
{
   public ProuctA factoryA()
  {
   return new ConcreteProductA1();
   }

   public ProuctB factoryB()
  {
   return new ConcreteProductB1();
   }
}

public class ConCreator2 implent Creator
{
   public ProuctA factoryA()
   {
    return new ProductA2();
    }

   public ProuctB factoryB()
   {
   return new ProductB2();
    }
}


public class ProductA1 implements  ProductA
{
 public  ProductA1()
   {
    }
}
public class ProductA2 implements  ProductA
{
 public  ProductA2()
   {
    }
}
public class ProductB1 implements  ProductB
{
 public  ProductB1()
   {
    }
}
public class ProductB2 implements  ProductB
{
 public  ProductB2()
   {
    }
}
实际上是q样?br /> 1Q两个工厂类ConCreator1QConCreator2都实CCreator接口
2QProuctA1,ProductA2都实CProductA接口
3QProuctB1,ProductB2都实CProductB接口
4QConCreator1负责生ProductAcd的?包括ProductA1QProductB1)
5QConCreator2负责生ProductBcd的?包括ProductA2QProductB2)
6Q工厂方法也有这L(fng)特征Q也是说Creator不知道什么被生出来Q甚至不知道ConCreator1q是ConCreator2被实例化了,因ؓ(f)client高兴调那一个工厂,p那一个工厂,是说工厂能生什么,对客L(fng)是可见的。甚臌有一U情况,客户端高兴v来就生了ProductA1,我就不生产ProductA2,因ؓ(f)上面的例子中它们q都是松散的Q没有绑定在一?br />



于是提出另外一个例子,也是老提L(fng)?sh)脑cd的例?br />
1Q电(sh)脑生产商是接口,
2QCUP是接口,
3Q硬盘是接口Q?br /> 4QIBM工厂是制造IBM品牌的电(sh)脑的工厂
5QDELL工厂是制造DEll品牌的电(sh)脑的工厂
论方便,p为电(sh)?CUP+盘Q?br /> 6Q所以呀CUP有IBM的CPU和DELL的CPU
7Q同L(fng)盘也是有IBM的硬盘和DELL的硬?br /> 8QIBM工厂生IBM的CPU和IBM的硬盘,l对不生产DELL的CPUQ也不生产DELL的硬?br /> 9Q同样DELL工厂也是一?br />

public interface  ?sh)脑生?br /> {
   public CPU 刉CPU();
   public 盘 刉硬?);
}

public interface CPU
{
}

public interface 盘
{
}

public class IBM的CPU implements CPU
{
   public     IBM的CPU();
}

public class IBM的硬?nbsp;implements 盘
{
    public     IBM的硬?);
}

public class DELL的CPU implements CPU
{
    public     DELL的CPU();
}

public class DELL的硬?nbsp;implements 盘
{
   public     DELL的硬?);
}

//下面是IBM工厂
public class  IBM工厂
{
   private CPU IBM的CPUU有变量=null;
   private 盘 IBM的硬盘私有变?null;
   private CPU 刉IBMCPU()
  {
     return  new IBM的CPU();
   }
 private 盘 刉IBM盘()
 {
    return  new IBM的CPU();
  }
 public ?sh)?nbsp; 刉IBM?sh)?)
 {
  try{
  IBM的CPUU有变量=刉IBMCPU();
  IBM的硬盘私有变?刉IBM盘();
  if(IBM的CPUU有变量!=null&&IBM的硬盘私有变?=null)
  retrun  (IBM的CPUU有变量+IBM的硬盘私有变?;
    //l装成IBM?sh)?br />    }
  catch(Exception e)
    {
    System.out.println("刉IBM?sh)脑p|Q?);
     }
   }
  }
}

q样Q客L(fng)无法通过命o(h)单生产出一个CPU来,q样抽象才真正成Z个完整品的工厂Q只要向工厂发出生的命令,一台完整的?sh)脑q产出来了Q而工厂怎么生的,生了哪些部Ӟ外界q不见了,外界q道这个工厂是生IBM?sh)脑整机的工厂?br />
DELL?sh)脑工厂一?

----------------------------ȝ----------------------------

工厂Ҏ(gu)模式Q?br /> 一个抽象品类Q可以派生出多个具体产品cR?nbsp; 
一个抽象工厂类Q可以派生出多个具体工厂cR?nbsp; 
每个具体工厂cd能创Z个具体品类的实例?br />
抽象工厂模式Q?br /> 多个抽象产品c,每个抽象产品cd以派生出多个具体产品cR?nbsp; 
一个抽象工厂类Q可以派生出多个具体工厂cR?nbsp; 
每个具体工厂cd以创建多个具体品类的实例?nbsp; 
   
区别Q?br /> 工厂Ҏ(gu)模式只有一个抽象品类Q而抽象工厂模式有多个?nbsp; 
工厂Ҏ(gu)模式的具体工厂类只能创徏一个具体品类的实例,而抽象工厂模式可以创建多个?/font>

]]>
SingletonQ单态)模式 ?Double-Checked LockingQ双重检查锁定)模式http://m.tkk7.com/renyangok/articles/58706.html保尔?/dc:creator>保尔?/author>Tue, 18 Jul 2006 02:56:00 GMThttp://m.tkk7.com/renyangok/articles/58706.htmlhttp://m.tkk7.com/renyangok/comments/58706.htmlhttp://m.tkk7.com/renyangok/articles/58706.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/58706.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/58706.html
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;   }

}



Double-Checked Locking在java实际上无法得到预期的效果Q不能保证singleton的正性?br />参考:(x)Q英文)
http://gee.cs.oswego.edu/dl/cpj/jmm.html
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

 


]]>
设计模式的原则和{略http://m.tkk7.com/renyangok/articles/58695.html保尔?/dc:creator>保尔?/author>Tue, 18 Jul 2006 02:08:00 GMThttp://m.tkk7.com/renyangok/articles/58695.htmlhttp://m.tkk7.com/renyangok/comments/58695.htmlhttp://m.tkk7.com/renyangok/articles/58695.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/58695.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/58695.html2、优先用对象组合,而不是类l承?br />3、针Ҏ(gu)口设计而不是实现设计?br />4、开放-闭原则Q模块、类和方法应该对扩展是开攄Q而对更改是封闭的?img src ="http://m.tkk7.com/renyangok/aggbug/58695.html" width = "1" height = "1" />

]]>
AdapterQ适配器)模式http://m.tkk7.com/renyangok/articles/57591.html保尔?/dc:creator>保尔?/author>Tue, 11 Jul 2006 00:52:00 GMThttp://m.tkk7.com/renyangok/articles/57591.htmlhttp://m.tkk7.com/renyangok/comments/57591.htmlhttp://m.tkk7.com/renyangok/articles/57591.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/57591.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/57591.html

    有时Qؓ(f)复用而设计的工具q不能够被复用的原因仅仅是因ؓ(f)它的接口与专业应用领域所需要的接口不匹配?br />    适配器模式有cȝ适配器模式和对象的适配器模式两U不同的形式?br />
一、类的适配器模?br />    cȝ适配器模式把适配的类的API转换成目标类的API?br />


  • 目标(Target)角色Q这是所期待得到的接口?
  • ?Adaptee)角色Q现有需要适配的接口?
  • 适配?Adapter)角色Q适配器类是本模式的核心。适配器把源接口{换成目标接口。显然这一角色不可以是接口Q而必L具体cR?/li>
/**
 * 定义Client使用的与特定领域相关的接?br /> */
public interface Target {
    void sampleOperation1();
    void sampleOperation2();
}
/**
 * 定义一个已l存在的接口Q这个接口需要适配
 */
public class Adaptee {
    public void sampleOperation1() {
        // ......
    }
}
/**
 * 对Adaptee与Target接口q行适配
 */
public class Adapter extends Adaptee implements Target {
    public void sampleOperation2() {
        // ......
    }
}

二、对象适配?br />    与类的适配器模式一P对象适配器模式把适配的类的API转换成ؓ(f)目标cȝAPIQ与cȝ适配器模式不同的是,对象的适配器模式不是用承关p连接到Adapteec,而是使用委派关系q接到AdapteecR示意代码如下:(x)
/**
 * 定义Client使用的与特定领域相关的接?br /> */
public interface Target {
    void sampleOperation1();
    void sampleOperation2();
}
/**
 * 定义一个已l存在的接口Q这个接口需要适配
 */
public class Adaptee {
    public void sampleOperation1() {
        // ......
    }
}
/**
 * 对Adaptee与Target接口q行适配
 */
public class Adapter implements Target {
    private Adaptee adaptee;
    public Adapter(Adaptee adaptee) {
        super();
        this.adaptee = adaptee;
    }
    public void sampleOperation1() {
        adaptee.sampleOperation1();
    }
    public void sampleOperation2() {
        // ......
    }
}

c适配器模式和对象适配器模式的异同QTarget接口和Adapteec都相同Q不同的是类适配器的Adapterl承Adaptee实现TargetQ对象适配器的Adapter实现Target聚集Adaptee?br />
适配器模式的用意是将接口不同而功能相同或者相q的两个接口加以转换?br />
三、JDBC驱动软g与适配器模?br />    JDBCl出一个客L(fng)通用的界面,每个数据库引擎的JDBC驱动软g都是一个介于JDBC接口和数据库引擎接口之间的适配器Y件?br />

]]>
FacadeQ外观)模式http://m.tkk7.com/renyangok/articles/57541.html保尔?/dc:creator>保尔?/author>Mon, 10 Jul 2006 09:15:00 GMThttp://m.tkk7.com/renyangok/articles/57541.htmlhttp://m.tkk7.com/renyangok/comments/57541.htmlhttp://m.tkk7.com/renyangok/articles/57541.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/57541.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/57541.html Facade模式的定?/em>
: 为子pȝ中的一l接口提供一个一致的界面.。现在的软g都是按照模块q行划分Q对不同的模块分别进行编E。但是在用户开来,不同的模块应该具有统一的接口,换句话说Q我们应该可以通过l一的接口访问系l中的所有功能?

    有一个很典型的例子就是编译系l。通常我们编译系l分解ؓ(f)QCompile和Link两个步骤。一个Compile又可以分解ؓ(f)词法分析、语法分析、语义分析、中间代码生成等{步骤。对于用hԌ我们不可能将q些模块分别提供l他们,让他们依ơ调用。相反的Q我们应该提供一个统一的接口,使得用户可以方便的用各个功能,例如IDE ?/p>

Facade一个典型应用就是数据库JDBC的应?如下例对数据库的操作:

public class DBCompare {

  Connection conn = null;
  PreparedStatement prep = null;
  ResultSet rset = null;
  try {
     Class.forName( "<driver>" ).newInstance();
     conn = DriverManager.getConnection( "<database>" );
    
     String sql = "SELECT * FROM <table> WHERE <column name> = ?";
     prep = conn.prepareStatement( sql );
     prep.setString( 1, "<column value>" );
     rset = prep.executeQuery();
     if( rset.next() ) {
        System.out.println( rset.getString( "<column name" ) );
     }
  } catch( SException e ) {
     e.printStackTrace();
  } finally {
     rset.close();
     prep.close();
     conn.close();
  }
}

上例是Jsp中最通常的对数据库操作办?

在应用中,l常需要对数据库操?每次都写上述一D代码肯定比较麻?需要将其中不变的部分提炼出?做成一个接?q就引入了facade外观对象.如果以后我们更换Class.forName中的<driver>也非常方?比如从Mysql数据库换到Oracle数据?只要更换facade接口中的driver可?

我们做成了一?a target="_blank">Facade接口,使用该接?上例中的E序可以更改如?

public class DBCompare {

  String sql = "SELECT * FROM <table> WHERE <column name> = ?";  

  try {
     Mysql msql=new mysql(sql);
     prep.setString( 1, "<column value>" );
     rset = prep.executeQuery();
     if( rset.next() ) {
        System.out.println( rset.getString( "<column name" ) );
     }
  } catch( SException e ) {
     e.printStackTrace();
  } finally {
     mysql.close();
     mysql=null;
  }
}

可见非常?所有程序对数据库访问都是用改接口,降低pȝ的复杂?增加了灵zL?

如果我们要用连接池,也只要针对facade接口修改可?

 

׃囑֏以看? facade实际上是个理系l间关系,降低pȝ间耦合度的一个常用的办法,也许你已l不知不觉在使用,管不知道它?yu)是facade.



]]>BridgeQ桥接)模式http://m.tkk7.com/renyangok/articles/57540.html保尔?/dc:creator>保尔?/author>Mon, 10 Jul 2006 09:13:00 GMThttp://m.tkk7.com/renyangok/articles/57540.htmlhttp://m.tkk7.com/renyangok/comments/57540.htmlhttp://m.tkk7.com/renyangok/articles/57540.html#Feedback0http://m.tkk7.com/renyangok/comments/commentRss/57540.htmlhttp://m.tkk7.com/renyangok/services/trackbacks/57540.htmlBridge模式的目的:(x)把抽象部分和行ؓ(f)部分分离Q它们都能独立变化?br />

M事物对象都有抽象和行Z分,例如人,人是一U抽象,人分男h和女人等Qh有行为,行ؓ(f)也有各种具体表现Q所以,“h”与“h的行为”两个概念也反映了抽象和行ؓ(f)之分?/p>

在面向对象设计的基本概念中,对象q个概念实际是由属性和行ؓ(f)两个部分l成的,属性我们可以认为是一U静止的Q是一U抽象,一般情况下Q行为是包含在一个对象中Q但是,在有的情况下Q我们需要将q些行ؓ(f)也进行归c,形成一个ȝ行ؓ(f)接口Q这是桥模式的用处?br />

MQBridge模式是使抽象和行ؓ(f)分离Q做到各自的独立发展Q就是说抽象和行为各抽象Z个接口。当需要扩展行为或者抽象部分时Q?br />只需扩展相应部分Q而不用修改原来的l构?br />
例子一Q?/strong>
假如有个cDrawGraph有个d的接口,当然q个圆Ş可以用铅W画Q也可以用钢W画。其中画圆是抽象部分Q?br />用铅W画和用钢笔L行ؓ(f)部分。往往q个时候我们分别会(x)定义铅笔cPencilDrawQ钢W类PenDraw来实现DrawQ?br />q样׃得抽象部分和行ؓ(f)部分固定的捆l在一P扩展性不强。假如要动态增加一个用_笔ȝ行ؓ(f)和一个画方Ş的抽象部分,
必然要新定义一个ChalkDrawc,DrawGraphc里增加drawRectangle接口。显然这是很ȝ的?/p>

Bridge模式是这样实现的Q?br />//抽象部分
public abstract class DrawGraph {

 private ToolDraw toolDraw;
 public void setToolDraw(){
  this.toolDraw = ToolDrawSingleton.getToolDraw();//用Singleton模式来选工兗?/strong>
 }
 
 public ToolDraw getToolDraw(){
  return toolDraw;
 }
 
 public abstract void draw();
}

//d
public class DrawCircle implements DrawGraph{
 public DrawCircle(){
  setToolDraw();
 }
 public void draw(){
  System.out.pritnln(toolDraw.getName() + " draw circle");
 }
}

//ȝ?br />public class DrawRectangle implements DrawGraph{
 public DrawRectangle(){
  setToolDraw();
 }
 public void draw(){
  System.out.pritnln(toolDraw.getName() + " draw rectangle");
 }
}

//行ؓ(f)部分
public abstract class ToolDraw{
 public abstract String getName();
 public abstract void drawWithTool();
}

//铅笔
public class PencilDraw implements ToolDraw{
 private final static String name = "Pencil";
 
 public static String getName(){
  return name;
 }
 
 public void drawWithTool(){
  System.out.println("Draw with Pencil.");
 }
}

//钢笔
public class PenDraw implements ToolDraw{
 private final static String name = "Pen";
 
 public String getName(){
  return name;
 }
 
 public void drawWithTool(){
  System.out.println("Draw with Pen.");
 }
}

//_笔
public class ChalkDraw implements ToolDraw{
 private final static String name = "Chalk";
 
 public String getName(){
  return name;
 }
 
 public void drawWithTool(){
  System.out.println("Draw with Chalk.");
 }
}

做一个SingletoncL联系抽象和行为。通过此类来选工?br />public class ToolDrawSingleton{
 private static ToolDraw toolDraw;
 
 public ToolDrawSingleton(ToolDraw toolDraw){
  this.toolDraw = toolDraw
 }
 public static ToolDraw getToolDraw(){
  return toolDraw;
 }
}

假如我们现在要用_笔来画一个方?一个圆形:(x)
//取得工具
ToolDrawSingleton tool = new ToolDrawSingleton(new ChalkDraw());
//L?br />DrawGraph drawRectangle = new DrawRectangle();
drawRectangle.draw();
//d?br />drawRectangle = new DrawCircle();
drawRectangle.draw();

例子二:(x)
例如,一杯咖啡ؓ(f)?子类实现cMؓ(f)四个Q中杯加奶、大杯加奶?中杯不加奶、大杯不加奶?/p>

但是Q我们注意到Q上面四个子cM有概念重叠,可从另外一个角度进行考虑Q这四个cd际是两个角色的组合:(x)抽象 和行为,其中抽象为:(x)中杯和大杯;行ؓ(f)为:(x)加奶 不加Ӟ如加汁 加苹果汁Q?

实现四个子类在抽象和行ؓ(f)之间发生了固定的l定关系Q如果以后动态增加加葡萄汁的行ؓ(f)Q就必须再增加两个类Q中杯加葡萄汁和大杯加葡萄汁。显然؜?扩展性极差?/p>

那我们从分离抽象和行为的角度Q用Bridge模式来实现?/p>

如何实现?
以上面提到的咖啡 Z. 我们原来打算只设计一个接?抽象c?,使用Bridge模式?我们需要将抽象和行为分开,加奶和不加奶属于行ؓ(f),我们它们抽象成一个专门的行ؓ(f)接口.

先看看抽象部分的接口代码:

public abstract class Coffee
{
  CoffeeImp coffeeImp;

  public void setCoffeeImp() {
    this.CoffeeImp = CoffeeImpSingleton.getTheCoffeImp();
  }

  public CoffeeImp getCoffeeImp() {return this.CoffeeImp;}

  public abstract void pourCoffee();
}

其中CoffeeImp 是加不加奶的行ؓ(f)接口,看其代码如下:

public abstract class CoffeeImp
{
  public abstract void pourCoffeeImp();
}

现在我们有了两个抽象c?下面我们分别对其q行l承,实现concrete class:

//中杯
public class MediumCoffee extends Coffee
{
  public MediumCoffee() {setCoffeeImp();}

  public void pourCoffee()
  {
    CoffeeImp coffeeImp = this.getCoffeeImp();
    //我们以重复次数来说明是冲中杯q是大杯 ,重复2ơ是中杯
    for (int i = 0; i < 2; i++)
    {

      coffeeImp.pourCoffeeImp();
    }
  
  }
}

//大杯
public class SuperSizeCoffee extends Coffee
{
  public SuperSizeCoffee() {setCoffeeImp();}

  public void pourCoffee()
  {
    CoffeeImp coffeeImp = this.getCoffeeImp();
    //我们以重复次数来说明是冲中杯q是大杯 ,重复5ơ是大杯
    for (int i = 0; i < 5; i++)
    {

      coffeeImp.pourCoffeeImp();
    }
  
  }
}

上面分别是中杯和大杯的具体实?下面再对行ؓ(f)CoffeeImpq行l承:

//加奶
public class MilkCoffeeImp extends CoffeeImp
{
  MilkCoffeeImp() {}

  public void pourCoffeeImp()
  {
    System.out.println("加了味的牛?);
  }
}

//不加?br />public class FragrantCoffeeImp extends CoffeeImp
{
  FragrantCoffeeImp() {}

  public void pourCoffeeImp()
  {
    System.out.println("什么也没加,清香");
  }
}

Bridge模式的基本框架我们已l搭好了,别忘记定义中q有一?动态结?我们现在可以喝到臛_四种咖啡:
1.中杯加奶
2.中杯不加?br />3.大杯加奶
4.大杯不加?/p>

看看是如何动态结合的,在用之?我们做个准备工作,设计一个单态类(Singleton)用来hold当前的CoffeeImp:

public class CoffeeImpSingleton
{
  private static CoffeeImp coffeeImp;

  public CoffeeImpSingleton(CoffeeImp coffeeImpIn)
   {this.coffeeImp = coffeeImpIn;}

  public static CoffeeImp getTheCoffeeImp()
  {
    return coffeeImp;
  }
}

看看中杯加奶 和大杯加?是怎么出来?

//拿出牛奶
CoffeeImpSingleton coffeeImpSingleton = new CoffeeImpSingleton(new MilkCoffeeImp());

//中杯加奶
MediumCoffee mediumCoffee = new MediumCoffee();
mediumCoffee.pourCoffee();

//大杯加奶
SuperSizeCoffee superSizeCoffee = new SuperSizeCoffee();
superSizeCoffee.pourCoffee();

注意: Bridge模式的执行类如CoffeeImp和Coffee是一对一的关p? 正确创徏CoffeeImp是该模式的关键?br />



]]>
վ֩ģ壺 jyzzjyzz鶹| JIZZJIZZŮ| AVר޾Ʒ| Ļ| ѿƷ鶹| Ѱββ8x| ˬִ̼ëƬ| Ѹ弤Ƶ| 㻨߹ۿѹۿ| ëƬѹۿվ| 97޳| ëƬ߹ۿվ| 91Ʒѹۿ| ݹѾþþ91| jizzjizzƵ| ޾Ʒþþwww| ɫƷVRһ| a߹ۿ| ҹþþþþ| avһ| av| ޾Ʒ߹ۿ| ɫվѹۿ| Ļ߹ۿƬ| ޸һ| ˾Ʒձר6| պƷAV| ˸һ91| avҹһƬѿþ| ˿wwwƵ| 2021ƷƷѹۿ| ëƬѹۿƵ| AVH߹ۿ| ɫþþ99Ʒ| þþƷAVӰ| ۺɫɫ| Ƶվ߲| 99þ99ֻѵľƷ| 99ֻоƷ6| 69Ƶר| ޾Ʒ·һ߹ۿ|