十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本文源碼:GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里
虎林ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!
原型模式屬于對(duì)象的創(chuàng)建模式。通過給出一個(gè)原型對(duì)象來指明所有創(chuàng)建的對(duì)象的類型,然后用復(fù)制這個(gè)原型對(duì)象的辦法創(chuàng)建出更多同類型的對(duì)象。
原型模式要求對(duì)象實(shí)現(xiàn)一個(gè)可以“克隆”自身的接口,這樣就可以通過復(fù)制一個(gè)實(shí)例對(duì)象本身來創(chuàng)建一個(gè)新的實(shí)例。這樣一來,通過原型實(shí)例創(chuàng)建新的對(duì)象,就不再需要關(guān)心這個(gè)實(shí)例本身的類型,只要實(shí)現(xiàn)了克隆自身的方法,就可以通過這個(gè)方法來獲取新的對(duì)象,而無須再去通過new來創(chuàng)建。
1)、UML關(guān)系圖
2)、核心角色
這種形式涉及到三個(gè)角色:
1)、客戶(Client)角色:客戶類提出創(chuàng)建對(duì)象的請(qǐng)求。
2)、抽象原型(Prototype)角色:這是一個(gè)抽象角色,通常由一個(gè)Java接口或Java抽象類實(shí)現(xiàn)。此角色給出所有的具體原型類所需的接口。
3)、具體原型(Concrete Prototype)角色:被復(fù)制的對(duì)象。此角色需要實(shí)現(xiàn)抽象的原型角色所要求的接口。
3)、基于JDK源碼實(shí)現(xiàn)
/**
* 基于JDK源碼方式實(shí)現(xiàn)原型模式
*/
public class C01_Property {
public static void main(String[] args) {
Product product = new Product("機(jī)械鍵盤","白色",100.00) ;
Product product1 = (Product) product.clone();
Product product2 = (Product) product.clone();
System.out.println(product1);
System.out.println(product2);
System.out.println(product1==product2); // false
}
}
class Product implements Cloneable {
private String name ;
private String color ;
private Double price ;
public Product(String name, String color, Double price) {
this.name = name;
this.color = color;
this.price = price;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
", price=" + price +
'}';
}
@Override
protected Object clone() {
Product product = null ;
try{
product = (Product)super.clone() ;
} catch (Exception e){
e.printStackTrace();
}
return product ;
}
// 省略GET和SET方法
}
@Test
public void test01 (){
ApplicationContext context01 = new ClassPathXmlApplicationContext(
"/spring/spring-property.xml");
// 原型模式
Sheep sheep1 = (Sheep)context01.getBean("sheep01") ;
Sheep sheep2 = (Sheep)context01.getBean("sheep01") ;
System.out.println(sheep1==sheep2); // false
// 單例模式
Sheep sheep3 = (Sheep)context01.getBean("sheep02") ;
Sheep sheep4 = (Sheep)context01.getBean("sheep02") ;
System.out.println(sheep3==sheep4); // true
}
1)、執(zhí)行流程
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory
2)、單例多例判斷
所以默認(rèn)就是單例模式,指定[scope="prototype"]就是原型模式。
public boolean isSingleton() {
return "singleton".equals(this.scope) || "".equals(this.scope);
}
public boolean isPrototype() {
return "prototype".equals(this.scope);
}
1) 數(shù)據(jù)類型是基本數(shù)據(jù)類型、String類型的成員變量,淺拷貝直接進(jìn)行值傳遞,也就是將該屬性值復(fù)制一份給新的對(duì)象。
2) 數(shù)據(jù)類型是引用數(shù)據(jù)類型的成員變量,比如說成員變量是數(shù)組、類的對(duì)象等,淺拷貝會(huì)進(jìn)行引用傳遞,也就是只是將該成員變量的引用值(內(nèi)存地址)復(fù)制一份給新的對(duì)象。實(shí)際上兩個(gè)對(duì)象的成員變量都指向同一個(gè)實(shí)例。修改其中一個(gè)對(duì)象屬性會(huì)影響到另一個(gè)對(duì)象的屬性。
3) 淺拷貝是使用默認(rèn)的 clone()方法來實(shí)現(xiàn)。
1)、概念描述
除了淺拷貝要拷貝的值外,還負(fù)責(zé)拷貝引用類型的數(shù)據(jù)。那些引用其他對(duì)象的變量將指向被復(fù)制過的新對(duì)象,而不再是原有的那些被引用的對(duì)象,這種對(duì)被引用到的對(duì)象的復(fù)制叫做間接復(fù)制。
2)、源代碼實(shí)現(xiàn)
序列化實(shí)現(xiàn)深度克隆
對(duì)象寫到流里的過程是序列化(Serialization)過程;而把對(duì)象從流中讀出來的過程則叫反序列化(Deserialization)過程。應(yīng)當(dāng)指出的是,寫到流里的是對(duì)象的一個(gè)拷貝,而原對(duì)象仍然存在于JVM里面。
在Java語言里深度克隆一個(gè)對(duì)象,常??梢韵仁箤?duì)象實(shí)現(xiàn)Serializable接口,然后把對(duì)象(實(shí)際上只是對(duì)象的拷貝)寫到一個(gè)流里(序列化),再從流里讀回來(反序列化),便可以重建對(duì)象。
/**
* 深拷貝和淺拷貝對(duì)比案例
*/
public class C02_DeepClone {
public static void main(String[] args) throws Exception {
Dog dog = new Dog("Tom") ;
Dog dog1 = (Dog)dog.clone() ;
Dog dog2 = (Dog)dog.clone() ;
// dog1:1639622804;dog2:1639622804
System.out.println("dog1:"+dog1.cat.hashCode()+";dog2:"+dog2.cat.hashCode());
Dog dog3 = (Dog)dog.deepClone() ;
Dog dog4 = (Dog)dog.deepClone() ;
// dog3:1937348256;dog4:1641808846
System.out.println("dog3:"+dog3.cat.hashCode()+";dog4:"+dog4.cat.hashCode());
}
}
class Cat implements Serializable {
public String name ;
public Cat (String name){
this.name = name ;
}
}
class Dog implements Cloneable,Serializable {
public String name ;
public Cat cat ;
public Dog (String name){
this.name = name ;
this.cat = new Cat("Kit") ;
}
@Override
protected Object clone() {
Dog dog = null ;
try{
dog = (Dog)super.clone() ;
} catch (Exception e){
e.printStackTrace();
}
return dog ;
}
public Object deepClone() throws IOException, ClassNotFoundException{
//將對(duì)象寫到流里面:序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//從流里面讀出對(duì)象:反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
原型模式允許在運(yùn)行時(shí)動(dòng)態(tài)改變具體的實(shí)現(xiàn)類型。原型模式可以在運(yùn)行期間,由客戶來注冊(cè)符合原型接口的實(shí)現(xiàn)類型,也可以動(dòng)態(tài)地改變具體的實(shí)現(xiàn)類型,看起來接口沒有任何變化,但其實(shí)運(yùn)行的已經(jīng)是另外一個(gè)類實(shí)例了。因?yàn)榭寺∫粋€(gè)原型就類似于實(shí)例化一個(gè)類。
原型模式最主要的缺點(diǎn)是每一個(gè)類都必須配備一個(gè)克隆方法。配備克隆方法需要對(duì)類的功能進(jìn)行通盤考慮,這對(duì)于全新的類來說不是很難,而對(duì)于已經(jīng)有的類不一定很容易,特別是當(dāng)一個(gè)類引用不支持序列化的間接對(duì)象,或者引用含有循環(huán)結(jié)構(gòu)的時(shí)候。
GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent