《JAVA-原形模式》

原型模式屬於對象的建立模式。經過給出一個原型對象來指明全部建立的對象的類型,而後用複製這個原型對象的辦法建立出更多同類型的對象。
  原型模式要求對象實現一個能夠「克隆」自身的接口,這樣就能夠經過複製一個實例對象自己來建立一個新的實例。這樣一來,經過原型實例建立新的對象,就再也不須要關心這個實例自己的類型,只要實現了克隆自身的方法,就能夠經過這個方法來獲取新的對象,而無須再去經過new來建立。java

        原型模式有淺度clone和深度clone之分(我的理解)。下面我就用一個例子來闡述二者的區別ide

首先建立一個實體類WordDocment讓它實現Cloneable,並重寫clone方法。代碼以下測試

public class WordDocment implements Cloneable{
	
	private String mText="測試";
	private List<String> mImages=new ArrayList<String>();
	
	public WordDocment(){
		System.out.println("WordDocment");
	}
	@Override
	protected WordDocment clone() throws CloneNotSupportedException {
		WordDocment docment=(WordDocment) super.clone();
		docment.mImages= this.mImages;
		docment.mText=this.mText;
		return docment;
	}

	public String getmText() {
		return mText;
	}
	public void setmText(String mText) {
		this.mText = mText;
	}
	public List<String> getmImages() {
		return mImages;
	}
	public void setmImages(List<String> mImages) {
		this.mImages = mImages;
	}
	
	public void add(String text){
		mImages.add(text);
	}
	
	
}

而咱們執行的代碼就很簡單了this

public static void main(String[] args) {
		//獲取原對象並打印
		WordDocment docment=new WordDocment();
		docment.add("test1");
		docment.add("test2");
		docment.add("test3");
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		System.out.println(docment.getmText());
		for (String string : docment.getmImages()) {
			System.out.println(string);
		}
		System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		try {
			//clone對象WordDocment
			WordDocment clone = docment.clone();
			clone.setmText("asdf");
			clone.add("test4");
			clone.add("test5");
			clone.add("test6");
			System.out.println("???????????????????????????????");
			System.out.println(clone.getmText());
			for (String string : clone.getmImages()) {
				System.out.println(string);
			}
			System.out.println("???????????????????????????????");
			
			//原對象打印
			System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
			System.out.println(docment.getmText());
			for (String string : docment.getmImages()) {
				System.out.println(string);
			}
			System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
			System.out.println(docment.equals(clone));
		} catch (CloneNotSupportedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

從以上代碼咱們不難看出,clone的方法很簡單。雖然如此,可是咱們仍是須要理清WordDocment與Cloneable和main方法三者的關係(其實也是原形模式中的一種關係表)code

在原形模式中有三個角色:對象

  (1)客戶(Client)角色:客戶類提出建立對象的請求。接口

  (2)抽象原型(Prototype)角色:這是一個抽象角色,一般由一個Java接口或Java抽象類實現。此角色給出全部的具體原型類所需的接口。get

  (3)具體原型(Concrete Prototype)角色:被複制的對象。此角色須要實現抽象的原型角色所要求的接口。原型

關係類圖:string

很明顯,咱們這兒main方法充當了客戶(Client)角色,Cloneable就是抽象原型(Prototype)角色,而WordDocment這個實體類則是咱們的具體原型。

關係弄清楚了以後,咱們再看看運行的結果

結果中看到,WordDocment構造方法只執行了一次,這說明clone只是拷貝了一當前對象,完成了一次備份的工做。可是咱們發如今完成clone以後,給對象中的引用類型的屬性設值,原對象的屬性也發生了改變,這是爲何呢?

緣由其實很簡單,docment.mImages=this.mImages;這句代碼執行的時候只是把this.mImages的引用傳遞給了咱們clone的對象,並無從新開闢空間,這也側面的說明了WordDocment的clone方法只進行了淺度的clone。

那我就想完徹底全的拷貝一個新的對象要怎麼作呢?

其實也很簡單,咱們只須要針對List<String> mImages進行clone就會好的,因而clone的方法裏面就完成了這樣

@Override
	protected WordDocment clone() throws CloneNotSupportedException {
		WordDocment docment=(WordDocment) super.clone();
		docment.mImages=(List<String>) ((ArrayList<String>) this.mImages).clone();
		docment.mText=this.mText;
		return docment;
	}

而後咱們再執行測試方法

這兩個類之間就沒用相互影響了,這就是所謂的深度clone

講完了謝謝你們,水平有限,多多包含

相關文章
相關標籤/搜索