1. 概述
在本教程中,我们将探讨 Kotlin 中的策略设计模式,并通过一个实际案例理解它解决的问题。
策略模式(Strategy Pattern)是一种行为型设计模式,它允许我们为同一问题定义多个解决方案,并在运行时动态切换这些方案。这是实际项目中使用最广泛的设计模式之一,尤其适用于需要根据不同条件动态改变行为的场景。
2. 代码示例
我们以一个简单的书店系统为例。书店根据用户的会员类型提供不同的折扣,比如普通会员享受10%折扣,高级会员享受20%折扣。当用户购买书籍时,系统需要根据其会员类型计算折扣金额。
我们先来看不使用策略模式的实现方式。
2.1. Book
类
首先定义一个表示书籍的类:
data class Book(val title: String, val price: Double)
为了简化,我们只保留两个属性:title
和 price
。
2.2. Customer
类
接着定义一个表示用户的类:
data class Customer(val name: String, val membershipType: MembershipType)
这个类有两个属性:name
和 membershipType
,其中 membershipType
是一个枚举类型。
2.3. MembershipType
枚举
定义会员类型的枚举如下:
enum class MembershipType {
REGULAR, PREMIUM
}
包含两个类型:REGULAR
(普通)和 PREMIUM
(高级)。
2.4. DiscountCalculator
– 未使用策略模式
接下来是折扣计算器类:
class DiscountCalculator {
fun calculateDiscount(book: Book, customer: Customer): Double {
return if (customer.membershipType == MembershipType.REGULAR) {
book.price * 0.1
} else {
book.price * 0.2
}
}
}
当前只有两种会员类型时,这种方式看似可行。但随着会员类型增多或折扣逻辑变复杂,这种 if-else
的方式将变得难以维护和扩展,代码可读性和扩展性都会大打折扣。
3. 使用策略模式
接下来我们使用策略模式来重构上面的代码,提升其可维护性和扩展性。
3.1. 策略接口
首先定义一个折扣策略接口:
interface DiscountStrategy {
fun calculateDiscount(book: Book): Double
}
该接口只有一个方法 calculateDiscount()
,用于根据书籍计算折扣金额。
3.2. 普通用户策略类
实现普通用户的折扣策略:
class RegularCustomerDiscountStrategy : DiscountStrategy {
override fun calculateDiscount(book: Book): Double {
return book.price * 0.1
}
}
3.3. 高级用户策略类
实现高级用户的折扣策略:
class PremiumCustomerDiscountStrategy : DiscountStrategy {
override fun calculateDiscount(book: Book): Double {
return book.price * 0.2
}
}
3.4. 改造 DiscountCalculator
支持策略
现在我们更新 DiscountCalculator
类,让它使用策略接口进行计算:
class DiscountCalculator(private val discountStrategy: DiscountStrategy) {
fun calculateDiscount(book: Book): Double {
return discountStrategy.calculateDiscount(book)
}
}
✅ 这样一来,DiscountCalculator
不再关心具体折扣逻辑,只负责调用策略。新增会员类型时,只需新增策略类,无需修改 DiscountCalculator
,符合开闭原则。
4. 测试
现在我们编写测试代码来验证不同策略是否正常工作。
4.1. 构造 DiscountCalculator
的方法
我们根据用户类型动态选择策略:
class DiscountCalculatorTest {
private fun createDiscountCalculator(customer: Customer): DiscountCalculator {
val discountStrategy = when (customer.membershipType) {
MembershipType.REGULAR -> RegularCustomerDiscountStrategy()
MembershipType.PREMIUM -> PremiumCustomerDiscountStrategy()
}
return DiscountCalculator(discountStrategy)
}
}
4.2. 编写测试用例
分别测试普通用户和高级用户的折扣计算:
@Test
fun `calculate discount for regular customer`() {
val book = Book("Effective Java", 100.0)
val customer = Customer("John Doe", MembershipType.REGULAR)
val discountCalculator = createDiscountCalculator(customer)
val discount = discountCalculator.calculateDiscount(book)
assertEquals(10.0, discount)
}
@Test
fun `calculate discount for premium customer`() {
val book = Book("Effective Java", 100.0)
val customer = Customer("John Doe", MembershipType.PREMIUM)
val discountCalculator = createDiscountCalculator(customer)
val discount = discountCalculator.calculateDiscount(book)
assertEquals(20.0, discount)
}
✅ 这些测试验证了我们的策略模式是否按预期工作。
5. 总结
通过本篇文章,我们了解了策略设计模式的基本概念,并通过 Kotlin 实现了一个实际案例。策略模式非常适合需要根据运行时条件动态切换行为的场景,比如:
- 不同支付方式(支付宝、微信、银联)
- 不同物流策略
- 不同用户等级的优惠策略
✅ 优点:
- 高内聚、低耦合
- 易于扩展和维护
- 符合开闭原则
❌ 缺点:
- 增加了类的数量(策略类)
- 对于简单逻辑可能显得“过度设计”
⚠️ 使用建议:当你的业务逻辑中频繁出现 if-else
或 switch-case
且每个分支逻辑逐渐复杂时,就该考虑使用策略模式了。
完整源码已上传至 GitHub:点此查看完整代码。