細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業,五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks
          您從圖書館的期刊從發現了幾篇您感興趣的文章,由於這是圖書館的書,您不可以直接在書中作記號或寫字,所以您將當中您所感興趣的幾個主題影印出來,這下子您就可在影印的文章上畫記重點。

          Prototype模式的作用有些類似上面的描述,您在父類別中定義一個clone()方法,而在子類別中重新定義它,當客戶端對於所產生的物件有興趣並想加以利用,而您又不想破壞原來的物件,您可以產生一個物件的複本給它。

          Prototype具有展示的意味,就像是展覽會上的原型車款,當您對某個車款感興趣時,您可以購買相同款示的車,而不是車展上的車。

          在軟體設計上的例子會更清楚的說明為何要進行物件複製,假設您要設計一個室內設計軟體,軟體中有一個展示家具的工具列,您只要點選工具列就可以產生一個家具複本,例如一張椅子或桌子,您可以拖曳這個複製的物件至設計圖中,隨時改變它的位置、顏色等等,當您改變設計圖中的物件時,工具列上的原型工具列是不會跟著一起改變的,這個道理是無需解釋的。

          下面的 UML 類別圖表示了上述的簡單概念:
          Prototype

          Prototype模式的重點在於clone(),它負責複製物件本身並傳回,但這個clone()本身在實作上存在一些困難,尤其是當物件本身又繼承另一個物件時,如何確保複製的物件完整無誤,在不同的程式語言中有不同的作法。

          在Java中的作法是透過實作一個Cloneable介面,它只是一個聲明的介面,並無規定任何實作的方法,您的目的是改寫Object的clone ()方法,使其具備有複製物件的功能,這個方面建議您參考:How to avoid traps and correctly override methods from java.lang.Object

          用一個簡單的例子來實作上圖中的結構,這個例子利用了Java語言本身的clone特性:
          • AbstractFurniture.java
          public abstract class AbstractFurniture 
          implements Cloneable {
          public abstract void draw();

          // 在Design Pattern上,以下的clone是抽象未實作的
          // 實際上在Java中class都繼承自Object
          // 所以在這邊我們直接重新定義clone()
          // 這是為了符合Java現行的clone機制
          protected Object clone() throws CloneNotSupportedException {
          return super.clone();
          }
          }

          CircleTable與SquareTable繼承了AbstractFurniture,並實作clone方法,用於傳回本身的複製品:
          • CircleTable.java
          import java.awt.*;

          public class CircleTable extends AbstractFurniture {
          protected Point center;

          public void setCenter(Point center) {
          this.center = center;
          }

          protected Object clone ()
          throws CloneNotSupportedException {
          Object o = super.clone();
          if(this.center != null) {
          ((CircleTable) o).center = (Point) center.clone();
          }

          return o;
          }

          public void draw() {
          System.out.println("\t圓桌\t中心:(" + center.getX()
          + ", " + center.getY()+ ")");
          }
          }

          • SquareTable.java
          import java.awt.*;

          public class SquareTable extends AbstractFurniture {
          protected Rectangle rectangle;

          public void setRectangle(Rectangle rectangle) {
          this.rectangle = rectangle;
          }

          protected Object clone ()
          throws CloneNotSupportedException {
          Object o = super.clone();
          if(this.rectangle != null) {
          ((SquareTable) o).rectangle = (Rectangle) rectangle.clone();
          }

          return o;
          }

          public void draw() {
          System.out.print("\t方桌\t位置:(" + rectangle.getX()
          + ", " + rectangle.getY()+ ")");
          System.out.println(" / 寬高:(" +
          rectangle.getWidth()
          + ", " + rectangle.getHeight()+ ")");
          }
          }

          House是個虛擬的房屋物件,從Prototype複製出來的物件加入至House中:
          • House.java
          import java.util.*;

          public class House {
          private Vector vector;

          public House() {
          vector = new Vector();
          }

          public void addFurniture(AbstractFurniture furniture) {
          vector.addElement(furniture);

          System.out.println("現有家具....");

          Enumeration enumeration = vector.elements();
          while(enumeration.hasMoreElements()) {
          AbstractFurniture f =
          (AbstractFurniture) enumeration.nextElement();
          f.draw();
          }
          System.out.println();
          }
          }

          再來是應用程式本身:
          • Application.java
          import java.awt.*;

          public class Application {
          private AbstractFurniture circleTablePrototype;

          public void setCircleTablePrototype(
          AbstractFurniture circleTablePrototype) {
          this.circleTablePrototype = circleTablePrototype;
          }

          public void runAppExample() throws Exception {
          House house = new House();
          CircleTable circleTable = null;

          // 從工具列選擇一個家具加入房子中
          circleTable =
          (CircleTable) circleTablePrototype.clone();
          circleTable.setCenter(new Point(10, 10));
          house.addFurniture(circleTable);

          // 從工具列選擇一個家具加入房子中
          circleTable =
          (CircleTable) circleTablePrototype.clone();
          circleTable.setCenter(new Point(20, 30));
          house.addFurniture(circleTable);
          }

          public static void main(String[] args) throws Exception {
          Application application = new Application();
          application.setCircleTablePrototype(
          new CircleTable());
          application.runAppExample();
          }
          }

          Java中的clone()方法是繼承自Object,AbstractFurniture的子類別則override這個clone()方法,以複製其本身並傳回。

          下圖為Prototype模式的類別結構圖:
          Prototype
          在 Gof 的設計模式書中給出一個原型模式的應用:一個通用的圖型編輯器 Framework。在這個 Framework中有一個工具列,您可以在上面選擇音樂符號以加入樂譜中,並可以隨時調整音樂符號的位置等等。

          圖型編輯器Framework是通用的,然而它並不知道這些音樂符號的型態,有人或許會想到繼承圖型編輯器Framework來為每個音樂符號設計一個框架子類別,但由於音樂符號的種類很多,這會產生相當多的子類別,為了避免這種情況,可以透過Prototype模式來減少子類別的數目,可以設計出以下的結構:
          Prototype

          依照這個結構,圖型編輯器的Framework可以獨立於要套用的特定類別之外,雖然不知道被複製傳回的對象型態是什麼,但總可以按照 Graphics所定義的介面來操作這些物件。
          posted on 2007-04-17 10:35 張金鵬 閱讀(337) 評論(0)  編輯  收藏 所屬分類: Creational 模式
          主站蜘蛛池模板: 老河口市| 靖远县| 内黄县| 保康县| 贵德县| 临海市| 南宫市| 闽侯县| 通化市| 原平市| 会泽县| 敖汉旗| 波密县| 穆棱市| 岗巴县| 江陵县| 乌拉特前旗| 新河县| 九龙县| 新绛县| 庐江县| 周至县| 察哈| 白山市| 闵行区| 宁津县| 宁明县| 江安县| 西昌市| 会东县| 红原县| 昭通市| 黔江区| 鹿邑县| 获嘉县| 长春市| 米泉市| 政和县| 阿巴嘎旗| 瓮安县| 桐梓县|