哪些語言能更優雅地實現裝飾器模式? - frankel
在這篇文章中,我想描述如何向已經存在程式碼中新增新行為,所有主流語言都提供這樣的功能, Java 是唯一在這方面沒有提供任何內容的語言。解釋型語言允許擴充套件外部 API,而編譯型語言則不允許——Kotlin 是個例外。
JavaScript
可以輕鬆地將屬性(狀態或行為)新增到原來的物件中:
Object.defineProperty(String.prototype, "toTitleCase", { value: function toTitleCase() { return this.replace(/\w\S*/g, function(word) { return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase(); }); } }); console.debug("OncE upOn a tImE in thE WEst".toTitleCase()); |
Ruby
在 Ruby 生態系統中,向現有類新增方法或屬性是非常標準的。我發現了兩種向 Ruby 中現有型別新增方法的機制:
- 使用class_eval:在 mod 的上下文中評估字串或塊,除了在給定塊時,常量/類變數查詢不受影響。這可用於向類新增方法
- 只需在現有類上實現該方法。
這是第二種方法的程式碼:
class String def to_camel_case() return self.gsub(/\w\S*/) {|word| word.capitalize()} end end puts "OncE upOn a tImE in thE WEst".to_camel_case() |
Python
Python 允許您向現有型別新增函式 - 有限制。讓我們嘗試使用str內建型別:
import re def to_title_case(string): return re.sub( r'\w\S*', lambda word: word.group(0).capitalize(), string) setattr(str, 'to_title_case', to_title_case) print("OncE upOn a tImE in thE WEst".to_title_case()) |
不幸的是,上面的程式碼在執行過程中失敗了:因為str是內建型別,我們不能動態新增行為。我們可以更新程式碼來應對這個限制:
import re def to_title_case(string): return re.sub( r'\w\S*', lambda word: word.group(0).capitalize(), string) class String(str): pass setattr(String, 'to_title_case', to_title_case) print(String("OncE upOn a tImE in thE WEst").to_title_case()) |
現在可以擴充套件了String,因為它是我們建立的一個類。當然,它違背了最初的目的:我們必須首先擴充套件str。因此,它適用於第三方庫。
使用解釋型語言,向型別新增行為相當容易。然而,Python 已經達到了極限,因為內建型別是用 C 實現的。
Java
Java 是一種在 JVM 上執行的靜態和強型別編譯語言。它的靜態特性使得無法向型別新增行為。
解決方法是使用static方法。如果您已經成為 Java 開發人員很長時間了,我相信您可能在職業生涯的早期就見過自定義StringUtils和DateUtils類。這些類看起來像這樣:
public class StringUtils { public static String toCamelCase(String string) { // The implementation is not relevant } // Other string transformations here } |
我希望到現在為止,使用 Apache Commons 和 Guava 已經取代了所有這些類:
System.out.println(WordUtils.capitalize("OncE upOn a tImE in thE WEst")); |
在這兩種情況下,靜態方法的使用都會阻止流暢的 API 使用,從而損害開發人員的體驗。但是其他 JVM 語言確實提供了令人興奮的替代方案。
Scala
與 Java 一樣,Scala 是一種在 JVM 上執行的編譯型、靜態和強型別語言。它最初的設計目的是在物件導向程式設計和函數語言程式設計之間架起橋樑。Scala 提供了許多強大的功能。其中,隱式類允許向現有類新增行為和狀態。以下是如何將toCamelCase()函式新增到String:
import Utils.StringExtensions object Utils { implicit class StringExtensions(thiz: String) { def toCamelCase() = "\\w\\S*".r.replaceAllIn( thiz, { it => it.group(0).toLowerCase().capitalize } ) } } println("OncE upOn a tImE in thE WEst".toCamelCase()) |
Scala 3使用更合適的語法保持相同的功能:implicit
extension(thiz: String) def toCamelCase() = "\\w\\S*".r.replaceAllIn( thiz, { it => it.group(0).toLowerCase().capitalize } ) |
請注意,編譯後的位元組碼在這兩種情況下都與 Java 的靜態方法方法有些相似。然而,API 的使用是流暢的,因為您可以一個接一個地連結方法呼叫。
kotlin
與 Java 和 Scala 一樣,Kotlin 是一種在 JVM 上執行的編譯型、靜態和強型別語言。其他幾種語言,包括 Scala,啟發了它的設計。
我的觀點是 Scala 比 Kotlin 更強大,但權衡是額外的認知負擔。相反,Kotlin 有一種輕量級的方法,更實用。這是Kotlin 版本:
fun String.toCamelCase() = "\\w\\S*" .toRegex() .replace(this) { it.groups[0] ?.value ?.lowercase() ?.replaceFirstChar { char -> char.titlecase(Locale.getDefault()) } ?: this } println("OncE upOn a tImE in thE WEst".toCamelCase()) |
Rust
最後但並非最不重要的在我們的列表中,Rust 是一種編譯語言,靜態和強型別。它最初旨在生成本地二進位制檔案。然而,通過相關配置,它還允許生成Wasm。
有趣的是,雖然是靜態型別,但 Rust 還允許擴充套件第三方 API,如下面的程式碼所示:
trait StringExt { fn to_camel_case(&self) -> String; } impl StringExt for str { fn to_camel_case(&self) -> String { let re = Regex::new("\\w\\S*").unwrap(); re.captures_iter(self) .map(|capture| { let word = capture.get(0).unwrap().as_str(); let first = &word[0..1].to_uppercase(); let rest = &word[1..].to_lowercase(); first.to_owned() + rest }) .collect::<Vec<String>>() .join(" ") } } println!("{}", "OncE upOn a tImE in thE WEst".to_camel_case()); |
Trait 實現有一個限制:我們的程式碼必須至少宣告 trait 或結構之一。您不能為現有結構實現現有特徵。
相關文章
- 更優雅地實現策略模式模式
- 【裝飾器設計模式詳解】C/Java/JS/Go/Python/TS不同語言實現設計模式JavaJSGoPython
- 帶引數的 Python 裝飾器讓你的程式碼更優雅Python
- 如何用Java語言優雅地匯出Word文件Java
- 封裝React Hook函式useState實現更優雅的setValue封裝ReactHook函式
- 如何優雅地實現多資料庫的發件箱模式資料庫模式
- 如何更優雅地切換 Git 分支Git
- 如何優雅地實現分頁查詢
- 裝飾器模式(Decorator)模式
- Python裝飾器模式Python模式
- 【Android】在Kotlin中更優雅地使用LiveDataAndroidKotlinLiveData
- 設計模式----裝飾器模式設計模式
- 設計模式-裝飾器模式設計模式
- [設計模式] 裝飾器模式設計模式
- 用proxy實現一個更優雅的vueVue
- Python 使用 backoff 更優雅的實現輪詢Python
- 如何優雅地實現瀏覽器相容與CSS規則回退瀏覽器CSS
- 使用lambda實現裝飾者模式 - Voxxed模式
- 設計模式:如何優雅地使用工廠模式設計模式
- 教你更優雅地寫 API 之「列舉使用」API
- 設計模式學習-使用go實現裝飾模式設計模式Go
- Python設計模式-裝飾器模式Python設計模式
- 設計模式之-裝飾器模式設計模式
- 設計模式(八)裝飾器模式設計模式
- java設計模式--裝飾器模式Java設計模式
- 設計模式(六):裝飾器模式設計模式
- 設計模式之【裝飾器模式】設計模式
- 設計模式:如何優雅地使用責任鏈模式設計模式
- Java用策略模式優雅地匯出ExcelJava模式Excel
- Spring Boot中如何優雅地實現非同步呼叫?Spring Boot非同步
- 教你更優雅地寫 API 之「靈活地任務排程」API
- spring boot 整合 Pebble,更優雅地輸出變數Spring Boot變數
- 教你更優雅地寫 API 之「記錄日誌」API
- python裝飾器有哪些作用Python
- PHP設計模式- Decorator 裝飾器模式PHP設計模式
- Go 設計模式之裝飾器模式Go設計模式
- Java 設計模式(五)《裝飾器模式》Java設計模式
- java設計模式之裝飾器模式Java設計模式