土城战役_避免使用FOR –反假战役
土城戰役
您是否想知道FOR如何影響您的代碼? 他們如何限制您的設計,更重要的是如何將您的代碼轉換為無人為含義的多行代碼?
在這篇文章中,我們將看到如何將for的簡單示例(由Francesco Cirillio提供- 反if活動)轉換為更具可讀性和精心設計的示例。
因此,讓我們從使用FOR的原始代碼開始:
請參見printSlips方法。 如此簡單的方法,只有10條線計數白線,但卻違反了最重要的規則之一,該方法在其內部混合了不同級別的抽象而不只是做一件事。
正如羅伯特·C·馬丁(Robert C. Martin)在他的著作《函數應該做一件事情》中指出的那樣。 他們應該做得很好。 他們應該只做[…]。 如果一個函數僅執行比該函數的指定名稱低一級的步驟,則該函數正在做一件事[…]。 。
因此,使用給定的方法外觀定義,讓我們回顧一下以前的方法,看看有多少事情在做
printSlips方法? 具體四個 。
該方法是循環,選擇資源,訪問內容以及訪問媒體。 看到它們每個都屬于不同的抽象級別,打印到控制臺應該以不同的級別檢查資源是否尚未到期。
讓我們看看Francesco提出的解決方案。
首先要做的是將主要功能分成三個類和兩個接口,一個用于迭代資源,另一個用于選擇尚未過期的資源,另一個用于打印資源。 通過這種方法,我們正在創建一個旨在擴展的解決方案,并且還提高了可讀性。
現在是時候編寫代碼了:
如果資源滿足已實現條件,則將使用謂詞接口來實現。
public interface Predicate {boolean is(Resource each);}例如,在我們的例子中,接口的實現如下所示:
public class InForcePredicate implements Predicate {public boolean is(Resource each) {return each.lastContract().deadline().after(new Date());}}我們將條件轉移到InForcePredicate類。 請注意,如果我們要創建一個檢查合同是否過期的類,我們將創建一個實現Predicate的新類,其內容類似于return each.lastContract()。deadline()。before(new Date()) ;
下一個接口是Block接口,它將實現對媒體的訪問。 在這種情況下,要進行控制臺:
public interface Block {void evaluate(Resource resource);}及其實現:
public class PrintSlip implements Block {public void evaluate(Resource resource) {System.out.println(resource.name()); System.out.println(resource.salary());}}再次注意,更改信息的發送位置(控制臺,文件,網絡等)僅是實現Block接口的問題。
最后一類是包含資源迭代器的類,還提供了調用先前創建的每個接口的方法:
public class ResourceOrderedCollection {private Collection<Resource> resources = new ArrayList<Resource>();public ResourceOrderedCollection() {super();}public ResourceOrderedCollection(Collection<Resource> resources) {this.resources = resources;}public void add(Resource resource) {this.resources.add(resource);}public void forEachDo(Block block) {Iterator<Resource> iterator = resources.iterator();while(iterator.hasNext()) {block.evaluate(iterator.next());}}public ResourceOrderedCollection select(Predicate predicate) {ResourceOrderedCollection resourceOrderedCollection = new ResourceOrderedCollection();Iterator<Resource> iterator = resources.iterator();while(iterator.hasNext()) {Resource resource = iterator.next();if(predicate.is(resource)) {resourceOrderedCollection.add(resource);}}return resourceOrderedCollection;}}請參閱接下來的三個要點:
- 第一個是構造函數接收資源列表。
- 第二個是select方法接收一個謂詞,該謂詞將執行到迭代器中,以知道是否可以選擇打印資源。 最后,返回帶有資源且沒有過期合同的ResourceOrderedCollection的新實例。
- 第三個forEachDo方法接收一個Block接口,該接口由資源列表的每個元素調用。
最后使用以前開發的類修改了Department類:
public class Department {private List<Resource> resources = new ArrayList<Resource>();public void addResource(Resource resource) {this.resources.add(resource);}public void printSlips() {new ResourceOrderedCollection(this.resources).select(new InForcePredicate()).forEachDo(new PrintSlip());}}注意,現在printSlips方法包含具有相同抽象級別的單個可讀行。
請注意,類名和接口名取自Francesco的示例,但是如果我也要這樣做,則將選擇更多的代表性名稱。 Cirillo的方法不錯,但需要考慮一些小方面。 例如,它具有“ 垂直問題 ”: Predicate接口中的InForcePredicate實例使用五行源代碼來封裝單個語句。
我們探索了問題的兩種可能解決方案,這是Cirillio提出的最后一種解決方案。 對于此問題,還有許多其他可能且正確的解決方案,例如,使用“ 模板方法模式” ,或混合使用Lambdaj和(或不使用) 閉包( Lambdaj語法可能會有些混亂)。 它們都有優點和缺點,但是它們都使您的代碼更具可讀性,而且更重要,所有功能都只能做一件事,它們只能做得很好。
作為本文的最后注解, JDK 8將提供對本機關閉的支持,還將提供Lambdaj現在提供的許多功能。 同時, JDK 8不穩定(計劃于2013年中半決賽)或您的舊代碼(從JDK 8的角度來看) 不穩定 , Lambdaj確實是一個很好的旅行者。
我們不斷學習。
參考: 避免FOR –來自我們的JCG合作伙伴 Alex Soto的“ 反若戰役”,來自One Jar to Rule All All博客。
翻譯自: https://www.javacodegeeks.com/2012/11/avoiding-fors-anti-if-campaign.html
土城戰役
總結
以上是生活随笔為你收集整理的土城战役_避免使用FOR –反假战役的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 更新后谷歌浏览器皮肤背景自动变成黑色模式
- 下一篇: 小规模流处理kata。 第2部分:RxJ