原型模式必知必會

類圖

在這裏插入圖片描述
在這裏插入圖片描述

實例

public interface Prototype{
    Prototype clone();
}
public class ConcretePrototypeA implements Prototype {

    private int age;
    private String name;
    private List hobbies;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public List getHobbies() {
        return hobbies;
    }

    public void setHobbies(List hobbies) {
        this.hobbies = hobbies;
    }

    @Override
    public ConcretePrototypeA clone() {
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        concretePrototype.setAge(this.age);
        concretePrototype.setName(this.name);
        concretePrototype.setHobbies(this.hobbies);
        return concretePrototype;
    }

}
public class ConcretePrototypeB implements Prototype {

    @Override
    public Prototype clone() {
        return null;
    }
}

public class Client {

    private Prototype prototype;

    public Client(Prototype prototype){
        this.prototype = prototype;
    }
    public Prototype startClone(Prototype concretePrototype){
        return (Prototype)concretePrototype.clone();
    }

}

public class PrototypeTest {

    public static void main(String[] args) {

        // 創建一個具體的需要克隆的對象
        ConcretePrototypeA concretePrototype = new ConcretePrototypeA();
        // 填充屬性,方便測試
        concretePrototype.setAge(18);
        concretePrototype.setName("prototype");
        List hobbies = new ArrayList<String>();
        concretePrototype.setHobbies(hobbies);
        System.out.println(concretePrototype);

        // 創建Client對象,準備開始克隆
        Client client = new Client(concretePrototype);
        ConcretePrototypeA concretePrototypeClone = (ConcretePrototypeA) client.startClone(concretePrototype);
        System.out.println(concretePrototypeClone);

        System.out.println("克隆對象中的引用類型地址值:" + concretePrototypeClone.getHobbies());
        System.out.println("原對象中的引用類型地址值:" + concretePrototype.getHobbies());
        System.out.println("對象地址比較:"+(concretePrototypeClone.getHobbies() == concretePrototype.getHobbies()));


    }
}

在這裏插入圖片描述

深克隆

例子:
在這裏插入圖片描述

public class Monkey {
    public int height;
    public int weight;
    public Date birthday;
}

public class JinGuBang implements Serializable {
    public float h = 100;
    public float d = 10;

    public void big(){
        this.d *= 2;
        this.h *= 2;
    }

    public void small(){
        this.d /= 2;
        this.h /= 2;
    }
}

public class QiTianDaSheng extends Monkey implements Cloneable,Serializable {

    public JinGuBang jinGuBang;

    public  QiTianDaSheng(){
        //只是初始化
        this.birthday = new Date();
        this.jinGuBang = new JinGuBang();
    }

    @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);

            QiTianDaSheng copy = (QiTianDaSheng)ois.readObject();
            copy.birthday = new Date();
            return copy;

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

    }


    public QiTianDaSheng shallowClone(QiTianDaSheng target){

        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        qiTianDaSheng.height = target.height;
        qiTianDaSheng.weight = target.height;

        qiTianDaSheng.jinGuBang = target.jinGuBang;
        qiTianDaSheng.birthday = new Date();
        return  qiTianDaSheng;
    }

    //淺克隆
    public QiTianDaSheng deep2(QiTianDaSheng target){

        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        qiTianDaSheng.height = target.height;
        qiTianDaSheng.weight = target.height;

        qiTianDaSheng.jinGuBang =  target.jinGuBang;
        qiTianDaSheng.birthday = new Date();
        return  qiTianDaSheng;
    }

}

public class DeepCloneTest {

    public static void main(String[] args) {

        QiTianDaSheng qiTianDaSheng = new QiTianDaSheng();
        try {
            QiTianDaSheng clone = (QiTianDaSheng)qiTianDaSheng.clone();
            System.out.println("深克隆:" + (qiTianDaSheng.jinGuBang == clone.jinGuBang));
        } catch (Exception e) {
            e.printStackTrace();
        }

        QiTianDaSheng q = new QiTianDaSheng();
        QiTianDaSheng n = q.shallowClone(q);
        System.out.println("淺克隆:" + (q.jinGuBang == n.jinGuBang));


    }
}

在這裏插入圖片描述

深克隆破壞單例解決方式

要麼你我們的單例類不實現Cloneable接口;
要麼我們重寫clone()方法,在clone方法中返回單例對象即可,具體代碼如下:

@Override
protected Object clone() throws CloneNotSupportedException{
	return INSTANCE;
}

Cloneable源碼分析先看我們常用的ArrayList就實現了Cloneable接口,來看代碼clone()方法的實現:`

public Object clone(){
	try{
		ArrayList<?>v=(ArrayList<?>)
		super.clone();v.elementData=Arrays.copyOf(elementData,size);
	     v.modCount=0;
	     return v;
	}catch(CloneNotSupportedExceptione){
		。。。
	}

個人理解

感覺和之前new出來一個對象,再set值一樣,只是,這個set的功能在對象內部。對外只暴露一個clone或者其他自定義接口。

原型克隆和new的區別

在這裏插入圖片描述

原型模式和抽象工廠模式的區別

在這裏插入圖片描述

本質

本質: 克隆生成對象。


代碼地址:

https://github.com/hufanglei/pattern-learn/tree/master/src/main/java/com/example/prototype
筆記地址 https://blog.csdn.net/baidu_21349635/article/details/106086578


個人微信公衆號:
搜索: 怒放de每一天
不定時推送相關文章,期待和大家一起成長!!
在這裏插入圖片描述


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