不變模式
不變模式
不變模式(immutable pattern)
一個類的內(nèi)部狀態(tài)創(chuàng)建后,在整個生命期間都不會發(fā)生變化時,就是不變類。這種使用不變類的做法叫做不變模式。
不變模式有兩種形式:一種是弱不變模式,另一種是強(qiáng)不變模式,比如String類 math類,Integer類都是強(qiáng)不變類。
弱不變模式:
一個類的實(shí)例的狀態(tài)是不可變化的,但是這個類的引用的實(shí)例具有可能會變化的狀態(tài)。這樣的類符合弱不變模式的定義。要實(shí)現(xiàn)弱不變模式,一個類必須滿足如下條件:
第一,對象沒有任何方法會修改對象的狀態(tài),當(dāng)對象的構(gòu)造函數(shù)對對象的狀態(tài)初始化之后,對象的狀態(tài)便不再改變。
第二,所有的屬性都應(yīng)當(dāng)是私有的,以防客戶端對象直接修改任何的內(nèi)部狀態(tài)。
第三,這個對象所引用的對象如果是可變對象的話,必須設(shè)法限制外界對這個對象的訪問,以防止對這些對象的修改。如果可能應(yīng)該盡量在不變對象的內(nèi)部來初始化。
弱不變類的缺點(diǎn):
弱不變類的子類的對象可以是可變的,這削弱了弱不變類的作用。
可變的子類的對象可能可能修改父對象的狀態(tài),有機(jī)會允許外界修改父對象的狀態(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() {
// 對象沒有任何方法修改對象的狀態(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由于是可變對象引用,所以有影響
u.setName("no");
age = 200;
System.out.println("修改引用后:" + weak.getState() + ","
+ weak.getUser().getName() + "," + weak.getAge());
}
}
結(jié)果:可以看到user的名字會改變。
原始值:0,yes,100
修改引用后:0,no,100
強(qiáng)不變模式:
一個類的實(shí)例的狀態(tài)不會改變,同時它的子類的實(shí)例也具有不可變化的狀態(tài)。這樣的類符合強(qiáng)不變模式。要實(shí)現(xiàn)強(qiáng)不變模式,一個類必須首先滿足弱不變模式所要求的所有條件,并且還要滿足下面條件之一:
第一,所考慮的類所有的方法都應(yīng)當(dāng)是final,這樣這個類的子類不能夠置換掉此類的方法。
第二,這個類本身就是final的,那么這個類就不可能會有子類,從而也就不可能有被子類修改的問題。
不變模式在Java中的應(yīng)用
如String類
String a = "123" ;
String a1 = "123" ;
String a2 = "123" ;
String a3 = "1234" ;
java虛擬機(jī)只會創(chuàng)建一個字符串實(shí)例,a,a1,a2對象共享一個值。遇到不同的字符串,java虛擬機(jī)會再創(chuàng)建一個String對象,如a3。如果程序所處理的字串有頻繁的內(nèi)容變化,就不宜使用String類型,而應(yīng)當(dāng)使用StringBuffer類型,如果需要對字串做大量的循環(huán)查詢,也不宜使用String類型,應(yīng)當(dāng)考慮使用byte或char數(shù)組,math這個類也是不變類,你可以去看看源碼。
其它不變類:
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)對象的健壯性。不變模式允許多個對象共享某一對象,降低了對該對象進(jìn)行并發(fā)訪問時的同步化開銷。唯一缺點(diǎn)是一旦需要修改一個不變對象的狀態(tài),就只好創(chuàng)建一個新的同類對象,在需要頻繁修改不變對象的環(huán)境里,會有大量的不變對象作為中間結(jié)果被創(chuàng)建出來,再被Java的垃圾收集器收走,這是一種資源的浪費(fèi)。
作者:chen.yu
深信服三年半工作經(jīng)驗(yàn),目前就職游戲廠商,希望能和大家交流和學(xué)習(xí),
微信公眾號:編程入門到禿頭 或掃描下面二維碼
零基礎(chǔ)入門進(jìn)階人工智能(鏈接)