一天一個設計模式---原型模式__設計模式

來源:互聯網
上載者:User

介紹:用原型執行個體指定建立對象的種類,並且通過拷貝這些原型建立新的對象。這個模式相對簡單,其實我們只需要掌握對象拷貝的知識。

情境:我們在使用對象的時候可能會通過下面的方式來建立新的對象。但是,這樣只是將stu2引用指向stu1,而並非建立一個新的對象。在我們之後對stu2的屬性改變時,也會造成stu1的改變。

Student stu2 = stu1;
一、對象拷貝的概念

我們在實現對象拷貝的時候,首先應該實現Cloneable介面,並重寫clone()方法。

這裡,我們不得不提到對象拷貝的概念—也就是淺拷貝和深拷貝。

淺拷貝:
對實值型別的成員變數進行值的複製,對參考型別的成員變數只複製引用,不複製引用的對象。也就是說,如果拷貝的對象中還有物件類型的屬性,那麼它的在之後的變換中是會對所用的引用造成影響的。

深拷貝:
對實值型別的成員變數進行值的複製,對參考型別的成員變數也進行引用對象的複製。這樣就避免了上面的這種情況的發生。 二、淺拷貝

情境:小米買了個PSP,小明看到了也讓小米幫忙買了一個。但是,小米買來的時候啟用用的是自己的帳號。小明在用了一段時間後想修改使用者名稱密碼,並且增加記憶體大小。記憶體是增加了,但是由於自己修改了帳號,導致小米的帳號不能用了。。。

帳號

public class Account {    private String name;    private String password;    @Override    public String toString() {        return "Acount name:" + name + ",Acount name:" + password;    }    // setter and getter}

PSP

public class PSP implements Cloneable {    private String color;    private double price;    private Account account;    private int ram;    @Override    protected Object clone() {        PSP psp = null;        try {            psp = (PSP) super.clone();        } catch (CloneNotSupportedException e) {            e.printStackTrace();        }        return psp;    }    @Override    public String toString() {        return color + "," + ram + "," + price + "," + account;    }    // setter and getter}

測試

    public static void main(String[] args) {        PSP psp1 = new PSP();        Account acc = new Account();        acc.setName("小米");        acc.setPassword("123");        psp1.setAccount(acc);        psp1.setColor("red");        psp1.setPrice(1600.0);        psp1.setRam(8);        System.out.println("小米:" + psp1.toString());        PSP psp2 = (PSP) psp1.clone();        System.out.println("小明:" + psp2.toString());        System.out.println("小明修改記憶體和帳號==========");        psp2.getAccount().setName("小明");        psp2.getAccount().setPassword("555");        psp2.setRam(16);        System.out.println("小米:" + psp1.toString());        System.out.println("小明:" + psp2.toString());    }

輸出

小米:red,8,1600.0,Acount name:小米,Acount name:123小明:red,8,1600.0,Acount name:小米,Acount name:123小明修改記憶體和帳號==========小米:red,8,1600.0,Acount name:小明,Acount name:555小明:red,16,1600.0,Acount name:小明,Acount name:555

可以看到,淺拷貝的方式,基本屬性是進行複製,而物件類型則還是使用原來的引用(也可通過查看兩者Account的hashCode來說明)。 三、深拷貝

實現深拷貝,我們可以藉助序列化(Serialization),我們可以將對象序列化寫入流中,然後通過還原序列化再擷取,這樣就能得到一個完整的拷貝。這裡需要注意,我們的類需要實現Serializable介面,否則會報java.io.NotSerializableException的異常。

帳號

public class Account implements Serializable {    private static final long serialVersionUID = -7747721962690262418L;    private String name;    private String password;    @Override    public String toString() {        return "Acount name:" + name + ",Acount name:" + password;    }    // setter and getter}

PSP

public class PSP implements Cloneable, Serializable {    private static final long serialVersionUID = 6401635201114419015L;    private String color;    private double price;    private Account account;    private int ram;    @Override    protected Object clone() {        PSP psp = null;        try {            // 將對象寫到流裡            ByteArrayOutputStream bos = new ByteArrayOutputStream();            ObjectOutputStream oos;            oos = new ObjectOutputStream(bos);            oos.writeObject(this);            // 從流裡讀回來            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());            ObjectInputStream ois = new ObjectInputStream(bis);            psp = (PSP) ois.readObject();        } catch (IOException | ClassNotFoundException e) {            e.printStackTrace();        }        return psp;    }    @Override    public String toString() {        return color + "," + ram + "," + price + "," + account;    }    // setter and getter}

測試

    public static void main(String[] args) {        PSP psp1 = new PSP();        Account acc = new Account();        acc.setName("小米");        acc.setPassword("123");        psp1.setAccount(acc);        psp1.setColor("red");        psp1.setPrice(1600.0);        psp1.setRam(8);        System.out.println("小米:" + psp1.toString());        PSP psp2 = (PSP) psp1.clone();        System.out.println("小明:" + psp2.toString());        System.out.println("小明修改記憶體和帳號==========");        psp2.getAccount().setName("小明");        psp2.getAccount().setPassword("555");        psp2.setRam(16);        System.out.println("小米:" + psp1.toString());        System.out.println("小明:" + psp2.toString());    }

輸出

小米:red,8,1600.0,Acount name:小米,Acount name:123小明:red,8,1600.0,Acount name:小米,Acount name:123小明修改記憶體和帳號==========小米:red,8,1600.0,Acount name:小米,Acount name:123小明:red,16,1600.0,Acount name:小明,Acount name:555

可以看到,這樣小明修改帳號,小明的帳號密碼都不會修改,這樣就避免上面的這種情況。

更多模式: 一天一個設計模式—分類與六大原則

更多源碼: https://github.com/oDevilo/Java-Base

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.