1. 程式人生 > >設計模式筆記之四原型模式

設計模式筆記之四原型模式

原型模式

為什麼引入原型模式?

當我們需要建立某個物件的時候,我們使用new關鍵字,但是當我們需要建立兩個相同的物件,接著new,當數量特定少的時候,我們可以採用直接建立物件,但是當我們需要建立很多物件的時候,我們就不能一直new,首先是因為堆記憶體有限,只允許我們new特定數量的物件,因此我們需要另一種方式,快速的實現物件的複製,克隆,因此引入原型模式。

原型模式是什麼?

用原型歐例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。

核心思想:

原型模式的實現方式十分簡單,即只需繼承Cloneable介面,覆蓋clone()方法。

這裡需要解釋一下什麼是淺克隆和深克隆。

淺克隆:

繼承Cloneable介面,覆蓋clone方法所實現的克隆就是淺克隆,淺克隆的方式即Object類的clone方法只是拷貝物件本身,其物件內部的陣列,引用物件都不拷貝,還是指向原生物件的內部元素地址,int,long,char等基恩型別會被拷貝,但是String型別,通過字串常量池在需要的時候才在記憶體中建立新的字串,讀者可以把String當做基本型別使用即可。

深克隆:

將物件的所有東西都拷貝一份,實現物件之間的獨立。深拷貝在淺拷貝的基礎上,對陣列,引用物件單獨拷貝。

具體案例:

我們現在有一個名牌汽車,我們希望在以這件車為模型生產很多輛

程式碼:

package com.dong.yuanxing;

import java.util.ArrayList;

public class Car implements Cloneable{
	private String name;
	private int Id;
	private ArrayList<String> otherDes = new ArrayList<String>() ;
	
	public Car clone() {
		Car car =null;
		try {
			car = (Car)super.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("克隆不支援");
			return null;
		}
		return car;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getId() {
		return Id;
	}
	public void setId(int id) {
		Id = id;
	}
	public ArrayList<String> getOtherDes() {
		return otherDes;
	}
	public void setOtherDes(String value) {
		this.otherDes.add(value);
	}
}

package com.dong.yuanxing;

import java.util.ArrayList;
//淺拷貝
public class Main {
	public static void main(String args[]) {
		Car carold ,carnew,carthre;
		carold = new Car();
		carold.setOtherDes("111");	
		carnew = carold.clone();	
		carnew.setOtherDes("222");
		System.out.println(carnew + carnew.getOtherDes().toString());	
	}
}

深拷貝需要改動的地方:

	public Car clone() {
		Car car =null;
		try {
			//淺拷貝
			car = (Car)super.clone();
			//深拷貝,即對私有的類變數進行單獨的拷貝。
			//car = (Car)super.clone();
			//car.otherDes = (ArrayList<String>) this.otherDes.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("克隆不支援");
			return null;
		}
		return car;
	}


	public static void main(String args[]) {
		Car carold ,carnew;
		carold = new Car();
		carold.setOtherDes("111");	
		carnew = carold.clone();	
		carnew.setOtherDes("222");
		System.out.println(carold + carold.getOtherDes().toString());
		System.out.println(carnew + carnew.getOtherDes().toString());
	}

優點

拷貝的效能優良,原型模式是在記憶體二進位制流的拷貝,要比直接new一個物件的效能好。

缺點

淺拷貝不能拷貝物件的所有,對於內部的陣列,引用物件是不會拷貝的,需要使用深拷貝。

擴充套件:

深拷貝的另一種實現方式:

package com.dong.prototype;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class DeepCloneObj implements Serializable{

	private static final long serialVersionUID = 1L;
	//為需要克隆的類
	private StudentA student;
	public StudentA getStudent() {
		return student;
	}
	public void setStudent(StudentA student) {
		this.student = student;
	}
	public DeepCloneObj clone() {
		ByteArrayOutputStream bos;
		ObjectOutputStream oos;
			try {
				bos = new ByteArrayOutputStream();
				oos = new ObjectOutputStream(bos);
				oos.writeObject(this);
				ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
				ObjectInputStream ois = new ObjectInputStream(bis);
				try {
					return (DeepCloneObj) ois.readObject();
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		return null;			
	}
}