控制抽象

根據(jù)正交設(shè)計(jì)的基本原則,如果設(shè)計(jì)出現(xiàn)重復(fù)的控制邏輯,可抽象出穩(wěn)定的抽象;借助于Scala強(qiáng)大的可擴(kuò)展能力,可以將「小括號(hào)」神奇地轉(zhuǎn)換為「大括號(hào)」,讓用戶代碼感覺是一種新的控制結(jié)構(gòu)。

本文通過一個(gè)簡單的例子,通過若干迭代,遵循正交設(shè)計(jì)的基本原則,靈活地應(yīng)用重構(gòu),逐漸改進(jìn)設(shè)計(jì),以供參考。

需求1:搜索目錄下擴(kuò)展名為.scala的所有文件

快速實(shí)現(xiàn)

object FileMatchers {
  def ends(file: File, ext: String) = {
    for (file <- file.listFiles if file.getName.endsWith(ext))
      yield filelist
  }
}

需求2:搜索目錄下名字包含Test的所有文件

重復(fù)

object FileMatcher {
  def ends(file: File, ext: String) = {
    for (file <- file.listFiles if file.getName.endsWith(ext))
      yield file
  }
  
  def contains(file: File, query: String) = {
    for (file <- file.listFiles if file.getName.contains(query))
      yield file
  }
}

需求3:搜索目錄下名字正則匹配特定模式的所有文件

再現(xiàn)重復(fù)

object FileMatcher {
  def ends(file: File, ext: String) = {
    for (file <- file.listFiles if file.getName.endsWith(ext))
      yield file
  }
  
  def contains(file: File, query: String) = {
    for (file <- file.listFiles if file.getName.contains(query))
      yield file
  }
      
  def matches(file: File, regex: String) = {
    for (file <- file.listFiles if file.getName.matches(regex))
      yield file
  }
}

提取抽象

消除消除上述實(shí)現(xiàn)的重復(fù),最重要的是提取公共的關(guān)注點(diǎn): Matcher: (String, String) => Boolean。

object FileMatcher {
  private def list(file: File, query: String, 
    matcher: (String, String) => Boolean) = {
    for (file <- file.listFiles if matcher(file.getName, query))
      yield file
  }

  def ends(file: File, ext: String) =
    list(file, ext, (fileName, ext) => fileName.endsWith(ext))
    
  def contains(file: File, query: String) =
    list(file, query, (fileName, query) => fileName.contains(query))
          
  def matches(file: File, regex: String) =
    list(file, regex, (fileName, regex) => fileName.matches(regex))
}

類型推演

借助于Scala強(qiáng)大的類型推演能力,可以得到更為簡潔的函數(shù)字面值。

object FileMatcher {
  private def list(file: File, query: String, 
    matcher: (String, String) => Boolean) = {
    for (file <- file.listFiles if matcher(file.getName, query))
      yield file
  }

  def ends(file: File, ext: String) =
    list(file, ext, _.endsWith(_))
    
  def contains(file: File, query: String) =
    list(file, query, _.contains(_))
          
  def matches(file: File, regex: String) =
    list(file, regex, _.matches(_))
}

類型別名

list的參數(shù)由于類型修飾,顯得有點(diǎn)過長而影響閱讀;可以通過「類型別名」的機(jī)制縮短函數(shù)的類型修飾符,以便改善表達(dá)力。

object FileMatcher {
  private type Matcher = (String, String) => Boolean

  private def list(file: File, query: String, matcher: Matcher) = {
    for (file <- file.listFiles if matcher(file.getName, query))
      yield file
  }

  def ends(file: File, ext: String) =
    list(file, ext, _.endsWith(_))
    
  def contains(file: File, query: String) =
    list(file, query, _.contains(_))
          
  def matches(file: File, regex: String) =
    list(file, regex, _.matches(_))
}

簡化參數(shù)

簡化參數(shù)傳遞,消除不必要的冗余,是簡單設(shè)計(jì)基本原則之一。

object FileMatcher {
  private type Matcher = String => Boolean

  private def list(file: File, matcher: Matcher) = {
    for (file <- file.listFiles if matcher(file.getName))
      yield file
  }

  def ends(file: File, ext: String) =
    list(file, _.endsWith(ext))
    
  def contains(file: File, query: String) =
    list(file, _.contains(query))
          
  def matches(file: File, regex: String) =
    list(file, _.matches(regex))
}

替換for comprehension

可以通過定制「高階函數(shù)」替代語法較為復(fù)雜的「for comprehension」,以便改善表達(dá)力。

object FileMatcher {
  private type Matcher = String => Boolean

  private def list(file: File, matcher: Matcher) =
    file.listFiles.filter(f => matcher(f.getName))

  def ends(file: File, ext: String) =
    list(file, _.endsWith(ext))
    
  def contains(file: File, query: String) =
    list(file, _.contains(query))
          
  def matches(file: File, regex: String) =
    list(file, _.matches(regex))
}

柯里化

應(yīng)用「柯里化」,漂亮的「大括號(hào)」終于登上了舞臺(tái)。

object FileMatcher {
  private type Matcher = String => Boolean

  def list(file: File)(matcher: Matcher) =
    file.listFiles.filter(f => matcher(f.getName))

  def ends(file: File, ext: String) =
    list(file) { _.endsWith(ext) }

  def contains(file: File, query: String) =
    list(file) { _.contains(query) }

  def matches(file: File, regex: String) =
    list(file) { _.matches(regex) }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 戲路如流水,從始至終,點(diǎn)滴不漏。一路百折千回,本性未變,終歸大海。一步一戲,一轉(zhuǎn)身一變臉,撲朔迷離。真心自然流露,...
    劉光聰閱讀 2,075評(píng)論 3 13
  • 即使水墨丹青,何以繪出半妝佳人。 Scala是一門優(yōu)雅而又復(fù)雜的程序設(shè)計(jì)語言,初學(xué)者很容易陷入細(xì)節(jié)而迷失方向。這也...
    劉光聰閱讀 3,202評(píng)論 4 9
  • 讀《快學(xué)Scala 》一書的摘要 Scala 運(yùn)行于JVM之上,擁有海量類庫和工具,兼顧函數(shù)式編程和面向?qū)ο蟆?在...
    abel_cao閱讀 1,375評(píng)論 0 8
  • 桃花落,閑池閣,山盟雖在,錦書難托,莫,莫,莫! 「函數(shù)(Function)」是函數(shù)式編程的基本單元。本文將重點(diǎn)討...
    劉光聰閱讀 4,308評(píng)論 6 13
  • 《富爸爸窮爸爸》的作者羅伯特.清崎,他有2個(gè)“爸爸”,一個(gè)親生父親,是高學(xué)歷的教育官員,另外一個(gè)是他好朋友的父親,...
    沉睡中的獅子閱讀 299評(píng)論 0 0

友情鏈接更多精彩內(nèi)容