怎么樣做網(wǎng)站的目錄結(jié)構(gòu)友情鏈接買賣代理
1.原型模式定義
? ? ? ? 用一個已經(jīng)創(chuàng)建的實例作為原型,通過復制該原型對象來創(chuàng)建一個和原型對象相同的新對象;
1.1 原型模式優(yōu)缺點
優(yōu)點
- 當創(chuàng)建一個新的對象實例較為復雜時,使用原型模式可以簡化對象的創(chuàng)建過程,通過復制一個已有的實例可以提高新實例的創(chuàng)建效率;
- 相較比工程模式,原型模式提供了簡化的創(chuàng)建結(jié)構(gòu),無需專門的工廠類來創(chuàng)建產(chǎn)品;
- 可以使用深克隆的方式保存對象狀態(tài),輔助實現(xiàn)撤銷操作;
缺點
- 需要為每個類配備一個克隆方法,而且這個克隆方法位于一個類的內(nèi)部,對已有的類改造時需要修改源代碼,違反了開閉原則;
1.2 原型模式適用場景
? ? ? ? 創(chuàng)建對象的成本比較大,比如對象中的數(shù)據(jù)是經(jīng)過復雜計算或者需要從數(shù)據(jù)庫得到,這種情況就可以使用原型模式,從其他已有的對象中進行拷貝,而不是每次都創(chuàng)建新的對象;
- 資源優(yōu)化場景,如當進行對象初始化需要很多外部資源,IO資源、數(shù)據(jù)文件、CPU、網(wǎng)絡、內(nèi)存等;
- 復雜的依賴場景,如A對象的創(chuàng)建依賴B,B依賴C,C依賴D。。。
- 性能和安全要求的場景,如同一個用戶在一個會話周期里,可能會反復登錄平臺或使用某些受限的功能,每一次訪問請求都會訪問授權(quán)服務器進行授權(quán),但如果每次都通過 new 產(chǎn)生一個對象會非常煩瑣,這時則可以使用原型模式;
- 同一個對象可能被多個修改者使用的場景;
- 需要保存原始狀態(tài)的場景,如記錄歷史操作的場景;
2.原型模式原理
? ? ? ? 原型模式核心就是通過克隆復制一個對象;
- 抽象原型類(Prototype):聲明克隆方法的接口類,是所有具體原型類的公共父類,它可以是抽象類也可以是接口;
- 具體原型類(ConcretePrototype):實現(xiàn)在抽象原型類中聲明的克隆方法,在克隆方法中返回自己的一個克隆對象;
- 客戶類(Client):在客戶類中使一個原型對象克隆自身從而創(chuàng)建一個新的對象,由于客戶類針對抽象原型類編程,因此用戶可以根據(jù)需要選擇具體原型類,系統(tǒng)具有較好的擴展性,增加或者替換原型類都比較方便;?
?
2.1 深克隆與淺克隆
- 深克隆:完全創(chuàng)建一個新對象,且新對象的變量同原型一致,二者互不影響;
- 淺克隆:新對象的變量同原型一致,且新對象的引用仍然指向原型對象,二者共享同一對象;
? ? ? ? Java 中的 Object 類的 clone() 方法就是淺克隆;如下面常用的BeanUtils用到了淺克隆;
BeanUtils.cloneBean(Object obj);
???????? 對象序列化之后再進行反序列化獲取到的就是不同對象,這就是深克隆;
SerializationUtils.clone(T object);
3.原型模式實現(xiàn)
【實例】
? ? ? ? 如一個廣告郵件的發(fā)送,大部分信息都是用的模板是相同的,只有收件人等不同,如果每發(fā)送一個郵件就創(chuàng)建一個郵件對象比較浪費,這就可以用到原型模式;
【代碼】
? ? ? ? 首先實體類中重寫clone()方法
@Data
public class Mail implements Cloneable{//收件人private String receiver;//郵件名稱private String subject;//稱謂private String appellation;//郵件內(nèi)容private String context;//構(gòu)造函數(shù)public Mail(AdvTemplate advTemplate) {this.context = advTemplate.getAdvContext();this.subject = advTemplate.getAdvSubject();}@Overridepublic Mail clone(){Mail mail = null;try {mail = (Mail)super.clone();} catch (CloneNotSupportedException e) {e.printStackTrace();}return mail;}
}
? ? ? ? 然后即可克隆該對象
//模擬郵件發(fā)送
int i = 0;//把模板定義出來,數(shù)據(jù)是從數(shù)據(jù)庫獲取的
Mail mail = new Mail(new AdvTemplate());
mail.setTail("xxx銀行版權(quán)所有");
while(i < MAX_COUNT){//下面是每封郵件不同的地方Mail cloneMail = mail.clone();cloneMail.setAppellation(" 先生 (女士)");Random random = new Random();int num = random.nextInt(9999999);cloneMail.setReceiver(num+"@"+"liuliuqiu.com");//發(fā)送 郵件sendMail(cloneMail);i++;
}