重修设计模式-结构型-门面模式

news/2024/9/19 14:50:24 标签: android

重修设计模式-结构型-门面模式

门面模式为子系统提供一组统一的接口,定义一组高层接口让子系统更易用

门面模式(Facade Pattern),也称作外观模式,主要用于为复杂的子系统提供一个统一的、更简洁的接口,使得子系统更加容易使用,并减少系统的相互依赖,提高系统的灵活性和可维护性。

开发中接口粒度的设计是一个难题,如果接口粒度过细,每个功能都独立成一个接口,虽然符合单一职责原则,复用性会更高,但外部在调用时,需要和多个接口打交道,易用性会非常差;如果接口粒度过大,一个接口做了 n 个事,易用性在某些场合会好一些,但复用性会变差。

门面模式就是抽象出一个更通用的接口层,来平衡接口通用性和易用性之间的矛盾。它的实现和原理非常简单,应用也非常广泛,在日常的编码中,很可能不经意间就用到了门面模式。

举个例子,在开发过程中会封装各种各样的工具和辅助类,比如 Android 中的网络模块,可以封装一个 HttpUtil 来请求网络,调用处只需知道调用它能实现网络请求即可,无需关注其内部细节:

/**
 * 网络请求封装
 */
object HttpUtil {
    private val okHttpClient = OkHttpClient.Builder().build()

    fun getRequest(baseUrl: String, success: (String?) -> Unit, failure:(String?) -> Unit) {
        val request = Request.Builder().url(baseUrl).get().build()
        okHttpClient.newCall(request).enqueue(object: Callback {
            override fun onFailure(call: Call, e: IOException) {
                failure.invoke(e.message)
            }

            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
                    success.invoke(response.body()?.string())
                } else {
                    failure.invoke(response.message())
                }
            }
        })
    }
}

//调用处:
fun main() {
    HttpUtil.getRequest("https://www.baidu.com", success = {
        println("请求成功:${it}")
    }, failure = {
        println("请求失败:${it}")
    })
}

调用处只跟门面类 HttpUtil 打交道,无需关注具体网络请求细节,如果后续需要将网络请求实现从 Okhttp 切换到 Volley,调用处代码也无需更改,耦合性非常低。

门面模式适用场景:

  1. 子系统复杂度高:当子系统包含大量相互依赖的类,外部调用者难以理解和使用时,可以使用门面模式来简化接口。
  2. 需要隐藏子系统细节:当需要隐藏子系统的内部实现细节,只提供一个精简的接口供客户端使用时,门面模式是一个很好的选择。
  3. 提高子系统独立性:通过门面模式,客户端不直接与子系统交互,而是通过门面角色来进行交互,这有助于提高子系统的独立性。
  4. 隔离风险:需要隔离客户端与子系统的直接交互,预防低水平人员带来的风险扩散时,可以使用门面模式。

以下是我在Android开发中发现的一些具体应用场景:

  1. 工具和辅助类

    Android开发中,开发者经常会编写各种工具类和辅助类来简化开发流程。这些工具类往往也采用了门面模式的设计,它们封装了复杂的逻辑,对外提供简洁的接口。例如,一个网络请求的工具类,它可能封装了HTTP请求、响应解析等复杂的操作,对外只提供一个发送请求并获取结果的简单接口。

  2. Context类

    在 Android 开发中,Context是非常重要的上下文类型,它封装了很多重要的操作,如启动活动(startActivity())、发送广播(sendBroadcast())等。Context是一个抽象类,它定义了抽象接口,而真正的实现在ContextImpl类中。这种设计就类似于门面模式,Context作为门面类,为开发者提供了一个统一的接口来访问系统的各种功能,而不需要直接与底层的ContextImpl或其他子系统打交道。

  3. 组件化开发

    在Android的组件化开发中,门面模式也有重要的应用。组件化开发要求将应用拆分成多个独立的模块,每个模块都负责特定的功能。为了降低模块之间的耦合度,可以在模块之间引入门面类,通过门面类来定义模块之间的交互接口,使得模块之间的调用更加清晰和简洁。

门面模式优缺点:

  • 优点:
    • 简化接口:通过提供一个统一的接口,简化了客户端与子系统的交互。
    • 降低耦合度:门面类作为中介,隐藏了子系统的具体实现细节,减少了客户端与子系统之间的直接依赖。
    • 提高灵活性:子系统内部的变化不会影响到门面类,只要门面类的接口不变,客户端代码就无需修改。
  • 缺点
    • 可能引入额外的间接层:如果滥用门面模式,可能导致系统增加不必要的抽象层次,影响性能和理解。
    • 对新增子系统功能的支持不够灵活:若子系统有新功能加入,可能需要修改门面类以适应新的接口需求。

门面模式和适配器模式有一些相似之处,但应用场景是不同的:适配器是做接口转换,解决原接口和目标接口兼容性问题;门面模式是做接口整合,解决多接口的复杂调用的问题。

总结

门面模式是一种非常实用的设计模式,它通过提供一个统一的接口来简化复杂子系统的使用,降低了客户端与子系统的耦合度,提高了系统的灵活性和可维护性。


http://www.niftyadmin.cn/n/5665733.html

相关文章

C++学习笔记----7、使用类与对象获得高性能(二)---- 理解对象生命周期(4)

7、拷贝构造函数 在C中有一种叫做拷贝构造函数的特殊的构造函数,它允许生成另一个对象的拷贝的对象。下面是在SpreadsheetCell类中的拷贝构造函数的声明: export class SpreadsheetCell { public:SpreadsheetCell(const SpreadsheetCell& src);// R…

【Java】多态性【主线学习笔记】

文章目录 前言多态性1、编译时多态性(静态多态性):2、运行时多态性(动态多态性)3、多态性的实用性4、多态性的优点与弊端 下一篇点击跳转《【Java】多态性-向下转型【主线学习笔记】》 前言 Java是一门功能强大且广泛应…

功能测试干了三年,快要废了。。。

8年前刚进入到IT行业,到现在学习软件测试的人越来越多,所以在这我想结合自己的一些看法给大家提一些建议。 最近聊到软件测试的行业内卷,越来越多的转行和大学生进入测试行业,导致软件测试已经饱和了,想要获得更好的待…

JAVA与Python谁更适合后端?

Java和Python各有优势,选择哪种语言应根据项目的具体需求和团队的实际情况来决定。 小型团队或原型开发:如果项目规模小、需求变动频繁,或者需要快速开发产品原型,建议使用Python。大型项目或企业级应用:如果项目规模…

【毕设】基于Java的超市管理系统

基于Java的超市管理系统是一个用于管理超市日常运营的软件解决方案,它可以包括库存管理、销售管理、客户管理等多个模块。以下是一个简化的系统设计方案,以及一些关键组件和技术选型的建议。 系统架构 前端: HTML/CSS/JavaScript&#xf…

状态估计算法

目录 前言一、贝叶斯滤波二、卡尔曼滤波2.1 KF简介2.2 基本线性模型2.3 KF公式推导2.3.1 预测值2.3.2 先验误差协方差矩阵2.3.3 卡尔曼增益2.3.4 最优估计值2.3.5 后验误差协方差矩阵 2.4 KF算法使用2.5 MATLAB验证2.5 Python验证 三、扩展卡尔曼滤波3.1 EKF原理3.2 MATLAB实现…

(java+Seleniums3)自动化测试实战2

1.环境问题点 此时,可以成功打开浏览器 此时,selenium可以控制浏览器 get--就是访问的意思 将驱动复制在当前项目之下 复制驱动的路径 2.基本元素定位 使用id来定位: 使用Name来定位: 成功: 使用id是唯一的&#xff0c…

python画图|3D bar进阶探索

前述学习过程只能怪,已经探究了3D直方图的基础教程,详见下述链接: python画图|3D直方图基础教程-CSDN博客 实际上,基础文章直接进入了堆叠教程,相对来说基础的程度不够,因此有必要再次探索。 【1】官网教…