積千里跬步,匯萬里江河;每天進步一點點,終有一天將成大佬
所有源代碼都在這:https://github.com/z573419235/GofDemo
各位大佬記得點個星星哦
前言
? 前幾天生病了,每天頭昏腦脹的,誒,生病的時候才知道身體健康的重要性,以后還是要加強鍛煉,身體是革命的本錢;
? 隔了差不多有五六天沒寫日志了,罪過罪過;好了,今天要說的是原型模式,原型模式在Java
中核心秘密就是clone
這個方法,通過重新Object
中的clone
方法.來達到原型模式;而要重新clone
方法就必須要實現(xiàn)Cloneable
這個接口,不實現(xiàn)這個接口的話就會報java.lang.CloneNotSupportedException
異常;
我是鳴人
? 鳴人最喜歡的就是吃拉面,就算是上課的時候也是心心念念的想著一樂大叔的拉面
先來看看鳴人的原型實體類:
/**
* @author zheng
*
* 我是鳴人實體類
*/
@Data
public class Naruto implements Cloneable{
/**
* 姓名
* */
private String name="鳴人";
/**
* 年齡
* */
private int age=13;
/**
* 任務(wù)
* */
private String task;
/**
*愛好
* */
private ArrayList<String> hobby=new ArrayList<>();
/**
* 構(gòu)造方法
* */
public Naruto(){
this.hobby.add("吃拉面");
this.hobby.add("泡溫泉");
}
/**
* 重寫Object類的clone方法
* */
@Override
public Naruto clone(){
Naruto naruto=null;
try {
naruto=(Naruto)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return naruto;
}
@Override
public String toString() {
return "Naruto{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", task='" + task + '\'' +
", hobby=" + hobby +
'}';
}
}
為了代碼整潔,我安裝了lombok插件,所以不用寫get/set方法,直接加個
@Data
注解就可以了;
一天,鳴人上著伊魯卡老師的課,可是心里還是念念不忘一樂大叔的拉面,想著前幾天剛學(xué)了影分身之術(shù),想著用分身術(shù)逃出去吃拉面.于是他就有變了一個分身留著這上課,自己卻跑去吃拉面了;
/**
* 原型模式
* @author zheng
* */
public class Main {
public static void main(String[] args) {
//我是鳴人本人
Naruto naruto=new Naruto();
//我是影分身
Naruto narutoYin=naruto.clone();
narutoYin.setTask("上課");
naruto.setTask("吃拉面");
System.out.println("鳴人本人:"+naruto.toString());
System.out.println("影分身:"+narutoYin.toString());
}
}
//控制臺輸出
鳴人本人:Naruto{name='鳴人', age='13', task='吃拉面', hobby=[吃拉面, 泡溫泉]}
影分身:Naruto{name='鳴人', age='13', task='上課', hobby=[吃拉面, 泡溫泉]}
可以看到,鳴人本人的任務(wù)是去吃拉面,他的影分身的任務(wù)是留著教室上課;當然鳴人可以通過他本人創(chuàng)建無數(shù)個影分身,同時執(zhí)行多個任務(wù);這就是原型模式;
淺拷貝和深拷貝
原型模式就是通過一個原型clone出多個和原型一樣的類,但是拷貝也分淺拷貝和深拷貝;
淺拷貝
淺拷貝有多淺,淺到就相當于沒有給你拷貝,他就是讓你和原型共用一個空間,沒有給你分配新的內(nèi)存;
比如上面的鳴人本人有愛好,但是隱分身一般是沒有愛好的,所以創(chuàng)建隱分身要吧愛好給清除調(diào):
/**
* 原型模式
* @author zheng
* */
public class Main {
public static void main(String[] args) {
//我是鳴人本人
Naruto naruto=new Naruto();
//我是影分身
Naruto narutoYin=naruto.clone();
narutoYin.setTask("上課");
//影分身不配有愛好
narutoYin.getHobby().clear();
naruto.setTask("吃拉面");
System.out.println("鳴人本人:"+naruto.toString());
System.out.println("影分身:"+narutoYin.toString());
}
}
//控制臺輸出
鳴人本人:Naruto{name='鳴人', age='13', task='吃拉面', hobby=[]}
影分身:Naruto{name='鳴人', age='13', task='上課', hobby=[]}
WTF,竟然把本人的愛好也清除調(diào)了,那還去吃啥拉面啊,算了算了,安安心心上課吧,誒;叫你上影分身課是時候不認真,失敗了吧!!!
深拷貝
深拷貝就是在
clone
方法里除了克隆類之外,還要克隆引用對象,這樣才會重新給引用對象分配新的內(nèi)存空間
進過上次的教訓(xùn),鳴人苦練影分身之術(shù),終于學(xué)得核心所在,看看他新的影分身技能吧:
在變一個看看:
/**
* 原型模式
* @author zheng
* */
public class Main {
public static void main(String[] args) {
//我是鳴人本人
Naruto naruto=new Naruto();
//我是影分身
Naruto narutoYin=naruto.clone();
narutoYin.setTask("上課");
//影分身不配有愛好
narutoYin.getHobby().clear();
naruto.setTask("吃拉面");
System.out.println("鳴人本人:"+naruto.toString());
System.out.println("影分身:"+narutoYin.toString());
}
}
//控制臺輸出
鳴人本人:Naruto{name='鳴人', age='13', task='吃拉面', hobby=[吃拉面, 泡溫泉]}
影分身:Naruto{name='鳴人', age='13', task='上課', hobby=[]}
哈哈,成功了,這下可以安安心心的區(qū)吃拉面了吧;
總結(jié)
? 引用設(shè)計模式之禪的一句話:內(nèi)部的數(shù)組和引用對象才不拷貝,其他的原始類型比如int
慎陵、long
才顿、char
等都會被拷貝俩莽,但是對于String
類型衍腥,Java
就希望你把它認為是基本類型,它是沒有clone方法的唱歧,處理機制也比較特殊岖免,通過字符串池(stringpool)在需要的時候才在內(nèi)存中創(chuàng)建新的字符串,在使用的時候就把String
當做基本類使用即可合愈。注意:使用clone方法叮贩,在類的成員變量上就不要增加final關(guān)鍵字,否則當你重新設(shè)置這個成員變量的值時是不能設(shè)置的,因為final的不可變的,只能引用原來的值