原型模式:用原型實例指定建立對象的種類,並經過拷貝這些原型建立新的對象。通俗來講就是克隆一個對象,並且不用知道建立對象的細節,而後對這個對象進行自定義操做。首先,咱們先看一下下面的這個例子。性能
//公司類
public class Company { private String level; private Long workYears; public String getLevel() { return level; } public void setLevel(String level) { this.level = level; } public Long getWorkYears() { return workYears; } public void setWorkYears(Long workYears) { this.workYears = workYears; } } //實現Cloneable接口的People類(原型實例) public class People implements Cloneable { private String name; private Long age; private String gender; //公司屬性,沒有實現Cloneable接口 private Company company; public String getName() { return name; } public People() { //在初始People類的同時建立company實例 this.company = new Company(); } public void setName(String name) { this.name = name; } public Long getAge() { return age; } public void setAge(Long age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Company getCompany() { return company; } public void setCompany(String level,Long workYears) { //給company的屬性賦值 this.company.setLevel(level); this.company.setWorkYears(workYears); } //Clone()方法,clone people類 public Object Clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return (People) clone; } public void show() { System.out.println("name:" + name + ",age:" + age + ",gender" + gender); System.out.println("name:" + name + ",level:" + company.getLevel() + ",workYears:" + company.getWorkYears()); } } public class Test { public static void main(String[] args) {
//原型實例對象 People people = new People(); people.setName("zhangsan"); people.setAge(23L); people.setGender("man"); people.setCompany("A7",3L); //克隆對象1,修改age,gender屬性 People clone1 = (People)people.Clone(); clone1.setAge(25L); clone1.setGender("woman"); //克隆對象2,修改age,company屬性 People clone2 = (People)people.Clone(); clone2.setAge(26L); clone2.setCompany("A8",4L); people.show(); clone1.show(); clone2.show(); } }
獲得的結果爲:this
name:zhangsan,age:23,genderman
name:zhangsan,level:A8,workYears:4spa
name:zhangsan,age:25,genderwoman
name:zhangsan,level:A8,workYears:4code
name:zhangsan,age:26,genderman
name:zhangsan,level:A8,workYears:4對象
咱們能夠看到值類型的字段都會拷貝一份新的出來,對他們修改也不會對被克隆對象的值進行修改,可是若是字段是引用類型,則拷貝引用,但不復制引用的對象,這樣的話若是咱們對引用類型的字段company進行修改就會致使顯示的永遠是最後一次修改的值,由於拷貝出的三個引用指向一個對象,這就是淺拷貝。blog
那麼若是咱們想把引用類型的字段也拷貝一份出來呢,那麼咱們就須要把引用類型也實現Cloneable接口,並重寫Clone()方法,而且把引用類型的屬性再拷貝一遍,代碼以下:接口
public class Company implements Cloneable{ private String level; private Long workYears; public String getLevel() { return level; } public void setLevel(String level) { this.level = level; } public Long getWorkYears() { return workYears; } public void setWorkYears(Long workYears) { this.workYears = workYears; } //Clone()方法,clone company類 public Object Clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; } } //實現Cloneable接口的People類 public class People implements Cloneable { private String name; private Long age; private String gender; private Company company; public String getName() { return name; } public void setName(String name) { this.name = name; } public People() { //在給People賦name的同時建立company實例 this.company = new Company(); } public People(Company company) { this.company = (Company) company.Clone(); } public Long getAge() { return age; } public void setAge(Long age) { this.age = age; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Company getCompany() { return company; } public void setCompany(String level, Long workYears) { //給company的屬性賦值 this.company.setLevel(level); this.company.setWorkYears(workYears); } //Clone()方法,clone people類 public Object Clone() { Object object = null; try { object = super.clone();
//把引用類型company再拷貝一遍 ((People)object).company = (Company) this.company.Clone(); } catch (CloneNotSupportedException exception) { throw new RuntimeException(exception); } return object; } public void show() { System.out.println("name:" + name + ",age:" + age + ",gender" + gender); System.out.println("name:" + name + ",level:" + company.getLevel() + ",workYears:" + company.getWorkYears()); } }
結果爲:get
name:zhangsan,age:23,genderman
name:zhangsan,level:A7,workYears:3原型
name:zhangsan,age:25,genderwoman
name:zhangsan,level:A7,workYears:3io
name:zhangsan,age:26,genderman
name:zhangsan,level:A8,workYears:4
咱們能夠看到對複製出的對象中的引用對象company賦值時,並無改變原型對象,由於引用對象的變量指向了新的克隆出的對象,這就是深拷貝。
總結:原型模式的優勢就是能夠快速建立對象,比直接new一個對象再進行賦值的操做性能要好,缺點就是每一個類都得實現克隆方法,當有多層引用時,須要考慮是否會形成引用死循環。