策略模式
策略模式是一种行为设计模式,它定义了一系列算法,将每个算法封装成具有共同接口的独立类,并使他们可以互相替换。策略模式使得算法可以独立于客户端的变化,客户端通过使用不同的策略对象来选择不同的算法,从而实现不同的行为或功能。
优点
- 灵活性:可以在运行时动态切换算法,根据不同的需求选择不同的策略。
- 复用性:通过策略模式可以复用现有的算法实现,而不需要修改现有的代码结构。
- 单一职责原则:每个具体策略类都实现了一个算法,符合单一职责原则,使得代码更加清晰和易于维护。
示例
例如,在一个电商系统中,可以使用不同的策略模式来实现不同的促销策略。每种策略模式可以作为一个具体的策略类,实现一个方法来计算最终价格。客户端可以根据当前的营销活动选择不用的促销策略,从而计算出最优的价格。
1.定义策略接口
首先,我们定义一个抽象的折扣策略接口 DiscountStrategy:
protocol DiscountStrategy {
func applyDiscount(originalPrice: Double) -> Double
}
2. 实现具体的折扣策略类
然后,实现几种具体的折扣策略类,分别计算不同的折扣方式:
// 打折策略
class PercentageDiscountStrategy: DiscountStrategy {
private let percentage: Double // 折扣百分比
init(percentage: Double) {
self.percentage = max(0, min(percentage, 100)) // 百分比应该在 0 到 100 之间
}
func applyDiscount(originalPrice: Double) -> Double {
let discountAmount = originalPrice * (percentage / 100)
return originalPrice - discountAmount
}
}
// 满减策略
class FlatAmountDiscountStrategy: DiscountStrategy {
private let threshold: Double // 触发满减的金额阈值
private let discountAmount: Double // 满减的金额
init(threshold: Double, discountAmount: Double) {
self.threshold = threshold
self.discountAmount = discountAmount
}
func applyDiscount(originalPrice: Double) -> Double {
return originalPrice >= threshold ? originalPrice - discountAmount : originalPrice
}
}
3. 创建上下文类
接下来,创建一个上下文类 PriceCalculator,它接受一个具体的折扣策略对象,并提供计算最终价格的方法:
class PriceCalculator {
private var discountStrategy: DiscountStrategy
init(discountStrategy: DiscountStrategy) {
self.discountStrategy = discountStrategy
}
func setDiscountStrategy(_ discountStrategy: DiscountStrategy) {
self.discountStrategy = discountStrategy
}
func calculateFinalPrice(originalPrice: Double) -> Double {
return discountStrategy.applyDiscount(originalPrice: originalPrice)
}
}
4. 示例用法
最后,我们可以在客户端代码中使用策略模式来计算不同促销策略下的商品最终价格:
// 创建具体的折扣策略对象
let percentageStrategy = PercentageDiscountStrategy(percentage: 20)
let flatAmountStrategy = FlatAmountDiscountStrategy(threshold: 100, discountAmount: 20)
// 创建价格计算器上下文对象,并设置具体的折扣策略
let calculator = PriceCalculator(discountStrategy: percentageStrategy)
// 计算不同策略下的最终价格
let originalPrice = 150.0
let finalPrice1 = calculator.calculateFinalPrice(originalPrice: originalPrice)
print("Final Price with 20% discount: \(finalPrice1)")
// 切换到另一种策略
calculator.setDiscountStrategy(flatAmountStrategy)
let finalPrice2 = calculator.calculateFinalPrice(originalPrice: originalPrice)
print("Final Price with $20 off for orders over $100: \(finalPrice2)")
添加一个函数来比较不同策略计算出来的最终价格,并返回最便宜的策略:
// 定义一个函数来找到最便宜的策略
func findCheapestStrategy(strategies: [DiscountStrategy], originalPrice: Double) -> DiscountStrategy? {
guard let firstStrategy = strategies.first else { return nil }
var cheapestStrategy = firstStrategy
var cheapestPrice = firstStrategy.applyDiscount(originalPrice: originalPrice)
for strategy in strategies.dropFirst() {
let price = strategy.applyDiscount(originalPrice: originalPrice)
if price < cheapestPrice {
cheapestPrice = price
cheapestStrategy = strategy
}
}
return cheapestStrategy
}
let strategies: [DiscountStrategy] = [percentageStrategy, flatAmountStrategy]
if let cheapestStrategy = findCheapestStrategy(strategies: strategies, originalPrice: 150.0) {
let finalPrice = cheapestStrategy.applyDiscount(originalPrice: 150.0)
print("Cheapest Strategy: Final Price is \(finalPrice)")
} else {
print("No strategy found")
}