Android 策略设计模式的使用:使用设计模式,减少烂代码,让项目更好维护

news2024/11/6 21:40:36

目录

大家好呀~,我是前期后期,在网上冲浪的一名程序员,分享一些自己学到的知识,希望对大家有所帮助

在这里插入图片描述


前言:为什么要使用设计模式

在项目开发过程中,我们会对接很多种支付:国内(微信、支付宝),海外(日本的TakeMe、UnivaPay)等等,如果我们使用的是MVVM、或者MVP架构,那么这些逻辑都会在VM层或者P层。比如:

class QrCodeFragmentVM  {

    /**
     * 微信支付宝 获取二维码
     */
    fun twoPayCode() {}

    /**
     * takeMe Pay 获取二维码
     */
    fun takeMePay(){}

    /**
     * univa Pay 获取二维码
     */
    fun univaPay(){}


    /**
     * univa Pay 查询支付结果
     */
    fun univaPayStateQuery(){}

    /**
     * takeMe Pay 查询支付结果
     */
    fun takeMePayStateQuery(){}


}

可以看到,有很多的方法,如果后面再持续增加,那么就会很混乱,各种支付方式的方法都融合在一个类里面,久了以后,你甚至都不知道univa pay的请求方法有几个,可能有两个或者三个,会导致后面代码难以维护和新增。增加越多,越棘手。

所以接下来,我们介绍一种策略设计模式,来解决这个问题,为什么要使用设计模式呢,设计模式的作用,其实就是减少烂代码,让项目可以更好维护,不过也要视情况而使用。


一、策略和工厂设计模式来解决

1.1 定义一个接口:抽取共同项

我们来直接看代码,将支付的共同项进行一个抽取,每个策略都会有发起支付和查询交易结果的方法。

/**
 * 支付 接口 策略模式
 */
interface PaymentStrategy {

    /**
     * 发起支付
     * @param price 金额   -- 使用map,因为参数有可能很多~
     */
    suspend fun pay(params: Map<String, String>):Flow<String>


    /**
     * 查询交易结果
     */
    suspend fun queryPayState(params: Map<String, String>):Flow<String>

}

这里的参数使用Map,非常的重要,因为每种支付方式,他的参数是不一样的,如果你使用String,那么就得重载很多方法,很多参数,不利于复用。


1.2 创建一个类做默认实现

下面我们要创建一个类来做默认的实现,就像前面说的,有可能有些支付,他不只是两个方法,可能他还有上传交易结果的方法,如果直接实现接口,那么就得实现一个多余方法,所以我们这里就增加一个类做默认的实现。

/**
 * 支付 接口 策略模式 提供默认实现
 */
abstract class DefultPayMentStrategy : PaymentStrategy {

    override suspend fun pay(params: Map<String, String>):Flow<String> {
        return request {  }
    }

    override suspend fun queryPayState(params: Map<String, String>): Flow<String> {
        return request {  }
    }


1.3 具体的实现类:比如微信支付宝类、日本TakeMepay

接下来,就是我们的重头戏,将支付服装成一个类,各自提供自己的实现。


/**
 * 微信支付宝 类
 */
class WeChatAlipayPayMent @Inject constructor() : DefultPayMentStrategy() {
    private val TAG = "WeChatAlipayPayMent"

    /**
     * 发起支付
     */
    override suspend fun pay(params: Map<String, String>)= request<String> {
       // 请求微信支付宝的二维码。
    }

	....
}

/**
 * 日本支付 类
 */
class TakeMepayPayMent @Inject constructor() : DefultPayMentStrategy() {
    private val TAG = "TakeMepayPayMent "

    /**
     * 发起支付
     */
    override suspend fun pay(params: Map<String, String>)= request<String> {
       //请求日本支付的二维码
    }

	....
}

其实,到这里就已经发现,已经解决了我们的问题,各类的支付放到自己的类里面,这样方法就不会混乱,区分开来,这样就好维护很多。


1.4 创建支付策略工厂

由于我们需要在运行时决定使用哪个策略,我们可以创建一个工厂类来管理策略的创建。

@Singleton
class PaymentService @Inject constructor(
    private val weChatAlipayPayMent: WeChatAlipayPayMent,
     private val takeMepayPayMent: TakeMepayPayMent
) {
    fun getPaymentStrategy(type: String): PaymentStrategy {  
        return when (type) {  
            "weChatAlipayPayMent" -> weChatAlipayPayMent//微信支付
             "TakeMepayPayMent " -> takeMepayPayMent//日本支付
            else -> throw IllegalArgumentException("Unknown payment type: $type")
        }  
    }  
}

1.5 具体的使用

可以看到有了工厂以后,我们直接提供一个字符串就会生成对应的支付,也不需要我们创建对象了。

 @Inject
    lateinit var paymentService: PaymentService

    /**
     * 微信支付宝 获取二维码
     */
    fun twoPayCode() {
        viewModelScope.launch(Dispatchers.IO) {
            val paymentStrategy = paymentService.getPaymentStrategy("weChatAlipayPayMent")
        }
    }

二、 策略设计模式的一些概念

2.1 定义

策略设计模式是一种定义一系列算法的方法,它允许在运行时选择不同的实现。这些算法完成的是相同的工作,但实现方式不同。通过将算法封装成独立的策略类,策略设计模式使得算法的变化可以独立于使用算法的客户端。

2.2 组成部分

策略设计模式通常由以下几个部分组成:

  1. 抽象策略类:定义了一个算法家族,并声明了一个抽象的算法方法,可以被具体的策略类所替换。
  2. 具体策略类:实现了抽象策略类中定义的算法,每个具体策略类都封装了一个特定的算法实现。
  3. 环境类(上下文类):持有一个抽象策略类的引用,用于调用具体的策略类中实现的算法。环境类负责在运行时选择并调用合适的策略。

2.3 优点

  1. 算法独立性:策略模式将算法与客户端分离,使得算法可以独立变化,而不会影响到客户端的代码。
  2. 可扩展性:可以方便地增加或替换算法,从而满足不同的需求。
  3. 容易维护:策略模式将算法的实现封装在单独的类中,使得代码更加清晰、易于理解和维护。

2.4 缺点

  1. 增加系统复杂性:策略模式会增加系统中类的数量,从而增加系统的复杂性。

2.5 应用场景

  1. 当需要在不同情况下使用不同的算法时。
  2. 当一个类有多种行为或算法,并且这些行为或算法可以在运行时切换时。
  3. 当需要避免使用多重条件语句或大量的if-else语句时,以提高代码的可读性和可维护性。

好了,这篇文章就介绍到这里,我是前期后期,我们 下一篇文章 见·~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2229866.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp和vite项目配置多环境编译,增加测试环境变量配置--mode test

如果你的项目是使用vite和uniapp配置开发的&#xff0c;就可以在代码里面获取到这些变量&#xff0c;但是开发&#xff0c;测试和发布是不同的请求地址&#xff0c;所以需要配置。Vite 使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量&#xff1a; .env …

动态规划 - 编辑距离

115. 不同的子序列 困难 给你两个字符串 s 和 t &#xff0c;统计并返回在 s 的 子序列 中 t 出现的个数&#xff0c;结果需要对 10^9 7 取模。 算法思想&#xff1a;利用动态规划&#xff0c;分s[i - 1] 与 t[j - 1]相等&#xff0c;s[i - 1] 与 t[j - 1] 不相等两种情况具…

sudo apt install jupyter-notebook安装notebook失败E: Aborting install.

问题&#xff1a; sudo apt install jupyter-notebook安装notebook失败E: Aborting install. ~/jie/mywork/PointNetCFD$ sudo apt install jupyter-notebook --fix-missing Reading package lists... Done Building dependency tree Reading state information... Do…

第16课 核心函数(方法)

掌握常用的内置函数及其用法。 数学类函数&#xff1a;abs、divmod、max、min、pow、round、sum。 类型转换函数&#xff1a;bool、int、float、str、ord、chr、bin、hex、tuple、list、dict、set、enumerate、range、object。 序列操作函数&#xff1a;all、any、filter、m…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第2天,启动项目

24.11.01 下面讲一下如何通过USB连接手机然后启动app实现真机测试&#xff0c;还是有一些坑的。 调整电脑的驱动程序&#xff0c;完成USB的连接 在启动项目的第一步我就遇见了问题&#xff0c;那就是插入usb线以后没有检测到设备。想要完成连接需要2个步骤&#xff0c;第一步…

使用Mac如何才能提高OCR与翻译的效率

OCR与截图大家都不陌生&#xff0c;或许有的朋友对于这两项功能用到的不多&#xff0c;但是如果经常会用到的话&#xff0c;那你就该看看了 iOCR&#xff0c;快捷键唤出翻译窗口&#xff0c;不论是截图翻译、划词翻译、输入翻译、剪切板翻译&#xff0c;统统快捷键完成&#x…

Etsy又被封号了!这次我终于搞懂了原因...

你是否真的了解在Etsy开店有哪些红线不能踩&#xff1f;你是否真的知道Etsy被封号后如何解决&#xff1f;本文我将探讨Etsy账号被封的常见原因&#xff0c;以及卖家可以采取的应对策略&#xff0c;以期减轻对跨境业务的伤害程度&#xff0c;感兴趣的商家速速码住&#xff0c;不…

MySQL — 事务 (o゚▽゚)o

文本目录&#xff1a; ❄️一、什么是事务&#xff1a; ❄️二、ACID特性&#xff1a; ❄️三、使用事务&#xff1a; ▶1、查看支持事务的存储引擎&#xff1a; ▶2、语法&#xff1a; ▶3、开启并且回滚&#xff1a; ▶4、开启并且提交&#xff1a; ▶ 5、保存点&#xff…

DOS时代软件遗憾落幕,国产编程新势力接过火炬

在计算机发展史上&#xff0c;DOS时代是一个不可磨灭的篇章。那个时期&#xff0c;虽然操作系统的图形界面尚未普及&#xff0c;但一款款经典软件却为我们打开了通往数字世界的大门&#xff0c;让我们在那个相对简单却充满魅力的时代中&#xff0c;感受到科技的魅力与创新的力量…

Qt的信号槽机制学习一

一、Qt理论知识简记 &#xff08;一&#xff09;信号与槽[1] 信号与槽是Qt编程的基础&#xff0c;其使得处理界面上各个组件的交互操作变得比较直观和简单&#xff0c;GUI&#xff08;Graphical User Interface&#xff09;程序设计的主要工作就是对界面上各组件的信号进行相应…

P11232 [CSP-S 2024] 超速检测

P11232 [CSP-S 2024] 超速检测 难度&#xff1a;普及/提高。 考点&#xff1a;二分、贪心。 题意&#xff1a; 题意较长&#xff0c;没有题目大意&#xff0c;否则你也大意。 主干道长度为 L L L&#xff0c;有 n n n 辆车&#xff0c;看做左端点为 0 0 0&#xff0c;第 …

使用GetX实现GetPage中间件

前言 GetX 中间件&#xff08;Middleware&#xff09;是 GetX 框架中的一种机制&#xff0c;用于在页面导航时对用户进行权限控制、数据预加载、页面访问条件设置等。通过使用中间件&#xff0c;可以有效地控制用户的访问流程&#xff0c;并在适当条件下引导用户到所需页面。 这…

JAVA:常见 JSON 库的技术详解

1、简述 在现代应用开发中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;已成为数据交换的标准格式。Java 提供了多种方式将对象转换为 JSON 或从 JSON 转换为对象&#xff0c;常见的库包括 Jackson、Gson 和 org.json。本文将介绍几种常用的 JSON 处理…

视频怎么去水印?7个视频去水印在线工具大比拼,宝藏工具推荐!

您是否正在寻找一款好用的视频去水印在线工具&#xff0c;却总是难以找到合适的去水印软件&#xff1f;别担心&#xff0c;今天在本文中小编将和大家分享一些去水印的小助手。很多人都觉得视频或图片上的水印十分烦人。如果您有着同样的烦恼&#xff0c;那么使用去水印工具将是…

如何一键更换ppt模板?掌握这2个ppt技巧快速搞定!

每当要制作ppt&#xff0c;很多人会第一时间去搜刮各种ppt模板&#xff0c;有时我们找到了一份貌似符合需求的模板&#xff0c;等到了ppt制作环节&#xff0c;才发现离我们的预期相距甚远&#xff0c;做到一半的ppt如何换模板呢&#xff1f; 想要在中途更换ppt模板&#xff0c;…

0基础入门linux文件系统

目录 文件系统简介 1. 文件系统类型 2. 文件系统结构 3. 文件系统的主要功能 4. 文件系统的使用 5. 文件系统的维护 6. 注意事项 简单举例 机械硬盘 物理结构介绍​编辑 CHS寻址 逻辑结构介绍 LBA寻址法 文件系统与磁盘管理 Boot Block Data block inode block…

2024年meme币走势分析:最后两个月的市场趋势与机会 #交易所#dapp#KOL社区合作

2024年即将步入尾声&#xff0c;meme币市场经历了显著的波动。对于加密市场来说&#xff0c;年底的走势尤为关键&#xff0c;尤其是meme币这种受市场情绪影响较大的加密资产。本文将从市场环境、宏观经济因素、投资者情绪、技术分析等方面分析meme币在2024年最后两个月的潜在走…

Cpp多态机制的深入理解(20)

文章目录 前言一、多态的概念二、多态的定义与实现两个必要条件虚函数虚函数的重写重写的三个例外override 和 final重载、重写(覆盖)、重定义(隐藏) 三、抽象类概念接口继承和实现继承 四、多态的原理虚表和虚表指针虚函数调用过程动态绑定与静态绑定 五、那...那单继承甚至多…

.net core 接口,动态接收各类型请求的参数

[HttpPost] public async Task<IActionResult> testpost([FromForm] object info) { //Postman工具测试结果&#xff1a; //FromBody,Postman的body只有rawjson时才进的来 //参数为空时&#xff0c;Body(form-data、x-www-form-urlencoded)解析到的数据也有所…

高清解压视频素材从哪儿下载?推荐5个高清推文素材资源网站

做抖音小说推文&#xff0c;哪里找爆款素材&#xff1f;作为一名从业多年的视频剪辑师&#xff0c;今天就来给大家揭秘可以下载爆款推文视频素材的网站&#xff0c;如果你也在苦苦找寻找&#xff0c;赶紧进来看看吧&#xff5e; 1. 稻虎网 首先是稻虎网&#xff0c;作为国内顶…