装饰器模式(Decorator Pattern)是一种非常重要的设计模式,它允许我们在不修改已有对象的情况下,动态地为其添加新的行为和功能。
这种模式广泛用于 Android 和 iOS 的开发中,特别是在我们想要扩展现有功能,而不破坏已有代码时。让我们从 Android 和 iOS 两个角度,详细了解一下如何使用装饰器模式。
什么是装饰器模式?🤔
装饰器模式的核心思想是将一个对象"包裹"起来,动态地给它添加新的行为,而不是直接修改或继承该对象的类。
换句话说,我们用"装饰器"来增强现有对象的功能,而无需改变它的源代码。
- 装饰器模式的好处:
- 遵循开闭原则:对扩展开放,对修改封闭。
- 动态地扩展对象的功能,而不修改已有代码。
- 灵活性高,可以组合多个装饰器来增强对象。
Android (Kotlin) 实现装饰器模式 🧩📱
在 Android 开发中,装饰器模式常用于扩展 WebViewClient
、RecyclerView.Adapter
等类,来为现有功能增加新功能。
假设场景:
我们有一个 WebViewClient
,已经实现了基本的功能。现在,我们想在页面加载完成时,打印出当前页面的 HTML 内容,而不影响原有功能。
实现步骤:
- 获取或创建原有的
WebViewClient
对象。 - 用一个新的
WebViewClient
包装原有对象,并在页面加载完成时,添加新的行为。 - 调用原有对象的方法,保留原有功能。
Kotlin 实现代码:
kotlin
// 假设我们已经有一个 WebViewClient 实例
val originalWebViewClient = webView.webViewClient ?: WebViewClient()
// 创建新的 WebViewClient,扩展其功能
webView.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
// 调用原有的 onPageFinished 方法,保留现有功能
originalWebViewClient.onPageFinished(view, url)
// 添加新的功能:打印页面 HTML
view?.evaluateJavascript(
"""
(function() {
return document.documentElement.outerHTML;
})();
""".trimIndent()
) { html ->
Log.d("WebViewHTML", "HTML content: $html")
}
}
}
解释:
originalWebViewClient
: 复用已有的WebViewClient
,避免功能丢失。onPageFinished
: 在页面加载完成后,我们调用原有的逻辑,并添加打印 HTML 的功能。
这种做法的好处:
- 你无需修改已有的
WebViewClient
实现,只需包裹并扩展它。 - 保证了原有功能的完整性,还能动态地添加新的行为。
iOS (Swift) 实现装饰器模式 🧩🍏
在 iOS 开发中,装饰器模式同样可以用来扩展对象的功能,常用于扩展 UIViewController
、UITableViewDelegate
等。Swift 的扩展性很强,我们可以利用协议、类扩展等手段来实现装饰器模式。
假设场景:
我们有一个 WKNavigationDelegate
,它负责处理网页的加载。现在,我们想在页面加载完成时,获取页面的 HTML 内容,并打印出来。
实现步骤:
- 创建一个原有的
WKNavigationDelegate
实例。 - 使用装饰器模式,通过扩展
WKWebView
,为页面加载完成后添加新的行为。 - 保留原有
WKNavigationDelegate
的行为,同时扩展新功能。
Swift 实现代码:
swift
// 原有的 WKNavigationDelegate 实现
class OriginalNavigationDelegate: NSObject, WKNavigationDelegate {
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 原有的页面加载完成处理
print("Original page finished loading.")
}
}
// 扩展 WKWebView,添加打印 HTML 功能
extension WKWebView {
func printHTMLContent() {
self.evaluateJavaScript("document.documentElement.outerHTML.toString()") { result, error in
if let html = result as? String {
print("HTML content: \(html)")
}
}
}
}
// 创建新的装饰器类,包裹原有的 WKNavigationDelegate
class NavigationDelegateDecorator: NSObject, WKNavigationDelegate {
private let wrapped: WKNavigationDelegate
init(wrapped: WKNavigationDelegate) {
self.wrapped = wrapped
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 调用原有的行为
wrapped.webView?(webView, didFinish: navigation)
// 添加新的功能:打印页面 HTML
webView.printHTMLContent()
}
}
// 使用装饰器模式
let originalDelegate = OriginalNavigationDelegate()
let decoratedDelegate = NavigationDelegateDecorator(wrapped: originalDelegate)
// 将装饰后的 delegate 设置给 WKWebView
webView.navigationDelegate = decoratedDelegate
解释:
OriginalNavigationDelegate
: 原有的委托实现。NavigationDelegateDecorator
: 这是装饰器类,扩展了原有的委托功能。printHTMLContent
: 扩展了WKWebView
,在页面加载完成时打印 HTML。
这种做法的好处:
- 你无需修改原有的
WKNavigationDelegate
逻辑。 - 新增的功能和原有功能完全解耦,代码清晰且易于维护。
总结 ✨
装饰器模式是一种强大的设计模式,能够让我们在不修改已有代码的情况下,为对象动态地添加新功能。在 Android 和 iOS 开发中,装饰器模式尤其适用于扩展那些无法直接修改的类或对象,比如 WebViewClient
、WKNavigationDelegate
等。
- Android (Kotlin) :通过复用现有的
WebViewClient
,并在其基础上添加新的行为,比如打印页面 HTML。 - iOS (Swift) :使用类扩展和委托装饰,动态为
WKNavigationDelegate
添加新功能,比如打印页面 HTML。
装饰器模式的优势在于其灵活性和可组合性。无论是 Android 还是 iOS,都可以利用这种模式,让代码更加模块化,维护更加容易。🎉
感谢阅读!