不變模式
不變模式
不變模式(immutable pattern)
一個(gè)類的內(nèi)部狀態(tài)創(chuàng)建后,在整個(gè)生命期間都不會(huì)發(fā)生變化時(shí),就是不變類。這種使用不變類的做法叫做不變模式。
不變模式有兩種形式:一種是弱不變模式,另一種是強(qiáng)不變模式,比如String類 math類,Integer類都是強(qiáng)不變類。
弱不變模式:
一個(gè)類的實(shí)例的狀態(tài)是不可變化的,但是這個(gè)類的引用的實(shí)例具有可能會(huì)變化的狀態(tài)。這樣的類符合弱不變模式的定義。要實(shí)現(xiàn)弱不變模式,一個(gè)類必須滿足如下條件:
第一,對(duì)象沒有任何方法會(huì)修改對(duì)象的狀態(tài),當(dāng)對(duì)象的構(gòu)造函數(shù)對(duì)對(duì)象的狀態(tài)初始化之后,對(duì)象的狀態(tài)便不再改變。
第二,所有的屬性都應(yīng)當(dāng)是私有的,以防客戶端對(duì)象直接修改任何的內(nèi)部狀態(tài)。
第三,這個(gè)對(duì)象所引用的對(duì)象如果是可變對(duì)象的話,必須設(shè)法限制外界對(duì)這個(gè)對(duì)象的訪問,以防止對(duì)這些對(duì)象的修改。如果可能應(yīng)該盡量在不變對(duì)象的內(nèi)部來初始化。
弱不變類的缺點(diǎn):
弱不變類的子類的對(duì)象可以是可變的,這削弱了弱不變類的作用。
可變的子類的對(duì)象可能可能修改父對(duì)象的狀態(tài),有機(jī)會(huì)允許外界修改父對(duì)象的狀態(tài),破壞了不變性。
代碼演示:
/**
* @author chenyu
*
*/
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 弱不變模式
*
* @author chenyu
*
*/
public class WeakImmutable {
// 屬性私有,滿足條件2
private int state;
// 屬性私有,滿足條件2
private User user;
private Integer age;
public WeakImmutable(int state, User user, Integer age) {
this.state = state;
this.user = user;
this.age = age;
}
public int getState() {
return this.state;
}
public User getUser() {
return this.user;
}
public Integer getAge() {
return this.age;
}
public void setState() {
// 對(duì)象沒有任何方法修改對(duì)象的狀態(tài),滿足條件1
// do nothing.
}
public static void main(String[] args) {
int state = 0;
User u = new User();
Integer age = 100;
u.setName("yes");
WeakImmutable weak = new WeakImmutable(state, u, age);
System.out.println("原始值:" + weak.getState() + ","
+ weak.getUser().getName() + "," + weak.getAge());
// 修改引用后
state = 5;
// User由于是可變對(duì)象引用,所以有影響
u.setName("no");
age = 200;
System.out.println("修改引用后:" + weak.getState() + ","
+ weak.getUser().getName() + "," + weak.getAge());
}
}
結(jié)果:可以看到user的名字會(huì)改變。
原始值:0,yes,100
修改引用后:0,no,100
強(qiáng)不變模式:
一個(gè)類的實(shí)例的狀態(tài)不會(huì)改變,同時(shí)它的子類的實(shí)例也具有不可變化的狀態(tài)。這樣的類符合強(qiáng)不變模式。要實(shí)現(xiàn)強(qiáng)不變模式,一個(gè)類必須首先滿足弱不變模式所要求的所有條件,并且還要滿足下面條件之一:
第一,所考慮的類所有的方法都應(yīng)當(dāng)是final,這樣這個(gè)類的子類不能夠置換掉此類的方法。
第二,這個(gè)類本身就是final的,那么這個(gè)類就不可能會(huì)有子類,從而也就不可能有被子類修改的問題。
不變模式在Java中的應(yīng)用
如String類
String a = "123" ;
String a1 = "123" ;
String a2 = "123" ;
String a3 = "1234" ;
java虛擬機(jī)只會(huì)創(chuàng)建一個(gè)字符串實(shí)例,a,a1,a2對(duì)象共享一個(gè)值。遇到不同的字符串,java虛擬機(jī)會(huì)再創(chuàng)建一個(gè)String對(duì)象,如a3。如果程序所處理的字串有頻繁的內(nèi)容變化,就不宜使用String類型,而應(yīng)當(dāng)使用StringBuffer類型,如果需要對(duì)字串做大量的循環(huán)查詢,也不宜使用String類型,應(yīng)當(dāng)考慮使用byte或char數(shù)組,math這個(gè)類也是不變類,你可以去看看源碼。
其它不變類:
The Integer,String, Float, Double, Byte, Long, Short, Boolean, and Character classes are all examples of an immutable class. By definition, you may not alter the value of an immutable object after its construction.In Java, a class such as Integer acts as a simple wrapper around its primitive counterpart -- in this case, int. The wrappers found in java.lang allow us to treat the primitives as if they were objects. So, for example, you could not put an int into a Vector without wrapping it。
優(yōu)缺點(diǎn):
不變模式可增強(qiáng)對(duì)象的健壯性。不變模式允許多個(gè)對(duì)象共享某一對(duì)象,降低了對(duì)該對(duì)象進(jìn)行并發(fā)訪問時(shí)的同步化開銷。唯一缺點(diǎn)是一旦需要修改一個(gè)不變對(duì)象的狀態(tài),就只好創(chuàng)建一個(gè)新的同類對(duì)象,在需要頻繁修改不變對(duì)象的環(huán)境里,會(huì)有大量的不變對(duì)象作為中間結(jié)果被創(chuàng)建出來,再被Java的垃圾收集器收走,這是一種資源的浪費(fèi)。
作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號(hào):編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進(jìn)階人工智能(鏈接)