Cactoos中的面向对象的声明式输入/输出
Cactoos是一個面向對象的Java原語庫, 我們幾周前才開始使用它。 目的是為JDK,Guava,Apache Commons等提供一種干凈且更具聲明性的替代方案。 我們不是使用靜態過程,而是使用對象的使用方式,而是使用對象。 讓我們看看輸入/輸出如何以純面向對象的方式工作。
假設您要讀取文件。 這是使用JDK7中的實用程序類 Files的靜態方法readAllBytes()進行的操作:
byte[] content = Files.readAllBytes(new File("/tmp/photo.jpg").toPath() );這段代碼非常重要-它會立即讀取文件內容,并將其放入數組中。
這就是您使用Cactoos的方法 :
Bytes source = new InputAsBytes(new FileAsInput(new File("/tmp/photo.jpg")) );注意-還沒有方法調用。 只有三個構造函數或三個類組成一個更大的對象。 對象source的類型為Bytes ,代表文件的內容。 為了從中獲取內容,我們將其方法asBytes() :
bytes[] content = source.asBytes();這是觸摸文件系統的時刻。 如您所見,這種方法絕對是聲明性的,并且由于它具有面向對象的所有優點。
這是另一個例子。 假設您要向文件中寫入一些文本。 這是您在Cactoos中的操作方法。 首先,您需要Input :
Input input = new BytesAsInput(new TextAsBytes(new StringAsText("Hello, world!")) );然后,您需要Output :
Output output = new FileAsOutput(new File("/tmp/hello.txt") );現在,我們要將輸入復制到輸出。 純 OOP中沒有“復制”操作。 而且,根本不能進行任何操作。 只是對象。 我們有一個名為TeeInput的類,它是一個Input ,它將您從其中讀取的所有內容復制到Output ,類似于Apache Commons的 TeeInputStream所做的TeeInputStream ,但被封裝了。 因此,我們不進行復制,而是創建一個Input ,如果您觸摸它,它將復制:
Input tee = new TeeInput(input, output);現在,我們必須“觸摸”它。 而且我們必須觸摸它的每個字節,以確保它們都被復制了。 如果我們僅read()第一個字節,則只有一個字節將被復制到文件中。 觸摸所有對象的最佳方法是計算tee對象的大小,逐字節地計算。 我們有一個對象,叫做LengthOfInput 。 它封裝了一個Input ,其行為類似于其以字節為單位的長度:
Scalar<Long> length = new LengthOfInput(tee);然后我們從中取出值,然后進行文件寫入操作:
long len = length.asValue();因此,將字符串寫入文件的整個操作將如下所示:
new LengthOfInput(new TeeInput(new BytesAsInput(new TextAsBytes(new StringAsText("Hello, world!"))),new FileAsOutput(new File("/tmp/hello.txt"))) ).asValue(); // happens here這是它在JDK7中的替代程序:
Files.write(new File("/tmp/hello.txt").toPath(),"Hello, world!".getBytes() );“為什么面向對象即使更長,也更好?” 我聽到你問。 因為它完美地解耦了概念,而過程化的概念卻將它們保持在一起。
假設您正在設計一個類,該類應該加密一些文本并將其保存到文件中。 這是您將如何以程序方式設計它的方法(當然,這不是真正的加密):
class Encoder {private final File target;Encoder(final File file) {this.target = file;}void encode(String text) {Files.write(this.target,text.replaceAll("[a-z]", "*"));} }工作正常,但是當您決定擴展它以同時寫入OutputStream時,會發生什么? 您將如何修改此類? 那會多么丑陋? 那是因為設計不是面向對象的。
這就是您將使用Cactoos以面向對象的方式進行相同設計的方式:
class Encoder {private final Output target;Encoder(final File file) {this(new FileAsOutput(file));}Encoder(final Output output) {this.target = output;}void encode(String text) {new LengthOfInput(new TeeInput(new BytesAsInput(new TextAsBytes(new StringAsText(text.replaceAll("[a-z]", "*")))),this.target)).asValue();} }如果我們希望OutputStream被接受,我們該怎么做? 我們只添加一個輔助構造函數:
class Encoder {Encoder(final OutputStream stream) {this(new OutputStreamAsOutput(stream));} }做完了 那是多么容易和優雅。
那是因為概念被完美地分離并且功能被封裝了。 在該過程示例中,該對象的行為位于方法外部(在encode()方法中encode() 。 該文件本身不知道如何寫,有些外部過程Files.write()知道。
相反,在面向對象的設計中, FileAsOutput知道如何編寫,而其他人FileAsOutput知道。 文件寫入功能被封裝,這使得可以用任何可能的方式裝飾對象,從而創建可重用和可替換的復合對象。
您現在看到OOP的美麗了嗎?
翻譯自: https://www.javacodegeeks.com/2017/06/object-oriented-declarative-inputoutput-cactoos.html
總結
以上是生活随笔為你收集整理的Cactoos中的面向对象的声明式输入/输出的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果电脑查使用记录查询(苹果电脑查历史记
- 下一篇: hadoop综述_Hadoop书籍赠品–