前言
外观模式(Facade Pattern
)是一种结构型设计模式,旨在为子系统中的一组接口提供一个统一的接口。外观模式定义了一个高层接口,使得这一子系统更加容易使用。它将复杂的子系统封装在一个简单的接口后面,从而降低了客户端的复杂性。
实现
我们以银行APP
业务举个例子,其中包含多个子系统,如用户验证、账户管理、交易处理和通知服务,我们用外观模式来简化子系统的操作,让用户能够轻松的使用银行系统功能而不用考虑底层复杂的实现细节。首先要定义以下子系统:
1、用户验证(UserAuthentication
)
负责验证用户身份的子系统
kotlin
/**
* 用户认证
*/
class UserAuthentication {
fun validateUser(userId: String, password: String): Boolean {
println("System Validating user...")
return userId == "Ho" && password == "123456"
}
}
2、账户管理 (AccountManager
)*
负责账户查询和更新的子系统
kotlin
class AccountManager {
fun getBalance(accountId: String): Double {
println("Fetching balance for account: $accountId")
return 1000.0
}
fun updateBalance(accountId: String, amount: Double) {
println("Updating balance for account: $accountId by amount: $amount")
}
}
3、交易处理 (TransactionManager
)
负责执行交易的子系统
kotlin
/**
* 交易处理
*/
class TransactionManager {
fun makeTransaction(fromAccount: String, toAccount: String, amount: Double) {
println("Processing transaction from $fromAccount to $toAccount of amount $amount")
}
}
4、通知服务 (NotificationService
)
负责通知用户交易状态的子系统
kotlin
/**
* 通知服务
*/
class NotificationService {
fun sendNotification(userId: String, message: String) {
println("Sending notification to $userId: $message")
}
}
5、外观类
定义外观类BankingFacade
,将子系统对象作为外观类的构成参数传入,模拟对客户提供方法,比如转账transferMoney
,验证用户、校验余额、处理交易、以及通知都在内部就行
kotlin
class BankingFacade(
private val auth: UserAuthentication,
private val accountManager: AccountManager,
private val transactionManager: TransactionManager,
private val notificationService: NotificationService
) {
fun transferMoney(userId: String, password: String, fromAccount: String, toAccount: String, amount: Double) {
// 验证用户
if (!auth.validateUser(userId, password)) {
println("Authentication failed for user: $userId")
return
}
// 检查账户余额
val balance = accountManager.getBalance(fromAccount)
if (balance < amount) {
println("Insufficient funds in account: $fromAccount")
notificationService.sendNotification(userId, "Transaction failed due to insufficient funds.")
return
}
// 处理交易
transactionManager.makeTransaction(fromAccount, toAccount, amount)
accountManager.updateBalance(fromAccount, -amount)
accountManager.updateBalance(toAccount, amount)
// 发送通知
notificationService.sendNotification(userId, "Transaction of $amount from $fromAccount to $toAccount completed successfully.")
}
}
客户端使用外观类进行业务操作。
kotlin
// 创建子系统对象
val auth = UserAuthentication()
val accountManager = AccountManager()
val transactionManager = TransactionManager()
val notificationService = NotificationService()
// 创建外观对象
val bankingFacade = BankingFacade(auth, accountManager, transactionManager, notificationService)
// 执行转账操作
bankingFacade.transferMoney("Ho", "123456", "****6787", "****6291", 100.0)
应用
在Android
中,外观模式广泛用于简化API
的使用。比如以下
1、媒体播放MediaPlayer
MediaPlayer是一个非常典型的外观模式应用示例。它封装了音频和视频播放的复杂操作,提供了一个简单的接口供开发者使用。
子系统:音频解码、视频解码、缓冲处理、数据流处理等。
外观接口:MediaPlayer
类提供了一系列简单的接口,如start()
、pause()
、stop()
等,让开发者无需关心底层复杂的实现。
kotlin
val mediaPlayer = MediaPlayer().apply {
setDataSource("audio_file.mp3")
prepare()
start()
}
2、摄像头CameraX
CameraX
库封装了对摄像头的操作,提供了简单且一致的API
来处理图像捕获、预览和图像分析。
子系统:相机设备的选择、会话管理、图像捕获、焦点和曝光控制等。
外观接口:CameraX
提供了一个简化的API
,使得摄像头的使用更加直观和易于管理。
kotlin
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build().also {
it.setSurfaceProvider(previewView.surfaceProvider)
}
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
cameraProvider.bindToLifecycle(this, cameraSelector, preview)
}, ContextCompat.getMainExecutor(this))
3、连接管理类ConnectivityManager
ConnectivityManager
提供了一个接口来监视和管理设备的网络连接。它封装了不同网络类型(如Wi-Fi
、移动数据、蓝牙等)的连接管理,并提供了统一的接口。
子系统:不同网络类型的连接管理、状态监控、网络切换等。
外观接口:ConnectivityManager
提供了一个简化的接口来检测网络状态和进行网络操作。
kotlin
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
if (networkInfo?.isConnected == true) {
// 已连接到网络
}
总结
外观模式通过提供一个简化的接口,将复杂的子系统封装起来,降低了客户端与子系统之间的耦合性,并提高了系统的模块化和灵活性。然而,使用外观模式时,需要权衡隐藏细节和提供灵活性之间的平衡,避免引入不必要的复杂性。