設計模式之5 -- 原型模式

原型模式學習筆記

通過一個原型對象克隆出多個一模一樣的對象,該模式稱之爲原型模式。

定義:使用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。原型模式是一種對象創建型模式。

通過克隆所創建的對象是全新的對象,創建克隆對象的工廠就是原型類自身,工廠方法由克隆方法實現。

原型模式結構圖 如下圖所示:

在原型模式中包含如下幾個角色:

抽象原型類,聲明克隆方法的接口,是所有具體原型類的公共父類。

具體原型類:實現再抽象原型類中聲明的克隆方法,在克隆方法中返回自己的一個克隆對象。

class ConcreteProtoType implements ProtoType {
    private String attr;
    public void setAttr(String attr) {
        this.attr = attr;
    }

    public String getAttr() {
        return this.attr;
    }

    public ProtoType clone() {
        ProtoType protoType = new ConcreteProtoType();
        protoType.setAttr(this.attr);
        return protoType;
    }
}

在Java中對於所有的對象都是有一個共同父類Object的,而Object類已經聲明瞭clone方法接口的,因爲我們對於需要實現克隆方法的直接調用父類的clone方法就好,只需要在實現克隆類的時候實現Cloneable接口,即表示這個Java類支持被克隆。如下:

class ConcreteType implements Cloneable {
    ....
    public ProtoType clone() {
        Object object = null;
        try {
            object = super.clone();
        } catch (CloneNotSupportedException exception) {
            /*handle the exception*/
        }
        return (ProtoType)object;
    }
}

class Client {
    public static void main(String args[]) {
        ProtoType obj1 = new ConcreteProtoType();
        ProtoType obj2 = obj1.clone();
        /*此時obj1和obj2是完全相同的*/
    }
}

通過以上的方法就可以實現類的克隆。

但是在生產過程中發現如果類的成員含有的不只有基本類型的話,如果還含有其他類對象的話,就會導致問題。這裏涉及到深拷貝和淺拷貝的概念。

對於淺拷貝,只是簡單的將類的數據拷貝,即在內存中複製一份相同的數據而已,那如果還有別的類對象的話就會出現克隆類和原型類都含有對象的共同引用,而不是真正意義上的克隆。這裏就需要是用深拷貝,即在克隆的時候對於每一個類成員變量都會進行遞歸的進行克隆,那麼這時候克隆類裏所有的內容都和原類的內容一樣,但是地址完全不相同。

而爲了實現深拷貝,那麼克隆類就需要實現接口Serializable,即表明該Java類是支持深拷貝的(序列化)。代碼如下:

class WeeklyLog implements Serializable {
    private Attachment attachment;
    private String name;

    public void setAttachment(Attachment attachment) {
        this.attachment = attachment;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public Attachment getAttachment() {
        return this.attachment;
    }

    public WeeklyLog deepClone throws RuntimeException {
        ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
        ObjectOutputStream out= new ObjectOutputStream(memoryBuffer);
        out.writeObject(this);

        ObjectInputStream in = new ObjectArrayInputStream(new ByteArrayOutputStream(memoryBuffer.toByteArray()));
        return (WeeklyLog)in.readObject();
    }
}

通過序列化的方式就可以實現所謂的深拷貝,克隆出來的數據內容都是一樣的,但是對象的地址完全不一樣。

另外有一種所謂的原型管理器的概念,即將系統中所有需要使用原型模式進行克隆的類都放入管理器,客戶端調用的時候直接傳入需要克隆的參數,管理器會根據參數克隆出新的對象返回。

總結:

當需要創建的對象消耗很大的資源,諸如初始化時間長或者需要網絡資源/CPU資源等,那麼這時候就可以考慮使用原型模式,使用一個原本就存在的對象直接進行復製得到,這樣子可以很大的提高效率。如果系統中需要對某個對象的狀態進行保存,那麼這時候就可以使用原型模式。

爲了實現原型模式,類必須實現Clone接口或者Serializable接口,對於深拷貝的話還得修改每一層類的深克隆,實現起來較麻煩。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章