swift设计模式学习 - 策略模式

前端之家收集整理的这篇文章主要介绍了swift设计模式学习 - 策略模式前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

移动端访问不佳,请访问我的个人博客

设计模式学习的demo地址,欢迎大家学习交流

策略模式

策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户。

策略模式的组成

  • 抽象策略角色(Strategy): 策略类,通常由一个接口或者抽象类实现。
  • 具体策略角色(ConcreteStrategy):包装了相关的算法和行为。
  • 环境角色(Context):持有一个策略类的引用,最终给客户端调用

策略模式的基本实现

上图是最基本的装饰模式的结构图,下面将用Swift代码来实现一个基本策略模式:

// 策略类,定义所有支持 的算法的公共接口@H_404_27@
protocol Strategy {
    func AlgorithmInterface()
}

// 具体策略类,封装了具体的算法或行为,继承于Strategy@H_404_27@
class@H_404_27@ ConcreteStrategyA@H_404_27@: Strategy@H_404_27@ {@H_404_27@
    func AlgorithmInterface() {
        print("ConcreteStrategyA"@H_404_27@)
    }
}

class@H_404_27@ ConcreteStrategyB@H_404_27@: Strategy@H_404_27@ {@H_404_27@
    func AlgorithmInterface() {
        print("ConcreteStrategyB"@H_404_27@)
    }
}

class@H_404_27@ ConcreteStrategyC@H_404_27@: Strategy@H_404_27@ {@H_404_27@
    func AlgorithmInterface() {
        print("ConcreteStrategyC"@H_404_27@)
    }
}

// Context上下文,用一个 ConcreteStrategy来配置,维护一个对Strategy对象的引用@H_404_27@
class@H_404_27@ Context@H_404_27@ {@H_404_27@
    var@H_404_27@ strategy: Strategy?
    func ContextInterface() {
        strategy?.AlgorithmInterface()
    }
}

以上代码是最简单的策略模式的实现过程,定义了一个Strategy的算法族,通过它的子类可以实现算法(AlgorithmInterface)的替换,而不会影响到客户端。

用策略模式解决实际问题(商场打折)

我们知道在商场中一般有很多打折优惠方案,类似这种问题就可以用策略模式来解决,打折不同的方案就相当于不同的策略(ConcreteStrategy),然后用一个Context类来实现不同算法的切换,下面是商场打折策略模式的实现于UML图:

以上是一个简单的商场收银系统,CashNormal为普通收费子类,CashRebate为打折收费子类,CashReturn为返利收费子类,下面是代码的实现过程:

import@H_404_27@ Foundation

// 定义一个收费的策略接口@H_404_27@
protocol CashSuper {
    func acceptCash(money: Double) -> @H_404_27@Double
}

// 普通收费子类@H_404_27@
class CashNormal: CashSuper {
    // 正常原价返回@H_404_27@
    func acceptCash(money: Double) -> @H_404_27@Double {
        return@H_404_27@ money
    }
}

// 打折收费子类@H_404_27@
class CashRebate: CashSuper {
    // 折扣率@H_404_27@
    private@H_404_27@ var@H_404_27@ moneyRebate: Double =@H_404_27@ 1.0@H_404_27@

    init(moneyRebate: Double) {
        self@H_404_27@.@H_404_27@moneyRebate =@H_404_27@ moneyRebate
    }

    func acceptCash(money: Double) -> @H_404_27@Double {
        return@H_404_27@ money*@H_404_27@moneyRebate
    }
}

// 返利收费子类@H_404_27@
class CashReturn: CashSuper {
    // 返利要求@H_404_27@
    private@H_404_27@ var@H_404_27@ moneyCondition: Double =@H_404_27@ 0@H_404_27@
    // 返多少@H_404_27@
    private@H_404_27@ var@H_404_27@ moneyReturn: Double    =@H_404_27@ 0@H_404_27@

    init(moneyCondition: Double,moneyReturn: Double) {
        self@H_404_27@.@H_404_27@moneyCondition =@H_404_27@ moneyCondition
        self@H_404_27@.@H_404_27@moneyReturn    =@H_404_27@ moneyReturn
    }

    func acceptCash(money: Double) -> @H_404_27@Double {
        var@H_404_27@ result =@H_404_27@ money
        if@H_404_27@ money >=@H_404_27@ moneyCondition {
            result =@H_404_27@ money -@H_404_27@ floor(money /@H_404_27@ moneyCondition) *@H_404_27@ moneyReturn
        }
        return@H_404_27@ result
    }
}


// context类@H_404_27@
class CashContext {
    private@H_404_27@ var@H_404_27@ cs: CashSuper?@H_404_27@

    // 通过枚举判断使用哪种方式@H_404_27@
    init(style: CashStyle) {
        switch style {
        case@H_404_27@ .@H_404_27@normal:
            cs =@H_404_27@ CashNormal()
        case@H_404_27@ .@H_404_27@rebate(moneyRebate: let@H_404_27@ money):
            cs =@H_404_27@ CashRebate(moneyRebate: money)
        case@H_404_27@ .@H_404_27@return@H_404_27@(moneyCondition: let@H_404_27@ moneyCondition,moneyReturn: let@H_404_27@ moneyReturn):
            cs =@H_404_27@ CashReturn(moneyCondition: moneyCondition,moneyReturn: moneyReturn)
        }
    }

    func getResult(money: Double) -> @H_404_27@Double {
        return@H_404_27@ cs?@H_404_27@.@H_404_27@acceptCash(money: money) ??@H_404_27@ 0@H_404_27@
    }
}

// 优惠的枚举类型@H_404_27@
enum CashStyle {
    case@H_404_27@ normal
    case@H_404_27@ rebate(moneyRebate: Double)
    case@H_404_27@ `return`@H_404_27@(moneyCondition: Double,moneyReturn: Double)
}

下面我们测试一下代码

let@H_404_27@ money@H_404_27@: Double = 300@H_404_27@
// 普通
let@H_404_27@ normal = CashContext(style@H_404_27@: .normal)
//@H_404_27@ 打7@H_404_27@折
let@H_404_27@ rebate = CashContext(style@H_404_27@: .rebate(moneyRebate@H_404_27@: 0.7@H_404_27@))
//@H_404_27@ 满一百返20@H_404_27@
let@H_404_27@ `return@H_404_27@@H_404_27@` = CashContext(style@H_404_27@: .return@H_404_27@(moneyCondition@H_404_27@: 100@H_404_27@,moneyReturn@H_404_27@: 20@H_404_27@))
print@H_404_27@("普通: \(normal.getResult(money: money))"@H_404_27@)
print@H_404_27@("打7折: \(rebate.getResult(money: money))"@H_404_27@)
print@H_404_27@("满一百返20: \(`return`.getResult(money: money))"@H_404_27@)

下面是执行的结果:

普通: 300.0
打7折: 210.0
满一百返20: 240.0

策略模式总结

我们可以理解为策略就是用来封装算法,但在实践过程中不用那么死板,可以用来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。

以上是我对于策略模式的理解,如果有不对的地方欢迎大家交流,最后谢谢大家的阅读~~

猜你在找的Swift相关文章