原型模式
原型模式中,誰(shuí)涉及到對(duì)象的克隆,對(duì)象的引用和hashcode,以及原型的思想和創(chuàng)建.
在這里,自己將自己的理解和實(shí)踐記錄下來,和大家一起學(xué)習(xí).
接口Cloneable
Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
大體意思是
cloneble 保證 你的對(duì)象能在jvm中 安全的 被克隆,這里沒有clone方法.要想克隆需要 重寫clone 方法.
hashcode和引用
對(duì)象的引用: reference(C++中引用的概念是是指針的地址,java中引用在棧中,對(duì)外不開放),不是hashCode!
hashCode是用hash算法(hash算法有很多種)在散列存儲(chǔ)結(jié)構(gòu)中確定對(duì)象的存儲(chǔ)地址的,如Hashtable酵熙,HashMap中對(duì)象的存儲(chǔ).
Object中的hashCode是一個(gè)內(nèi)存地址經(jīng)過hash運(yùn)算后得到的hash值,但是hash值也有可能相同.
hashCode相同,表示兩個(gè)對(duì)象再同一個(gè)籃子,然后equals來尋找兩個(gè)對(duì)象是不是相同.
等號(hào)(==):
對(duì)比對(duì)象實(shí)例的內(nèi)存地址(也即對(duì)象實(shí)例的ID)魂莫,來判斷是否是同一對(duì)象實(shí)例;又可以說是判斷對(duì)象實(shí)例是否物理相等()势篡;
1.重寫equals時(shí)候,qual的規(guī)則要和重寫的hashcode相同.否則,用hashmap時(shí)候,將會(huì)有因?yàn)楫?dāng)你用hashSet()等的時(shí)候,會(huì)存在不同的hashCode,導(dǎo)致保存了兩個(gè)不同的對(duì)象.
關(guān)于hashcode,這是兩篇不錯(cuò)的深入文章
[傳送門1]
[傳送門2]
Object中的native方法clone()
protected native Object clone() throws CloneNotSupportedException;
clone方法是一個(gè)本地方法,它直接操作內(nèi)存中的二進(jìn)制流胎撤,特別是復(fù)制大對(duì)象時(shí)胶征,性能的差別非常明顯异吻。
JVM為每個(gè)新創(chuàng)建的線程都分配一個(gè)堆棧.
深拷貝和淺拷貝
淺拷貝
使用一個(gè)已知實(shí)例對(duì)新創(chuàng)建實(shí)例的成員變量逐個(gè)賦值尔艇,這個(gè)方式被稱為淺拷貝尔许。java中的8中基本類型以及他們的封裝類型,另外還有String.
所以,要想實(shí)現(xiàn)淺克隆,就要實(shí)現(xiàn)cloeable接口,重寫clone()方法!
深拷貝
當(dāng)一個(gè)類的拷貝構(gòu)造方法终娃,不僅要復(fù)制對(duì)象的所有非引用成員變量值味廊,還要為引用類型的成員變量創(chuàng)建新的實(shí)例,并且初始化為形式參數(shù)實(shí)例值棠耕。這個(gè)方式稱為深拷貝.
方法1:將逐層的對(duì)象進(jìn)行 實(shí)現(xiàn)cloeable接口,重寫clone()方法!
方法2:將對(duì)象串行化.
回歸正題--原型模式
一般來講,結(jié)合工廠模式,進(jìn)行 隊(duì)形緩存..
原型模式(Prototype Pattern)是用于創(chuàng)建重復(fù)的對(duì)象余佛,同時(shí)又能保證性能。這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式昧辽,它提供了一種創(chuàng)建對(duì)象的最佳方式衙熔。
類圖
代碼實(shí)現(xiàn)
Shape抽象類進(jìn)行淺克隆
public abstract class Shape implements Cloneable{
private String id;
protected String type;
abstract void draw();
/**
* 重寫clone的方法
* 強(qiáng)轉(zhuǎn) super為Shape類型
*/
@Override
protected Shape clone() {
// TODO Auto-generated method stub
Shape object=null;
try {
object= (Shape)super.clone();
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return object;
}
//...省略set,get方法
緩存類ShapeCache
public class ShapeCache {
/** @pdOid 568f3806-35b0-41de-8ba3-149c1027b27b */
private static HashMap<String, Shape> shapeCacheMap = new HashMap<>();
/**
* 簡(jiǎn)單---緩存
*
* @param type
* Traingle創(chuàng)建三角形traingle,Circle創(chuàng)建圓形Circle
* @return 緩存中的 Shape
*/
public static Shape getShape(String type) {
Shape shape = null;
shape = shapeCacheMap.get(type);
return shape.clone();
}
/**
* 當(dāng)需要更新緩存時(shí),調(diào)用
*
* @param type
* @return
*/
public static Shape loadChache(String type) {
Shape shape = null;
switch (type) {
case "Traingle":
shape=new Traingle();
shape.setId("1");
shapeCacheMap.put(type, shape);
break;
case "Circle":
shape=new Circle();
shape.setId("2");
shapeCacheMap.put(type, shape);
break;
default:
break;
}
return shape;
}
}
總結(jié)
原型模式,就是一種保存原數(shù)據(jù)不變的緩存策略.
作用:
備份源數(shù)據(jù),當(dāng)多次頻繁調(diào)用源數(shù)據(jù)(多次連接數(shù)據(jù)庫(kù)),此時(shí),只需要調(diào)用緩存中的目標(biāo)的clone,來節(jié)省時(shí)間和空間.
過程:
當(dāng)調(diào)用clone的時(shí)候,并不會(huì)調(diào)用構(gòu)造函數(shù),創(chuàng)建新的對(duì)象,而是通過一個(gè)本地方法,直接將數(shù)據(jù)寫入到另外一個(gè)地方.完成對(duì)象克隆.
注意點(diǎn):
當(dāng)拷貝一個(gè)對(duì)象時(shí),會(huì)發(fā)生深拷貝的有java中的8中基本類型以及他們的封裝類型,另外還有String類型搅荞。其余的都是淺拷貝.如果想實(shí)現(xiàn)深拷貝,需要將他的成員對(duì)象所在類中,繼承cloneable,并實(shí)現(xiàn)clone方法.