GOF23设计模式(创建型模式) 原型模式
目錄
一:原型模式的定義
二:關(guān)于深克隆和深克隆的區(qū)別
三:反序列化的方式實(shí)現(xiàn)深克隆
原型模式:
通過(guò)new產(chǎn)生一個(gè)對(duì)象需要非常繁瑣的數(shù)據(jù)準(zhǔn)備或訪冋權(quán)限,則可以使用原型模式。
就是java中的克隆技術(shù),以某個(gè)對(duì)象為原型,復(fù)制出新的對(duì)象。顯然,新的對(duì)象具備原型對(duì)象的特點(diǎn)
優(yōu)勢(shì)有:效率高(直接克隆,避免了重新執(zhí)行構(gòu)造過(guò)程步驟).
克隆類似于new,但是不同于new。new創(chuàng)建新的對(duì)象屬性采用的是默認(rèn)值。克隆出的對(duì)象的屬性值完全和原型對(duì)象相同。并且克隆出的新對(duì)象改變不會(huì)影晌原型對(duì)象。然后,再修改克隆對(duì)象的值
原型模式實(shí)現(xiàn):
繼承Cloneable接囗和重寫(xiě)clone()方法
詳解深克隆與淺克隆的區(qū)別示例:
打個(gè)比方,比如我們我們考試的時(shí)候,要抄別人的試卷,根據(jù)原型模式的思想,是沒(méi)有必要從頭到尾抄一遍的,而是把別人的試卷克隆一份,在這基礎(chǔ)上進(jìn)行修改就行了,而java給我們提供了clone()方法,讓我們看看jdk里面的描述:
| public interface Cloneable 一個(gè)類實(shí)現(xiàn)Cloneable接口,以指示Object.clone()方法,該方法對(duì)于該類的實(shí)例進(jìn)行現(xiàn)場(chǎng)復(fù)制是合法的。 在不實(shí)現(xiàn)Cloneable接口的實(shí)例上調(diào)用對(duì)象的克隆方法導(dǎo)致拋出異常CloneNotSupportedException 。 按照慣例,實(shí)現(xiàn)此接口的類應(yīng)使用公共方法覆蓋Object.clone (受保護(hù))。 |
因此,我們要用clone()方法,必須繼承Cloneable接口!!!!!!!!
關(guān)于克隆,其實(shí)分別兩類:
| 復(fù)制對(duì)象時(shí)僅僅復(fù)制對(duì)象本身,包括基本數(shù)據(jù)類型的屬性,但該對(duì)象的屬性為引用數(shù)據(jù)類型時(shí),不會(huì)進(jìn)行復(fù)制引用的對(duì)象,即拷貝出來(lái)的對(duì)象與被拷貝出來(lái)的對(duì)象中的屬性引用的對(duì)象是同一個(gè)。 |
| 創(chuàng)建一個(gè)新對(duì)象,屬性中引用的其他對(duì)象也會(huì)被克隆,不再指向原有對(duì)象地址。 |
?
接下來(lái),我將以試卷的克隆為例,實(shí)現(xiàn)一下clone()方法,并分析一下淺克隆和深克隆的區(qū)別~
- 首先創(chuàng)建一個(gè)試卷類test_paper繼承Cloneable接口,然后我們就實(shí)現(xiàn)Object類的clone()方法,該類有兩個(gè)私有屬性,一個(gè)是姓名name(基本數(shù)據(jù)類型)、一個(gè)是日期date(引用數(shù)據(jù)類型),添加對(duì)應(yīng)的構(gòu)造器和set、get方法
package 四_原型模式;import java.util.Date;/*** 克隆試卷*/public class test_paper implements Cloneable {String name;//名字,基本數(shù)據(jù)類型Date date;//日期,引用數(shù)據(jù)類型//克隆方法@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}public test_paper() {}public test_paper(String name, Date date) {this.name = name;this.date = date;}public String getName() {return name;}@Overridepublic String toString() {return "test_paper{" +"name='" + name + '\'' +", date=" + date +'}';}public void setName(String name) {this.name = name;}public Date getDate() {return date;}public void setDate(Date date) {this.date = date;}} ?
? ? ? ? ? 2. 然后我們?cè)谥骱瘮?shù)里面進(jìn)行測(cè)試
package 四_原型模式;import java.util.Date;@SuppressWarnings("all")public class Client {public static void main(String[] args) throws CloneNotSupportedException {Date date = new Date();String name = "zsr";test_paper paper1 = new test_paper(name, date);test_paper paper2 = (test_paper) paper1.clone();//通過(guò)paper1克隆出的對(duì)象paper2.getDate().setDate(1000);paper2.setName("gcc");//如果修改paper2的引用類型(非基本數(shù)據(jù)類型)屬性值,//paper1的對(duì)應(yīng)的引用類型屬性值會(huì)跟著更改,因?yàn)檫@是淺克隆,克隆出的對(duì)象和元對(duì)象指向同一個(gè)屬性System.out.println(paper1);System.out.println(paper2);}} ?
根據(jù)運(yùn)行結(jié)果,我們發(fā)現(xiàn)正確克隆出了一張新的試卷,
- 我們修改克隆出的試卷的基本類型的屬性name,原試卷對(duì)應(yīng)的name屬性并沒(méi)有改變
- 但是我們修改克隆對(duì)象試卷的引用類型屬性date,原試卷的date屬性值跟著改變了,這就是淺復(fù)制
- 淺復(fù)制復(fù)制的時(shí)候復(fù)制了自己的本身,以及本身的基本類型的屬性,但是對(duì)于自己的非基本數(shù)據(jù)類型的屬性,并沒(méi)有復(fù)制出一個(gè)新的相應(yīng)的引用對(duì)象,即復(fù)制出來(lái)的對(duì)象與原對(duì)象中的非基本類型屬性引用的對(duì)象是同一個(gè)!!所以對(duì)引用類型的屬性進(jìn)行修改,原對(duì)象和克隆對(duì)象對(duì)應(yīng)的屬性值都會(huì)改變!!!!!!
這樣就沒(méi)有達(dá)到完全復(fù)制、原對(duì)象和克隆對(duì)象相互之間完全沒(méi)有影響的目的。那如果我們都想復(fù)制呢??那就引入了深復(fù)制~~
我們只需要在clone()方法中添加對(duì)應(yīng)非基本類型屬性的復(fù)制
在這個(gè)示例中,即加入對(duì)date屬性的復(fù)制即可~
??? //克隆方法@Overrideprotected Object clone() throws CloneNotSupportedException {test_paper paper = (test_paper) super.clone();paper.date = (Date) date.clone();return paper;} ?
根據(jù)我們新的實(shí)驗(yàn)結(jié)果,我們發(fā)現(xiàn),修改paper2的所有屬性值,對(duì)應(yīng)的paper1元對(duì)象的屬性值都不會(huì)改變,這就是深克隆,達(dá)到了元對(duì)象和克隆對(duì)象之間不會(huì)影響的效果!!
當(dāng)然,實(shí)現(xiàn)深復(fù)制的方式可不止這么一種,我們還可以通過(guò)實(shí)現(xiàn)序列化和反序列化的方式實(shí)現(xiàn)深復(fù)制~
代碼實(shí)現(xiàn):
package 四_原型模式;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.Date;@SuppressWarnings("all")public class Client {public static void main(String[] args) throws Exception {Date date = new Date();String name = "zsr";test_paper paper1 = new test_paper(name, date);//通過(guò)序列化和反序列化來(lái)實(shí)現(xiàn)深克隆ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream obs = new ObjectOutputStream(bos);obs.writeObject(paper1);byte a[] = bos.toByteArray();ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(a));test_paper paper3 = (test_paper) ois.readObject();//獲取到新對(duì)象paper3.getDate().setDate(1000);//改變非基本類型屬性System.out.println(paper1);System.out.println(paper3);}} ?
根據(jù)實(shí)驗(yàn)結(jié)果,我們成功利用序列化和反序列化實(shí)現(xiàn)了深克隆~
總結(jié)
以上是生活随笔為你收集整理的GOF23设计模式(创建型模式) 原型模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: GOF23设计模式(创建型模式)建造者模
- 下一篇: hexo框架个人博客的搭建(面试加分!)