設計模式的學習總結-原型模式詳解

一、使用場景

1.類初始化消耗資源較多

2.new產生的對象需要非常繁瑣的過程(權限認證、數據準備)

3.構造函數比較複雜

4.循環體中產生大量對象

在Spring中原型模式應用的也非常廣泛,比如scope="prototype",我們常用的JOSN.parseObject();就是原型模式的一種

二、原型模式的使用

簡單克隆

一個簡單的原型模式代碼,這樣的設計。先創建原型接口 Prototype

package Prototype;

public interface Prototype {

    Prototype clone();
}

創建需要具體克隆的對象 PrototypeA

package Prototype;

import lombok.Data;

import java.util.List;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:15:23
 */
@Data //記得引入lombok包即可
public class PrototypeA implements Prototype {

    private String name;
    private int age;
    private List<String> hobby;

    @Override
    public PrototypeA clone() {
        PrototypeA a = new PrototypeA();
        a.setAge(this.age);
        a.setName(this.name);
        a.setHobby(this.hobby);
        return a;
    }
}

創建Client對象

package Prototype;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:15:35
 */
public class Client {

    private Prototype prototype;

    public Client(Prototype prototype){
        this.prototype = prototype;
    }

    public Prototype startClone(Prototype startPototype){
        return startPototype.clone();
    }

}

測試代碼:

package Prototype;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:15:38
 */
public class PrototypeTest {

    public static void main(String[] args){
        PrototypeA p1 = new PrototypeA();
        p1.setName("JY");
        p1.setAge(21);
        List list =new ArrayList(3);
        list.add("籃球");
        p1.setHobby(list);
        System.out.println(p1);

        Client client = new Client(p1);
        PrototypeA prototypeA = (PrototypeA)client.startClone(p1);
        System.out.println(prototypeA);

        //淺克隆,克隆引用對象,其引用對象主要是克隆地址
        System.out.println("引用對象地址比較:"+ (p1.getHobby() == prototypeA.getHobby()));
        System.out.println("對象地址比較:"+ (p1 == prototypeA ));

    }
}

總結:從測試結果可以看出我們克隆的只是引用對象的地址。也就是所有的引用對象都是指向原來的對象,這就是淺克隆。

深度克隆

我們都知道漩渦鳴人,他的分身術,他可以分出許多分身可不是每個分身都能使用九尾,所以我希望實現讓每個分身都能使用九尾,那每個九尾都是獨一無二了。

先創建鳴人Naruto 對象:

package Prototype.Degree;

import java.util.Date;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:17
 */
public class Naruto {

    private String name;
    private int age;
    private Date brithday;

}

創建九尾Ninetails對象:

package Prototype.Degree;

import java.io.Serializable;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:20
 */
public class Ninetails implements Serializable {

    private String Hurt; //傷害
    private String blood; //血量

}

創建漩渦鳴人XUNaruto對象:

package Prototype.Degree;

import java.io.*;
import java.util.Date;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:25
 */
public class XUNaruto extends Naruto implements Cloneable, Serializable {

    public Ninetails ninetails; //九尾

    public XUNaruto(){
        this.brithday = new Date();
        this.ninetails = new Ninetails();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return this.deepClone();
    }

    public Object deepClone(){
        try{

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);

            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);

            XUNaruto copy = (XUNaruto)ois.readObject();
            copy.brithday = new Date();
            return copy;

        }catch (Exception e){
            e.printStackTrace();
            return null;
        }

    }


    public XUNaruto Deep(XUNaruto xuNaruto){
        XUNaruto x = new XUNaruto();
        x.age = xuNaruto.age;
        x.name = xuNaruto.name;
        x.brithday = new Date();
        x.ninetails = xuNaruto.ninetails;
        return x;
    }
}

創建測試類NarutoTest對象:

package Prototype.Degree;

/**
 * Created with IDEA
 * author:Jy
 * Date:2020/3/24
 * Time:16:36
 */
public class NarutoTest {
    public static void main(String[] args){
        XUNaruto xu = new XUNaruto();
        //深克隆(每個分身都有獨立的九尾)
        try {
            XUNaruto a = (XUNaruto)xu.clone();
            System.out.println("深克隆:"+(xu.ninetails == a.ninetails));
        }catch (Exception e){
            e.printStackTrace();
        }
        //淺克隆(每個分身只有九尾的引用)
        XUNaruto xu1 = new XUNaruto();
        XUNaruto b = xu1.Deep(xu1);
        System.out.println("淺克隆:"+(xu1.ninetails == b.ninetails));
    }
}

 總結:如果我們克隆的對象是單例對象,這就意味着深克隆會破壞單例。解決思路,禁止深克隆。也可以實現 Cloneable接口,重寫 clone() 方法,返回單例對象即可。

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