⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prototypepattern.htm

📁 DesignPattern基于Java方面最好的书
💻 HTM
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>



  
  
  
  <link rel="stylesheet" href="css/stdlayout.css" type="text/css">



  
  
  
  <link rel="stylesheet" href="css/print.css" type="text/css">



  
  
  
  <meta content="text/html; charset=gb2312" http-equiv="content-type">



  
  
  
  <title>Prototype 模式</title>
</head>


<body>



<h3><a href="http://caterpillar.onlyfun.net/GossipCN/index.html">From
Gossip@caterpillar</a></h3>



<h1><a href="CppGossip.html">Design Pattern: Prototype 模式</a></h1>



您从图书馆的期刊从发现了几篇您感兴趣的文章,由于这是图书馆的书,您不可以直接在书中作记号或写字,所以您将当中您所感兴趣的几个主题影印出来,这下子您就可在影印的文章上画记重点。<br>

<br>

Prototype模式的作用有些类似上面的描述,您在父类别中定义一个clone()方法,而在子类别中重新定义它,当客户端对于所产生的物件有兴趣并想加以利用,而您又不想破坏原来的物件,您可以产生一个物件的复本给它。<br>

<br>

Prototype具有展示的意味,就像是展览会上的原型车款,当您对某个车款感兴趣时,您可以购买相同款示的车,而不是车展上的车。<br>

<br>

在软体设计上的例子会更清楚的说明为何要进行物件复制,假设您要设计一个室内设计软体,软体中有一个展示家具的工具列,您只要点选工具列就可以产生一个家
具复本,例如一张椅子或桌子,您可以拖曳这个复制的物件至设计图中,随时改变它的位置、颜色等等,当您改变设计图中的物件时,工具列上的原型工具列是不会
跟着一起改变的,这个道理是无需解释的。<br>

<br>

下面的 UML 类别图表示了上述的简单概念: <br>



<div style="text-align: center;"><img style="width: 558px; height: 266px;" alt="Prototype" title="Prototype" src="images/protoType-1.jpg"><br>

<br>

<div style="text-align: left;">Prototype模式的重点在于clone(),它负责复制物件本身并传回,但这个clone()本身在实作上存在一些困难,尤其是当物件本身又继承另一个物件时,如何确保复制的物件完整无误,在不同的程式语言中有不同的作法。<br>

<br>

在Java中的作法是透过实作一个Cloneable介面,它只是一个声明的介面,并无规定任何实作的方法,您的目的是改写Object的clone ()方法,使其具备有复制物件的功能,这个方面建议您参考:<a href="http://www.javaworld.com/javaworld/jw-01-1999/jw-01-object.html">How to avoid traps and correctly override methods from java.lang.Object</a>。<br>

<br>

用一个简单的例子来实作上图中的结构,这个例子利用了Java语言本身的clone特性:</div>

</div>

<ul>

  <li>AbstractFurniture.java</li>

</ul>

<pre>public abstract class AbstractFurniture <br>                             implements Cloneable {<br>    public abstract void draw();<br>    <br>    // 在Design Pattern上,以下的clone是抽象未实作的<br>    // 实际上在Java中class都继承自Object<br>    // 所以在这边我们直接重新定义clone() <br>    // 这是为了符合Java现行的clone机制<br>    protected Object clone() throws CloneNotSupportedException { <br>        return super.clone(); <br>    }<br>}</pre>

<br>

CircleTable与SquareTable继承了AbstractFurniture,并实作clone方法,用于传回本身的复制品:<br>

<ul>

  <li> CircleTable.java</li>

</ul>

<pre>import java.awt.*;<br><br>public class CircleTable extends AbstractFurniture {<br>    protected Point center;    <br>    <br>    public void setCenter(Point center) {<br>        this.center = center;<br>    }<br>    <br>    protected Object clone () <br>                     throws CloneNotSupportedException { <br>        Object o = super.clone(); <br>        if(this.center != null) {<br>            ((CircleTable) o).center = (Point) center.clone();<br>        }<br>        <br>        return o; <br>    } <br><br>    public void draw() { <br>        System.out.println("\t圆桌\t中心:(" + center.getX() <br>                            + ", " + center.getY()+ ")");<br>    } <br>}</pre>

<br>

<ul>

  <li> SquareTable.java</li>

</ul>

<pre>import java.awt.*;<br><br>public class SquareTable extends AbstractFurniture {<br>    protected Rectangle rectangle;    <br>    <br>    public void setRectangle(Rectangle rectangle) {<br>        this.rectangle = rectangle;<br>    }<br>    <br>    protected Object clone () <br>                      throws CloneNotSupportedException { <br>        Object o = super.clone(); <br>        if(this.rectangle != null) { <br>            ((SquareTable) o).rectangle = (Rectangle) rectangle.clone();<br>        }<br>        <br>        return o; <br>    } <br><br>    public void draw() { <br>        System.out.print("\t方桌\t位置:(" + rectangle.getX() <br>                            + ", " + rectangle.getY()+ ")");<br>        System.out.println(" / 宽高:(" + <br>                         rectangle.getWidth() <br>                + ", " + rectangle.getHeight()+ ")");<br>    }<br>}</pre>

<br>

House是个虚拟的房屋物件,从Prototype复制出来的物件加入至House中:<br>

<ul>

  <li>House.java</li>

</ul>

<pre>import java.util.*;<br><br>public class House { <br>    private Vector vector;<br><br>    public House() { <br>        vector = new Vector(); <br>    }<br><br>    public void addFurniture(AbstractFurniture furniture) { <br>        vector.addElement(furniture); <br>        <br>        System.out.println("现有家具....");<br>        <br>        Enumeration enumeration = vector.elements();<br>        while(enumeration.hasMoreElements()) { <br>             AbstractFurniture f = <br>                 (AbstractFurniture) enumeration.nextElement(); <br>             f.draw(); <br>        } <br>        System.out.println(); <br>    } <br>}</pre>

<br>

再来是应用程式本身:<br>

<ul>

  <li>Application.java</li>

</ul>

<pre>import java.awt.*;<br><br>public class Application {<br>    private AbstractFurniture circleTablePrototype;<br>    <br>    public void setCircleTablePrototype(<br>                   AbstractFurniture circleTablePrototype) {<br>        this.circleTablePrototype = circleTablePrototype;<br>    }<br>    <br>    public void runAppExample() throws Exception {<br>        House house = new House(); <br>        CircleTable circleTable = null;<br><br>        // 从工具列选择一个家具加入房子中<br>        circleTable =<br>            (CircleTable) circleTablePrototype.clone();<br>        circleTable.setCenter(new Point(10, 10));<br>        house.addFurniture(circleTable); <br>        <br>        // 从工具列选择一个家具加入房子中<br>        circleTable = <br>            (CircleTable) circleTablePrototype.clone();<br>        circleTable.setCenter(new Point(20, 30));<br>        house.addFurniture(circleTable); <br>    }<br>    <br>    public static void main(String[] args) throws Exception {<br>        Application application = new Application();<br>        application.setCircleTablePrototype(<br>                            new CircleTable());<br>        application.runAppExample();<br>    }<br>}</pre>

<br>

Java中的clone()方法是继承自Object,AbstractFurniture的子类别则override这个clone()方法,以复制其本身并传回。<br>

<br>

下图为Prototype模式的类别结构图: <br>

<div style="text-align: center;"><img style="width: 473px; height: 239px;" alt="Prototype" title="Prototype" src="images/protoType-2.jpg"><br>

<div style="text-align: left;">在 Gof 的设计模式书中给出一个原型模式的应用:一个通用的图型编辑器 Framework。在这个 Framework中有一个工具列,您可以在上面选择音乐符号以加入乐谱中,并可以随时调整音乐符号的位置等等。<br>

<br>

图型编辑器Framework是通用的,然而它并不知道这些音乐符号的型态,有人或许会想到继承图型编辑器Framework来为每个音乐符号设计一个框
架子类别,但由于音乐符号的种类很多,这会产生相当多的子类别,为了避免这种情况,可以透过Prototype模式来减少子类别的数目,可以设计出以下的
结构:<br>

<div style="text-align: center;"><img style="width: 472px; height: 317px;" alt="Prototype" title="Prototype" src="images/protoType-3.jpg"><br>
<br>

</div>

</div>

</div>

依照这个结构,图型编辑器的Framework可以独立于要套用的特定类别之外,虽然不知道被复制传回的对象型态是什么,但总可以按照 Graphics所定义的介面来操作这些物件。<br>



</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -