1. 概述

在本教程中,我们将探讨 Kotlin 中的策略设计模式,并通过一个实际案例理解它解决的问题。

策略模式(Strategy Pattern)是一种行为型设计模式,它允许我们为同一问题定义多个解决方案,并在运行时动态切换这些方案。这是实际项目中使用最广泛的设计模式之一,尤其适用于需要根据不同条件动态改变行为的场景。

2. 代码示例

我们以一个简单的书店系统为例。书店根据用户的会员类型提供不同的折扣,比如普通会员享受10%折扣,高级会员享受20%折扣。当用户购买书籍时,系统需要根据其会员类型计算折扣金额。

我们先来看不使用策略模式的实现方式。

2.1. Book

首先定义一个表示书籍的类:

data class Book(val title: String, val price: Double)

为了简化,我们只保留两个属性:titleprice

2.2. Customer

接着定义一个表示用户的类:

data class Customer(val name: String, val membershipType: MembershipType)

这个类有两个属性:namemembershipType,其中 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-elseswitch-case 且每个分支逻辑逐渐复杂时,就该考虑使用策略模式了。

完整源码已上传至 GitHub:点此查看完整代码


原始标题:Strategy Design Pattern in Kotlin