abstract:原理一個(gè)對(duì)象的狀態(tài)在對(duì)象被創(chuàng)建之后就不再變化,這就是所謂的不變模式。不變模式的結(jié)構(gòu) 不變模式可增強(qiáng)對(duì)象的強(qiáng)壯型(robustness)。不變模式允許多個(gè)對(duì)象共享某一個(gè)對(duì)象,降低了對(duì)該對(duì)象進(jìn)行并發(fā)訪(fǎng)問(wèn)時(shí)的同步化開(kāi)銷(xiāo)。如果需要修改一個(gè)不變對(duì)象的狀態(tài),那么就需要建立一個(gè)新的同類(lèi)型對(duì)象,并在創(chuàng)建時(shí)將這個(gè)新的狀態(tài)存儲(chǔ)在新對(duì)象里?! 〔蛔兡J街簧婕暗揭粋€(gè)類(lèi)。一個(gè)類(lèi)的內(nèi)部狀態(tài)創(chuàng)建后,在整個(gè)生命周期都不會(huì)發(fā)生變
原理
一個(gè)對(duì)象的狀態(tài)在對(duì)象被創(chuàng)建之后就不再變化,這就是所謂的不變模式。
不變模式的結(jié)構(gòu)
不變模式可增強(qiáng)對(duì)象的強(qiáng)壯型(robustness)。不變模式允許多個(gè)對(duì)象共享某一個(gè)對(duì)象,降低了對(duì)該對(duì)象進(jìn)行并發(fā)訪(fǎng)問(wèn)時(shí)的同步化開(kāi)銷(xiāo)。如果需要修改一個(gè)不變對(duì)象的狀態(tài),那么就需要建立一個(gè)新的同類(lèi)型對(duì)象,并在創(chuàng)建時(shí)將這個(gè)新的狀態(tài)存儲(chǔ)在新對(duì)象里。
不變模式只涉及到一個(gè)類(lèi)。一個(gè)類(lèi)的內(nèi)部狀態(tài)創(chuàng)建后,在整個(gè)生命周期都不會(huì)發(fā)生變化時(shí),這樣的類(lèi)稱(chēng)作不變類(lèi)。這種使用不變類(lèi)的做法叫做不變模式。不變模式有兩種形式:一種是弱不變模式,另一種是強(qiáng)不變模式。
弱不變模式
一個(gè)類(lèi)的實(shí)例的狀態(tài)是不可改變的;但是這個(gè)類(lèi)的子類(lèi)的實(shí)例具有可能會(huì)變化的狀態(tài)。這樣的類(lèi)符合弱不變模式的定義。要實(shí)現(xiàn)弱不變模式,一個(gè)類(lèi)必須滿(mǎn)足下面條件:
第一、所考慮的對(duì)象沒(méi)有任何方法會(huì)修改對(duì)象的狀態(tài);這樣一來(lái),當(dāng)對(duì)象的構(gòu)造函數(shù)將對(duì)象的狀態(tài)初始化之后,對(duì)象的狀態(tài)便不再改變。
第二、所有屬性都應(yīng)當(dāng)是私有的。不要聲明任何的公開(kāi)的屬性,以防客戶(hù)端對(duì)象直接修改任何的內(nèi)部狀態(tài)。
第三、這個(gè)對(duì)象所引用到的其他對(duì)象如何是可變對(duì)象的話(huà),必須設(shè)法限制外界對(duì)這些可變對(duì)象的訪(fǎng)問(wèn),以防止外界修改這些對(duì)象。如何可能,應(yīng)當(dāng)盡量在不變對(duì)象內(nèi)部初始化這些被引用的對(duì)象,而不要在客戶(hù)端初始化,然后再傳入到不變對(duì)象內(nèi)部來(lái)。如果某個(gè)可變對(duì)象必須在客戶(hù)端初始化,然后再傳入到不變對(duì)象里的話(huà),就應(yīng)當(dāng)考慮在不變對(duì)象初始化的時(shí)候,將這個(gè)可變對(duì)象復(fù)制一份,而不要使用原來(lái)的拷貝。
弱不變模式的缺點(diǎn)是:
第一、一個(gè)弱不變對(duì)象的子對(duì)象可以是可變對(duì)象;換言之,一個(gè)弱不變對(duì)象的子對(duì)象可能是可變的。
第二、這個(gè)可變的子對(duì)象可能可以修改父對(duì)象的狀態(tài),從而可能會(huì)允許外界修改父對(duì)象的狀態(tài)。
強(qiáng)不變模式
一個(gè)類(lèi)的實(shí)例不會(huì)改變,同時(shí)它的子類(lèi)的實(shí)例也具有不可變化的狀態(tài)。這樣的類(lèi)符合強(qiáng)不變模式。要實(shí)現(xiàn)強(qiáng)不變模式,一個(gè)類(lèi)必須首先滿(mǎn)足弱不變模式所要求的所有條件,并且還有滿(mǎn)足下面條件之一:
第一、所考慮的類(lèi)所有的方法都應(yīng)當(dāng)是final,這樣這個(gè)類(lèi)的子類(lèi)不能夠置換掉此類(lèi)的方法。
第二、這個(gè)類(lèi)本身就是final的,那么這個(gè)類(lèi)就不可能會(huì)有子類(lèi),從而也就不可能有被子類(lèi)修改的問(wèn)題。
“不變"和"只讀"的區(qū)別
"不變"(Immutable)與"只讀"(Read Only)是不同的。當(dāng)一個(gè)變量是”只讀“時(shí),變量的值不能直接改變,但是可以在其他變量發(fā)生改變的時(shí)候發(fā)生改變。
比如,一個(gè)人的出生年月日是”不變“屬性,而一個(gè)人的年齡便是”只讀“屬性,不是”不變“屬性。隨著時(shí)間的變化,一個(gè)人的年齡會(huì)隨之發(fā)生變化,而人的出生年月日則不會(huì)變化。這就是”不變“和“只讀”的區(qū)別。
不變模式在JAVA中的應(yīng)用
不變模式在JAVA中最著名的應(yīng)用便是java.lang.String類(lèi)。String類(lèi)是一個(gè)強(qiáng)不變類(lèi)型,在出現(xiàn)如下的語(yǔ)句時(shí):
String a = "test"; String b = "test"; String c = "test";
JAVA虛擬機(jī)其實(shí)只會(huì)創(chuàng)建這樣一個(gè)字符串的實(shí)例,而這三個(gè)String對(duì)象都在共享這一個(gè)值。
不變模式的優(yōu)點(diǎn)和缺點(diǎn)
不變模式有很明顯的優(yōu)點(diǎn):
(1)因?yàn)椴荒苄薷囊粋€(gè)不變對(duì)象的狀態(tài),所以可以避免由此引起的不必要的程序錯(cuò)誤;換言之,一個(gè)不變的對(duì)象要比可變的對(duì)象更加容易維護(hù)。
?。?)因?yàn)闆](méi)有任何一個(gè)線(xiàn)程能夠修改不變對(duì)象的內(nèi)部狀態(tài),一個(gè)不變對(duì)象自動(dòng)就是線(xiàn)程安全的,這樣就可以省掉處理同步化的開(kāi)銷(xiāo)。一個(gè)不變對(duì)象可以自由地被不同的客戶(hù)端共享。
不變模式的缺點(diǎn):
不變模式唯一的缺點(diǎn)是:一旦需要修改一個(gè)不變對(duì)象的狀態(tài),就只好創(chuàng)建一個(gè)新的同類(lèi)對(duì)象。在需要頻繁修改不變對(duì)象的環(huán)境里,會(huì)有大量的不變對(duì)象作為中間結(jié)果被創(chuàng)建出來(lái),再被JAVA垃圾收集器收集走。這是一種資源上的浪費(fèi)。
在設(shè)計(jì)任何一個(gè)類(lèi)的時(shí)候,應(yīng)當(dāng)慎重考慮其狀態(tài)是否有需要變化的可能性。除非其狀態(tài)有變化的必要,不然應(yīng)當(dāng)將它設(shè)計(jì)成不變類(lèi)。