天天看點

JAVA IO 序列化與設計模式

序列化

什麼是序列化

序列化:儲存對象的狀态

反序列化:讀取儲存對象的狀态

序列化和序列化是java提供的一種儲存恢複對象狀态的機制

序列化有什麼用

将資料儲存到檔案或資料庫中時

将資料通過套接字在網絡上傳輸時

通過 rpc rmi等傳輸對象時

如何序列化

實作serializable接口

實作externalizable接口

serialversionuid的作用serialversionuid建議給一個确定的值,不要由系統自動生成,否則在增減字段(不能修改字段類型及長度)時,如果兩邊的類的版本不同會導緻反序列化失敗

預設序列化機制

如果僅僅隻是讓某個類實作serializable接口,而沒有其它任何處理的話,則就是使用預設序列化機制。使用預設機制,在序列化對象時,不僅會序列化目前對象本身,還會對該對象引用的其它對象也進行序列化,同樣地,這些其它對象引用的另外對象也将被序列化,以此類推。是以,如果一個對象包含的成員變量是容器類對象,而這些容器所含有的元素也是容器類對象,那麼這個序列化的過程就會較複雜,開銷也較大。

(01) 序列化對static和transient變量,是不會自動進行狀态儲存的。

transient的作用就是,用transient聲明的變量,不會被自動序列化。

(02) 對于socket, thread類,不支援序列化。若實作序列化的接口中,有thread成員;在對該類進行序列化操作時,運作會出錯。

這主要是基于資源配置設定方面的原因。如果socket,thread類可以被序列化,但是被反序列化之後也無法對他們進行重新的資源配置設定。

示例:

java io的設計模式 

java io架構主要使用的兩種設計模式 裝飾模式和擴充卡模式

裝飾模式又名包裝(wrapper)模式

裝飾模式以對用戶端透明的方式擴充對象的功能,是繼承關系的一個替代方案。

裝飾模式通過建立一個包裝對象,也就是裝飾,來包裹真實的對象。

裝飾模式以對用戶端透明的方式動态地給一個對象附加上更多的責任。換言之,用戶端并不會覺得對象在裝飾前和裝飾後有什麼不同。

裝飾模式可以在不創造更多子類的情況下,将對象的功能加以擴充。

裝飾模式把用戶端的調用委派到被裝飾類。裝飾模式的關鍵在于這種擴充是完全透明的。 

裝飾模式的角色

抽象構件角色(component):給出一個抽象接口,以規範準備接收附加責任的對象。

具體構件角色(concrete component):定義将要接收附加責任的類。

裝飾角色(decorator):持有一個構件(component)對象的引用,并定義一個與抽象構件接口一緻的接口。

具體裝飾角色(concrete decorator):負責給構件對象“貼上”附加的責任。

裝飾模式的特點

裝飾對象和真實對象有相同的接口。這樣用戶端對象就可以以和真實對象相同的方式和裝飾對象互動。

裝飾對象包含一個真實對象的引用(reference)。

裝飾對象接收所有來自用戶端的請求,它把這些請求轉發給真實的對象。

裝飾對象可以在轉發這些請求之前或之後附加一些功能。

這樣就確定了在運作時,不用修改給定對象的結構就可以在外部增加附加的功能。

裝飾模式的優點

裝飾模式與繼承關系的目的都是要擴充對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。裝飾模式允許系統動态決定“貼上”一個需要的“裝飾”,或者除掉一個不需要的“裝飾”。繼承關系則不同,繼承關系是靜态的,它在系統運作前就決定了。

通過使用不同的具體裝飾類以及這些裝飾類的排列組合,設計師可以創造出很多不同行為的組合。

裝飾模式的缺點

由于使用裝飾模式,可以比使用繼承關系需要較少數目的類。使用較少的類,當然使設計比較易于進行。但是,在另一方面,使用裝飾模式會産生比使用繼承關系更多的對象。更多的對象會使得查錯變得困難,特别是這些對象看上去都很相像。

java io中的裝飾模式

抽象構件(component)角色:由inputstream扮演。這是一個抽象類,為各種子類型提供統一的接口。

具體構件(concretecomponent)角色:由bytearrayinputstream、fileinputstream、pipedinputstream、stringbufferinputstream等類扮演。它們實作了抽象構件角色所規定的接口。

抽象裝飾(decorator)角色:由filterinputstream扮演。它實作了inputstream所規定的接口。

具體裝飾(concretedecorator)角色:由幾個類扮演,分别是bufferedinputstream、datainputstream以及兩個不常用到的類linenumberinputstream、pushbackinputstream。

擴充卡模式

JAVA IO 序列化與設計模式

上圖是擴充卡模式的類圖。adapter 擴充卡設計模式中有 3 個重要角色:被适配者 adaptee,擴充卡 adapter 和目标對象 target。其中兩個現存的想要組合到一起的類分别是被适配者 adaptee 和目标對象 target 角色,按照類圖所示,我們需要建立一個擴充卡 adapter 将其組合在一起。

最簡單的擴充卡示例:

java i/o 庫大量使用了擴充卡模式,例如 bytearrayinputstream 是一個擴充卡類,它繼承了 inputstream 的接口,并且封裝了一個 byte 數組。換言之,它将一個 byte 數組的接口适配成 inputstream 流處理器的接口。

我們知道 java 語言支援四種類型:java 接口,java 類,java 數組,原始類型(即 int,float 等)。前三種是引用類型,類和數組的執行個體是對象,原始類型的值不是對象。也即,java 語言的數組是像所有的其他對象一樣的對象,而不管數組中所存儲的元素類型是什麼。這樣一來的話,bytearrayinputstream 就符合擴充卡模式的描述,是一個對象形式的擴充卡類。fileinputstream 是一個擴充卡類。在 fileinputstream 繼承了 inputstrem 類型,同時持有一個對 filediscriptor 的引用。這是将一個 filediscriptor 對象适配成 inputstrem 類型的對象形式的擴充卡模式。

同樣地,在 outputstream 類型中,所有的原始流處理器都是擴充卡類。bytearrayoutputstream 繼承了 outputstream 類型,同時持有一個對 byte 數組的引用。它一個 byte 數組的接口适配成 outputstring 類型的接口,是以也是一個對象形式的擴充卡模式的應用。

fileoutputstream 繼承了 outputstream 類型,同時持有一個對 filediscriptor 對象的引用。這是一個将 filediscriptor 接口适配成 outputstream 接口形式的對象型擴充卡模式。

reader 類型的原始流處理器都是擴充卡模式的應用。stringreader 是一個擴充卡類,stringreader 類繼承了 reader 類型,持有一個對 string 對象的引用。它将 string 的接口适配成 reader 類型的接口。

裝飾模式和擴充卡模式的對比

(1)裝飾模式和擴充卡模式,都是通過封裝其他對象達到設計目的的。

(2)理想的裝飾模式在對被裝飾對象進行功能增強時,要求具體構件角色、裝飾角色的接口與抽象構件角色的接口完全一緻;而擴充卡模式則不然,一般而言,擴充卡模式并不要求對源對象的功能進行增強,隻是利用源對象的功能而已,但是會改變源對象的接口,以便和目标接口相符合。

(3)裝飾模式有透明和半透明兩種,差別就在于接口是否完全一緻。關于裝飾模式的重要的事實是,很難找到理想的裝飾模式。一般而言,對一個對象進行功能增強的同時,都會導緻加入新的行為,是以,裝飾角色的接口比抽象構件角色的接口寬是很難避免的,這種現象存在于java i/o庫中多有的類型的連結流處理器中。一個裝飾類提供的新的方法越多,它離純裝飾模式的距離就越遠,離擴充卡模式的距離也就越近。