2010年2月3日星期三

網頁設計Java與模式:合成模式


網頁設計Java與模式:合成模式


發佈者:作者:Web Design香港網頁設計大皇 - 網站設計
Web Design

合成(Composite)模式是一種非常重要的設計模式,合成模式將對像組織到樹中,用來描述樹的關係。
一、原理圖
從原理圖可見,File、Folder都可以同等看待葦IFile,為對像管理提供了極大的便利。
當然,樹的概念不單單是文件文件夾的層次概念,只是因為這個很形象,實際中還有很多樹的概念,比如組織機構,分類層次等等,都是邏輯上的概念,不管是物理上的還是邏輯上的,在Java裡都是一樣處理的。
二、實例下面以一個邏輯樹為例子,以上面的原理圖為藍本,看看如何實現並如何使用這個樹,這個結構很簡單,但是如何去使用樹,遍歷樹、為我所用還是有一定難度的。
這裡主要用到樹的遞歸遍歷,如何遞歸、如何控制遍歷層級,如何將邏輯關係轉換為(類似)物理關係,這些都是有相當難度的。
廢話就不說了,看看便知。
/** * Created by IntelliJ IDEA. * User: leizhimin * Date: 2008-8-2 16:13:59 * 抽像文件角色 */ public interface IFile { //返回自己的實例 IFile getComposite(); //某個商業方法 void sampleOperation(); //獲取深度 int getDeep(); //設置深度 void setDeep(int x); }
import java.util.Vector; /** * Created by IntelliJ IDEA. * User: leizhimin * Date: 2008-8-2 16:15:03 * 文件夾角色 */ public class Folder implements IFile { private String name; //文件名字 private int deep; //層級深度,根深度為0 private Vector componentVector = new Vector(); public Folder(String name) { this.name = name; } //返回自己的實例 public IFile getComposite() { return this; } //某個商業方法 public void sampleOperation() { System.out.println("執行了某個商業方法!"); } //增加一個文件或文件夾 public void add(IFile IFile) { componentVector.addElement(IFile); IFile.setDeep(this.deep 1); } //刪除一個文件或文件夾 public void remove(IFile IFile) { componentVector.removeElement(IFile); } //返回直接子文件(夾)集合 public Vector getAllComponent() { return componentVector; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getDeep() { return deep; } public void setDeep(int deep) { this.deep = deep; } }
/** * Created by IntelliJ IDEA. * User: leizhimin * Date: 2008-8-2 16:27:15 * 文件 */ public class File implements IFile { private String name; //文件名字 private int deep; //層級深度 public File(String name) { this.name = name; } //返回自己的實例 public IFile getComposite() { return this; } //某個商業方法 public void sampleOperation() { System.out.println("執行了某個商業方法!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getDeep() { return deep; } public void setDeep(int deep) { this.deep = deep; } }
import java.util.Iterator; import java.util.Vector; /** * Created by IntelliJ IDEA. * User: leizhimin * Date: 2008-8-2 16:35:25 * 遍歷樹的一個測試 */ public class Client { public static String indentChar = "\t"; //文件層次縮進字符 public static void main(String args[]) { new Client().test(); } /** * 客戶端測試方法 */ public void test() { //根下文件及文件夾 Folder root = new Folder("樹根"); Folder b1_1 = new Folder("1_枝1"); Folder b1_2 = new Folder("1_枝2"); Folder b1_3 = new Folder("1_枝3"); File l1_1 = new File("1_葉1"); File l1_2 = new File("1_葉2"); File l1_3 = new File("1_葉3"); //b1_2下的文件及文件夾 Folder b2_1 = new Folder("2_枝1"); Folder b2_2 = new Folder("2_枝2"); File l2_1 = new File("2_葉1"); //締造樹的層次關係(簡單測試,沒有重複添加的控制) root.add(b1_1); root.add(b1_2); root.add(l1_1); root.add(l1_2); b1_2.add(b2_1); b1_2.add(b2_2); b1_2.add(l2_1); root.add(l1_3); root.add(b1_3); //控制台打印樹的層次 outTree(root); } public void outTree(Folder folder) { System.out.println(folder.getName()); iterateTree(folder); } /** * 遍歷文件夾,輸入文件樹 * * @param folder */ public void iterateTree(Folder folder) { Vector clist = folder.getAllComponent(); //todo:遍歷之前可以對clist進行排序,這些都不是重點 for (Iterator it = clist.iterator(); it.hasNext();) { IFile em = it.next(); if (em instanceof Folder) { Folder cm = (Folder) em; System.out.println(getIndents(em.getDeep()) cm.getName()); iterateTree(cm); } else { System.out.println(getIndents(em.getDeep()) ((File) em).getName()); } } } /** * 文件層次縮進字符串 * * @param x 縮進字符個數 * @return 縮進字符串 */ public static String getIndents(int x) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < x; i ) { sb.append(indentChar); } return sb.toString(); } }
三、運行測試
控制台輸出如下:
可見,樹邏輯關係已經成功展示出來了。
四、總結1、上面所用的合成模式是安全合成模式,所謂的安全是指File與Folder中的方法不同。Folder有對聚集對象的管理,File沒有。
2、合成模式在程序設計中有著廣泛的應用,比如Dom4j、資源管理器、Java GUI容器層次圖等等都是合成模式應用的典範。
3、合成模式很多都是需要分析思考才能鑒別出來的,比如要做一個複雜的數學表達式計算器,有四種運算符號。分析發現,運算量有兩種,一種是數字、一種是數字的表達式,但是表達式也是由數字組成,因此數字和表達式可以抽像為運算量。然後去表達要運算的表達式。問題迎刃而解。Web Hosting

没有评论:

发表评论