GoF設計模式-原型模式

    原型模式(重要):    
        當需要多次創建相同或相似對象時,可以複製這個對象。
    
    淺克隆:複製對象本身和基本類型的成員變量(String當做引用類型看待),對於引用類型的成員變量僅複製其引用地址,而引用對象不復制。通過覆蓋Java中的clone()方法來實現淺克隆,淺克隆的對象須實現Cloneable接口。
    深克隆:複製對象全部的內容,對於引用類型的成員變量,由於在堆中複製了其引用對象,所以引用地址肯定發生了變化。在Java中,通過序列化的方式實現深克隆。將原有對象寫入流中,寫到流中的對象是原有對象的一個拷貝,然後從流中讀出來實現深克隆,深克隆的對象須實現Serializable接口。
    淺克隆與深克隆的區別是引用類型的成員對象是否複製。

    原型模式的適用場景:
        1.創建新對象的成本過大,需要多次創建相同或相似對象時
        2.系統要保存對象的狀態,而對象的狀態變化很小,對象佔用的內存很小,可以使用原型模式配合備忘錄模式來應用。如果對象的狀態變化或佔用的內存很大,可以採用狀態模式。
    
    原型模式的應用:
        1.在Struts2中爲了保證線程的安全性,Action對象的創建使用了原型模式,當訪問一個已經存在Action對象時,通過克隆的方式創建一個新對象,從而保證對象中定義的變量無須進行加鎖而實現同步。
    
    原型模式的優點:
        1.簡化對象的創建過程,提高對象的創建效率
        2.由於克隆方法在原型類的內部,因此增加新的原型類不需要修改原有代碼
        3.可以使用深克隆保存對象的狀態
    
    原型模式的缺點:
        1.當要克隆已有的類時,需要修改原有代碼,違背了開閉原則
        2.實現深克隆需要編寫較爲複雜的代碼
            
        原型模式的例子:

要克隆的對象

public class Student implements Cloneable,Serializable{
	
	private String stuName;
	private int stuAge;
	private School school;
	
	/**
	 * 
	 * @Description: 淺克隆,需要實現Cloneable接口
	 * @author doudou
	 * @date 2019年10月8日
	 * @return
	 * @throws
	 * @return
	 * @see java.lang.Object#clone()
	 */
	public Object clone() {
		Student student = null;
		try {
			student = (Student) super.clone();
		} catch (Exception e) {
			System.out.println("Clone failure");
		}
		return student;
	}
	
	/**
	 * 
	 * @Description: 深克隆
	 * @author doudou
	 * @date 2019年10月8日
	 * @return
	 * @throws IOException
	 * @throws ClassNotFoundException
	 * @throws
	 * @return
	 */
	public Object deepClone() throws IOException, ClassNotFoundException {
		//將對象寫入流中
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
		objectOutputStream.writeObject(this);
		
		//將對象從流中取出
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
		return objectInputStream.readObject();
	}

	public String getStuName() {
		return stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	public int getStuAge() {
		return stuAge;
	}

	public void setStuAge(int stuAge) {
		this.stuAge = stuAge;
	}

	public School getSchool() {
		return school;
	}

	public void setSchool(School school) {
		this.school = school;
	}
	
}
public class School implements Serializable{
	
}

測試類:

public class Main {
	public static void main(String[] args) throws ClassNotFoundException, IOException {
		Student student = new Student();
		School school = new School();
		student.setSchool(school);
		student.setStuAge(10);
		student.setStuName("doudou");
		
		Student shallowClone = (Student) student.clone();
		Student deepClone = (Student) student.deepClone();
		
		System.out.println("student:"+student.toString());
		
		System.out.println("shallowClone:"+(shallowClone.toString()));
		System.out.println("shallowClone==student?"+(shallowClone==student));
		System.out.println("shallowClone.equals(student)?"+(shallowClone.equals(student)));
		System.out.println("shallowClone.getStuName()==student.getStuName()?"+(shallowClone.getStuName()==student.getStuName()));
		
		System.out.println("deepClone:"+(deepClone.toString()));
		System.out.println("deepClone==student?"+(deepClone==student));
		System.out.println("deepClone.equals(student)?"+(deepClone.equals(student)));
		System.out.println("deepClone.getStuName()==student.getStuName()?"+(deepClone.getStuName()==student.getStuName()));
	
	}
}

 

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