目录
大家好呀~,我是前期后期,在网上冲浪的一名程序员,分享一些自己学到的知识,希望对大家有所帮助
前言:为什么要使用设计模式
在项目开发过程中,我们会对接很多种支付:国内(微信、支付宝),海外(日本的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 组成部分
策略设计模式通常由以下几个部分组成:
- 抽象策略类:定义了一个算法家族,并声明了一个抽象的算法方法,可以被具体的策略类所替换。
- 具体策略类:实现了抽象策略类中定义的算法,每个具体策略类都封装了一个特定的算法实现。
- 环境类(上下文类):持有一个抽象策略类的引用,用于调用具体的策略类中实现的算法。环境类负责在运行时选择并调用合适的策略。
2.3 优点
- 算法独立性:策略模式将算法与客户端分离,使得算法可以独立变化,而不会影响到客户端的代码。
- 可扩展性:可以方便地增加或替换算法,从而满足不同的需求。
- 容易维护:策略模式将算法的实现封装在单独的类中,使得代码更加清晰、易于理解和维护。
2.4 缺点
- 增加系统复杂性:策略模式会增加系统中类的数量,从而增加系统的复杂性。
2.5 应用场景
- 当需要在不同情况下使用不同的算法时。
- 当一个类有多种行为或算法,并且这些行为或算法可以在运行时切换时。
- 当需要避免使用多重条件语句或大量的if-else语句时,以提高代码的可读性和可维护性。
好了,这篇文章就介绍到这里,我是前期后期,我们 下一篇文章 见·~