设计模式-2.策略模式

196 阅读2分钟

一句话概括

策略模式是一种定义一系列算法的方法,这些算法具有相同的功能,只是不同的实现。它以相同的方式(Api)调用所有算法类,减少了算法类和使用算法类的耦合。

需求

实现一个商城收银系统,可以根据单价和数量算出总价。

Code V1.0

根据需求很容易实现相关功能,计算出单个商品的总价,再累加求出总价。

class CashierSystem {
    static var totalPrice: Float = 0
    
    static func calculateTotalPrice(commodityName: String, unitPrice: Float, number: Int) {
        let singleCommodityTotalPrice = unitPrice * Float(number)
        totalPrice += singleCommodityTotalPrice
        
        print("商品:\(commodityName),价格:\(unitPrice) * \(number)个 = \(singleCommodityTotalPrice)")
        print("总价为:\(totalPrice)")
    }
    
    static func reset() {
        totalPrice = 0
    }
}

Code V2.0

商城经常会出现打折、满减活动,1.0的代码就满足不了这些需求。那么可以利用简单工厂模式来实现,属于创建型模式,由工厂类来生成不同的优惠类。

class CashierSystem {
    static var totalPrice: Float = 0
    
    static func calculateTotalPrice(commodityName: String, unitPrice: Float, number: Int, type: String) {

        let cashAccept = CashFctory.creatCashAccept(type: type)
        var singleCommodityTotalPrice = unitPrice * Float(number)
        singleCommodityTotalPrice = cashAccept.acceptCash(money: singleCommodityTotalPrice)
        totalPrice += singleCommodityTotalPrice
        
        print("商品:\(commodityName),价格:\(unitPrice) * \(number)个 = \(singleCommodityTotalPrice)")
        print("总价为:\(totalPrice)")
    }
    
    static func reset() {
        totalPrice = 0
    }
}

protocol CashProtocol {
    func acceptCash(money: Float) -> Float
}

class CashNormal: CashProtocol {
    func acceptCash(money: Float) -> Float {
        return money
    }
}

class CashDiscount: CashProtocol {
    ///折扣
    let discount: Float
    
    init(discount: Float) {
        self.discount = discount
    }
    
    func acceptCash(money: Float) -> Float {
        return money * discount
    }
}

class CashReturn: CashProtocol {
    ///满减条件金额
    let moneyCondition: Float
    ///满减金额
    let moneyReturn: Float
    
    init(moneyCondition: Float, moneyReturn: Float) {
        self.moneyCondition = moneyCondition
        self.moneyReturn = moneyReturn
    }
    
    func acceptCash(money: Float) -> Float {
        var result = money
        if money > moneyCondition {
            result = floor(money / moneyCondition) * moneyReturn
        }
        return result
    }
}

class CashFctory {
    static func creatCashAccept(type: String) -> CashProtocol {
        var cash: CashProtocol = CashNormal()
        switch type {
        case "正常收费":
            cash = CashNormal()
        case "打8折":
            cash = CashDiscount(discount: 0.8)
        case "满300返100":
            cash = CashReturn(moneyCondition: 300, moneyReturn: 100)
        default:
            break
        }
        return cash
    }
}

Code V3.0

下面用策略模式来实现这个需求,策略模式属于行为型模式。和简单工厂模式区别是策略模式不生成对象,是拿传进来的对象做事情,简单工厂模式是通过传进来的参数来生成对象。

class CashierSystem {
    static var totalPrice: Float = 0
    
    static func calculateTotalPrice(commodityName: String, unitPrice: Float, number: Int, type: String) {

        let cashContext = CashContext(type: type)
        var singleCommodityTotalPrice = unitPrice * Float(number)
        singleCommodityTotalPrice = cashContext.getResult(money: singleCommodityTotalPrice)
        totalPrice += singleCommodityTotalPrice
        
        print("商品:\(commodityName),价格:\(unitPrice) * \(number)个 = \(singleCommodityTotalPrice)")
        print("总价为:\(totalPrice)")
    }
    
    static func reset() {
        totalPrice = 0
    }
}

protocol CashProtocol {
    func acceptCash(money: Float) -> Float
}

class CashNormal: CashProtocol {
    func acceptCash(money: Float) -> Float {
        return money
    }
}

class CashDiscount: CashProtocol {
    ///折扣
    let discount: Float
    
    init(discount: Float) {
        self.discount = discount
    }
    
    func acceptCash(money: Float) -> Float {
        return money * discount
    }
}

class CashReturn: CashProtocol {
    ///满减条件金额
    let moneyCondition: Float
    ///满减金额
    let moneyReturn: Float
    
    init(moneyCondition: Float, moneyReturn: Float) {
        self.moneyCondition = moneyCondition
        self.moneyReturn = moneyReturn
    }
    
    func acceptCash(money: Float) -> Float {
        var result = money
        if money > moneyCondition {
            result = floor(money / moneyCondition) * moneyReturn
        }
        return result
    }
}

class CashContext {
    let cash: CashProtocol
    
    //标准策略模式不在Context内部生成对象
    init(type: String) {
        switch type {
        case "正常收费":
            self.cash = CashNormal()
        case "打8折":
            self.cash = CashDiscount(discount: 0.8)
        case "满300返100":
            self.cash = CashReturn(moneyCondition: 300, moneyReturn: 100)
        default:
            self.cash = CashNormal()
        }
    }
    
    func getResult(money: Float) -> Float {
        cash.acceptCash(money: money)
    }
}