java23種設計模式—— 1、設計模式介紹
java23種設計模式—— 2、單例模式
java23種設計模式——3、工廠模式
java23種設計模式——4、原型模式
java23種設計模式——5、建造者模式
java23種設計模式——6、適配器模式java
這種模式是實現了一個原型接口,該接口用於建立當前對象的克隆。當直接建立對象的代價比較大時,則採用這種模式。例如,一個對象須要在一個高代價的數據庫操做以後被建立。咱們能夠緩存該對象,在下一個請求時返回它的克隆,在須要的時候更新數據庫,以此來減小數據庫調用。git
舉個例子,就是當咱們須要給電腦安裝win10系統時須要去官網上下載win10系統的安裝包。而安裝包的大小都是很耗時的,還須要另外一臺電腦來操做。若是咱們下載了一個安裝包放在咱們的u盤裏,以後須要安裝win10時是否是就省去了中間尋找,下載等時間呢github
原型模式的克隆分爲淺克隆和深克隆,Java 中的 Object 類提供了淺克隆的 clone() 方法,具體原型類只要實現 Cloneable 接口就可實現對象的淺克隆,這裏的 Cloneable 接口就是抽象原型類。其代碼以下數據庫
新建一個實體類Sheep實現Cloneable 接口,重寫clone()方法設計模式
/** * @author codermy * @createTime 2020/5/14 */ public class Sheep implements Cloneable{ private String name; private int age; private String sex; 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Sheep(String name, int age, String sex) { this.name = name; this.age = age; this.sex = sex; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + '}'; } //克隆該實例,使用默認的clone方法 @Override protected Object clone() throws CloneNotSupportedException { Sheep sheep =null; sheep = (Sheep)super.clone(); return sheep; } }
測試緩存
/** * @author codermy * @createTime 2020/5/14 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { Sheep sheep = new Sheep("tom",1,"male"); Sheep sheep1 = (Sheep)sheep.clone(); System.out.println(sheep.hashCode()); System.out.println(sheep); System.out.println(sheep1.hashCode()); System.out.println(sheep1); sheep1.setAge(2); System.out.println(sheep1); System.out.println(sheep); } }
輸出bash
1163157884 Sheep{name='tom', age=1, sex='male'} 1956725890 Sheep{name='tom', age=1, sex='male'} Sheep{name='tom', age=2, sex='male'} Sheep{name='tom', age=1, sex='male'}
在淺克隆中,被複制對象的全部普通成員變量都具備與原來對象相同的值,而全部的對其餘對象的引用仍然指向原來的對象。也就是說,淺克隆僅僅複製所考慮的對象,不會複製它所引用的成員對象。ide
咱們先新建一個Pearson類,做爲對象屬性函數
/** * @author codermy * @createTime 2020/7/24 */ public class Person implements Cloneable{ String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person(){ } public Person(String name){ this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
咱們先給Sheep實體類種添加一個對象屬性
/** * @author codermy * @createTime 2020/6/16 */ public class Sheep implements Cloneable { private String name; private int age; private String sex; public Person owner;//對象引用 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Person getOwner() { return owner; } public void setOwner(Person owner) { this.owner = owner; } public Sheep(String name, int age, String sex, Person owner) { this.name = name; this.age = age; this.sex = sex; this.owner = owner; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", owner=" + owner + '}'; } //克隆該實例,使用默認的clone方法 @Override protected Object clone() throws CloneNotSupportedException { Sheep sheep =null; sheep = (Sheep)super.clone(); return sheep; } }
測試類中測試
/** * @author codermy * @createTime 2020/6/16 */ public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person owner = new Person("馬雲"); Sheep sheep = new Sheep("tom",1,"male", owner);//新建sheep類 Sheep sheep1 = (Sheep)sheep.clone();//克隆該類 System.out.println(sheep.hashCode() + " " + sheep.owner.hashCode()); System.out.println(sheep + " "+ sheep.owner); System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode()); System.out.println(sheep1 + " " + sheep1.owner); sheep1.owner.setName("馬化騰"); System.out.println(sheep.owner); System.out.println(sheep1.owner); } }
輸出
1163157884 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='馬雲'}} Person{name='馬雲'} 356573597 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='馬雲'}} Person{name='馬雲'} Person{name='馬化騰'} Person{name='馬化騰'}
咱們能夠看出淺克隆時對象的引用僅僅是指向了原空間,而並無複製對象。
在深克隆中,對值類型的成員變量進行值的複製,對引用類型的成員變量也進行引用對象的複製。
將上面Sheep類中的clone方法改寫
@Override protected Object clone() throws CloneNotSupportedException { Sheep sheep =null; sheep = (Sheep)super.clone(); sheep.owner = (Person) sheep.owner.clone();//引用對象的克隆方法 return sheep; }
測試類測試
public class Client { public static void main(String[] args) throws CloneNotSupportedException { Person owner = new Person("馬雲"); Sheep sheep = new Sheep("tom",1,"male", owner); Sheep sheep1 = (Sheep)sheep.clone(); System.out.println(sheep.hashCode() + " " + sheep.owner.hashCode()); System.out.println(sheep + " "+ sheep.owner); System.out.println(sheep1.hashCode()+ " " + sheep1.owner.hashCode()); System.out.println(sheep1 + " " + sheep1.owner); sheep1.owner.setName("馬化騰"); System.out.println(sheep.owner); System.out.println(sheep1.owner); } }
輸出
1163157884 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='馬雲'}} Person{name='馬雲'} 356573597 1735600054 Sheep{name='tom', age=1, sex='male', owner=Person{name='馬雲'}} Person{name='馬雲'} Person{name='馬雲'} Person{name='馬化騰'}
這時候咱們已經實現了深克隆,可是總以爲有點「淺淺克隆」的意思,若是person類中還有對象引用那不就是。。
禁止套娃
兩個實體類實現序列化接口
Person類
public class Person implements Serializable { String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } public Person(String name){ this.name = name; } }
Sheep類
/** * @author codermy * @createTime 2020/6/16 */ public class Sheep implements Serializable { private String name; private int age; private String sex; public Person owner;//對象引用 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 String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Person getOwner() { return owner; } public void setOwner(Person owner) { this.owner = owner; } public Sheep() { } public Sheep(String name, int age, String sex, Person owner) { this.name = name; this.age = age; this.sex = sex; this.owner = owner; } @Override public String toString() { return "Sheep{" + "name='" + name + '\'' + ", age=" + age + ", sex='" + sex + '\'' + ", owner=" + owner + '}'; } }
實現
** * @author codermy * @createTime 2020/7/24 */ public class Client { public static void main(String[] args) throws Exception { Person owner = new Person("馬雲"); Sheep sheep = new Sheep("tom",1,"male", owner); ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(sheep); ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); Sheep sheep1 =(Sheep) ois.readObject(); bos.flush();oos.flush(); bos.close();oos.close(); ois.close(); System.out.println("Sheep: " + sheep); System.out.println("Sheep1: " + sheep1); System.out.println("================================"); System.out.println("Sheep: " + sheep.hashCode() + "++++++++++" + sheep.owner.hashCode()); System.out.println("Sheep1: " + sheep1.hashCode() + "++++++++++" + sheep1.owner.hashCode()); System.out.println("================================"); sheep1.owner.setName("馬化騰"); System.out.println("Sheep: " + sheep.owner); System.out.println("Sheep1: " + sheep1.owner); } }
輸出
1163157884 1956725890 Sheep{name='tom', age=1, sex='male', owner=Person{name='馬雲'}} Person{name='馬雲'} 356573597 1735600054 Sheep{name='tom', age=1, sex='male', owner=Person{name='馬雲'}} Person{name='馬雲'} Person{name='馬雲'} Person{name='馬化騰'}
優勢:原型模式是在內存中二進制流的拷貝,要比new一個對象的性能要好,特別是須要產生大量對象時。
缺點:直接在內存中拷貝,構造函數是不會執行的。