1、定義
java
用原型實例指定建立對象的種類,並經過拷貝這些原型建立新的對象。android
2、理解定義編程
舉例說明:ide
一、定於一個模型函數
public class Person{ private String name; private int age; private double height; private double weight; public Person(){ } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public double getWeight() { return weight; } public void setWeight(double weight) { this.weight = weight; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + ", weight=" + weight + '}'; } }
要實現原型模式,只須要按照下面的幾個步驟去實現便可。this
二、實現Cloneable接口spa
public class Person implements Cloneable{}
三、重寫Object的clone方法code
@Override public Object clone(){ Person person=null; try { person=(Person)super.clone(); person.name=this.name; person.weight=this.weight; person.height=this.height; person.age=this.age; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; }
四、testorm
public class Main { public static void main(String [] args){ Person p=new Person(); p.setAge(18); p.setName("張三"); p.setHeight(178); p.setWeight(65); System.out.println(p); Person p1= (Person) p.clone(); System.out.println(p1); p1.setName("李四"); System.out.println(p); System.out.println(p1); } }
五、結果顯示對象
Person{name=’張三’, age=18, height=178.0, weight=65.0} Person{name=’張三’, age=18, height=178.0, weight=65.0} Person{name=’張三’, age=18, height=178.0, weight=65.0} Person{name=’李四’, age=18, height=178.0, weight=65.0}
3、應用場景
一、理解
一個對象須要提供給其餘對象訪問,並且各個調用者可能都須要修改其值時,能夠考慮使用原型模式拷貝多個對象供調用者使用,即保護性拷貝。
二、思考
試想一下,兩個不一樣的人,除了姓名不同,其餘三個屬性都同樣,用原型模式進行拷貝就會顯得異常簡單,這也是原型模式的應用場景之一。
三、應用
可是假設Person類裏還有一個屬性叫興趣愛好,是一個List集合,就像這樣子
private ArrayList<String> hobbies=new ArrayList<String>(); public ArrayList<String> getHobbies() { return hobbies; } public void setHobbies(ArrayList<String> hobbies) { this.hobbies = hobbies; }
在進行拷貝的時候要格外注意,若是你直接按以前的代碼那樣拷貝
@Override public Object clone(){ Person person=null; try { person=(Person)super.clone(); person.name=this.name; person.weight=this.weight; person.height=this.height; person.age=this.age; person.hobbies=this.hobbies; } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; }
test:
public class Main { public static void main(String [] args){ Person p=new Person(); p.setAge(18); p.setName("張三"); p.setHeight(178); p.setWeight(65); ArrayList <String> hobbies=new ArrayList<String>(); hobbies.add("籃球"); hobbies.add("編程"); hobbies.add("長跑"); p.setHobbies(hobbies); System.out.println(p); Person p1= (Person) p.clone(); System.out.println(p1); p1.setName("李四"); p1.getHobbies().add("游泳"); System.out.println(p); System.out.println(p1); } }
結果:
Person{name=’張三’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑]} Person{name=’張三’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑]} Person{name=’張三’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑, 游泳]} Person{name=’李四’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑, 游泳]}
觀察:
你會發現原來的對象的hobby也發生了變換。
其實致使這個問題的本質緣由是咱們只進行了淺拷貝,也就是隻拷貝了引用,最終兩個對象指向的引用是同一個,一個發生變化另外一個也會發生變換,顯然解決方法就是使用深拷貝
@Override public Object clone(){ Person person=null; try { person=(Person)super.clone(); person.name=this.name; person.weight=this.weight; person.height=this.height; person.age=this.age; person.hobbies=(ArrayList<String>)this.hobbies.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; }
結果說明:
注意person.hobbies=(ArrayList)this.hobbies.clone();,再也不是直接引用而是進行了一份拷貝。再運行一下,就會發現原來的對象不會再發生變化了。
Person{name=’張三’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑]} Person{name=’張三’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑]} Person{name=’張三’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑]} Person{name=’李四’, age=18, height=178.0, weight=65.0, hobbies=[籃球, 編程, 長跑, 游泳]}
4、原型模式其餘相關
一、經常使用寫法
在clone函數裏調用構造函數,構造函數的入參是該類對象。
@Override public Object clone(){ return new Person(this); }
在構造函數中完成拷貝邏輯
public Person(Person person){ this.name=person.name; this.weight=person.weight; this.height=person.height; this.age=person.age; this.hobbies= new ArrayList<String>(hobbies); }
二、android 源代碼中的應用
先看Bundle類,該類實現了Cloneable接口
public Object clone() { return new Bundle(this); } public Bundle(Bundle b) { super(b); mHasFds = b.mHasFds; mFdsKnown = b.mFdsKnown; }