zoukankan      html  css  js  c++  java
  • python---策略模式

    python–策略模式

    前言

    策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。

    策略模式:

    • 定义了一族算法(业务规则);
    • 封装了每个算法;
    • 这族的算法可互换代替(interchangeable)
    • 不会影响到使用算法的客户.

    结构图

    一. 应用

    下面是一个商场的活动实现

    #!/usr/bin/env python
    # ~*~ coding: utf-8 ~*~
    
    
    # 现金收费抽象类
    class CashSuper(object):
    
        def accept_cash(self, money):
            pass
    
    class CashNormal(CashSuper):
        """策略1: 正常收费子类"""
        def accept_cash(self, money):
            return money
    
    class CashRebate(CashSuper):
        """策略2:打折收费子类"""
        def __init__(self, discount=1):
            self.discount = discount
    
        def accept_cash(self, money):
            return money * self.discount
    
    
    class CashReturn(CashSuper):
        """策略3 返利收费子类"""
        def __init__(self, money_condition=0, money_return=0):
            self.money_condition = money_condition
            self.money_return = money_return
    
        def accept_cash(self, money):
            if money >= self.money_condition:
                return money - (money / self.money_condition) * self.money_return
            return money
    
    
    # 具体策略类
    class Context(object):
    
        def __init__(self, cash_super):
            self.cash_super = cash_super
    
        def GetResult(self, money):
            return self.cash_super.accept_cash(money)
    
    if __name__ == '__main__':
        money = input("原价: ")
        strategy = {}
        strategy[1] = Context(CashNormal())
        strategy[2] = Context(CashRebate(0.8))
        strategy[3] = Context(CashReturn(100, 10))
        mode = int(input("选择折扣方式: 1) 原价 2) 8折 3) 满100减10: "))
        if mode in strategy:
            cash_super = strategy[mode]
        else:
            print("不存在的折扣方式")
            cash_super = strategy[1]
        print("需要支付: ", cash_super.GetResult(money))
    
    

    类的设计图如下

    使用一个策略类CashSuper定义需要的算法的公共接口,定义三个具体策略类:CashNormal,CashRebate,CashReturn,继承于CashSuper,定义一个上下文管理类,接收一个策略,并根据该策略得出结论,当需要更改策略时,只需要在实例的时候传入不同的策略就可以,免去了修改类的麻烦

    二. 避免过多使用if…else

    对于业务开发来说,业务逻辑的复杂是必然的,随着业务发展,需求只会越来越复杂,为了考虑到各种各样的情况,代码中不可避免的会出现很多if-else。

    一旦代码中if-else过多,就会大大的影响其可读性和可维护性。

    首先可读性,不言而喻,过多的if-else代码和嵌套,会使阅读代码的人很难理解到底是什么意思。尤其是那些没有注释的代码。

    其次是可维护性,因为if-else特别多,想要新加一个分支的时候,就会很难添加,极其容易影响到其他的分支。

    下面来介绍如何使用策略模式 消除if …else

    示例: 将如下函数改写成策略模式

    # pay_money.py
    #!/usr/bin/env python
    # ~*~ coding: utf-8 ~*~
    
    def get_result(type, money):
        """商场促销"""
        result = money
        if money > 10000:
            if type == "UserType.SILVER_VIP":
                print("白银会员 优惠50元")
                result = money - 50
            elif type == "UserType.GOLD_VIP":
                print("黄金会员 8折")
                result = money * 0.8
    
            elif type == "UserType.PLATINUM_VIP":
                print("白金会员 优惠50元,再打7折")
                result = money * 0.7 - 50
            else:
                print("普通会员 不打折")
                result = money
    
        return result
    

    策略模式如下

    class CashSuper(object):
        """收款抽象类"""
    
        def pay_money(self,money):
            pass
    
    
    class SilverUser(CashSuper):
        """策略1:白银会员收费模式"""
    
        def __init__(self, discount_money=50):
            self.discount_money = discount_money
    
        def pay_money(self,money):
            return money - self.discount_money
    
    class GoldUser(CashSuper):
        """策略2: 黄金会员收费模式"""
        def __init__(self,discount=0.8):
            self.discount = discount
    
        def pay_money(self,money):
            return money* self.discount
    
    class PlatinumUser(CashSuper):
        """策略3: 白金会员收费模式"""
    
        def __init__(self,discount_money=50,discount=0.7):
            self.discount_money = discount_money
            self.discount = discount
    
        def pay_money(self,money):
            if money >= self.discount_money:
                return money* self.discount - self.discount_money
            return money
    
    class NormalUser(CashSuper):
        """策略4: 正常会员不打折"""
    
        def pay_money(self,money):
            return money
    
    
    class Context(object):
        """具体实现的策略类"""
    
        def __init__(self,cash_super):
            """初始化:将策略类传递进去作为属性"""
            self.cash_super = cash_super
    
        def get_result(self,money):
            return self.cash_super.pay_money(money)
    
    
    def main(money, user_type):
        """程序入口"""
    	if money  < 1000:
    		return money
        if user_type == "UserType.SILVER_VIP":
            strategy = Context(SilverUser())
        elif user_type == "UserType.GOLD_VIP":
            strategy = Context(GoldUser())
        elif user_type == "UserType.PLATINUM_VIP":
            strategy = Context(PlatinumUser())
        else:
            strategy = Context(NormalUser())
    
        return strategy.get_result(money)
    

    三. 使用策略,工厂模式.

    代码如下

    #!/usr/bin/env python
    # ~*~ coding: utf-8 ~*~
    
    """
    使用策略模式 + 工厂模式
    """
    
    class StrategyFactory(object):
        """工厂类"""
        strategy = {}
    
        @classmethod
        def get_strategy_by_type(cls, type):
            """类方法:通过type获取具体的策略类"""
            return cls.strategy.get(type)
    
        @classmethod
        def register(cls, strategy_type, strategy):
            """类方法:注册策略类型"""
            if strategy_type == "":
                raise Exception("strategyType can't be null")
            cls.strategy[strategy_type] = strategy
    
    
    class CashSuper(object):
        """收款抽象类"""
    
        def pay_money(self, money):
            pass
    
        def get_type(self):
            pass
    
    
    class SilverUser(CashSuper):
        """策略1:白银会员收费模式"""
    
        def __init__(self, discount_money=50):
            self.discount_money = discount_money
    
        def pay_money(self, money):
            return money - self.discount_money
    
        def get_type(self):
            return "UserType.SILVER_VIP"
    
        def collect_context(self):
            StrategyFactory.register(self.get_type(), SilverUser)
    
    
    class GoldUser(CashSuper):
        """策略2: 黄金会员收费模式"""
    
        def __init__(self, discount=0.8):
            self.discount = discount
    
        def pay_money(self, money):
            return money * self.discount
    
        def get_type(self):
            return "UserType.GOLD_VIP"
    
        def collect_context(self):
            StrategyFactory.register(self.get_type(), GoldUser)
    
    
    class PlatinumUser(CashSuper):
        """策略3: 白金会员收费模式"""
    
        def __init__(self, discount_money=50, discount=0.7):
            self.discount_money = discount_money
            self.discount = discount
    
        def pay_money(self, money):
            if money >= self.discount_money:
                return money * self.discount - self.discount_money
            return money
    
        def get_type(self):
            return "UserType.PLATINUM_VIP"
    
        def collect_context(self):
            StrategyFactory.register(self.get_type(), PlatinumUser)
    
    
    class NormalUser(CashSuper):
        """策略4: 正常会员不打折"""
    
        def pay_money(self, money):
            return money
    
        def get_type(self):
            return "UserType.Normal"
    
        def collect_context(self):
            StrategyFactory.register(self.get_type(), NormalUser)
    
    
    def InitialStrategys():
        """初始化方法:收集策略函数"""
        NormalUser().collect_context()
        PlatinumUser().collect_context()
        GoldUser().collect_context()
        SilverUser().collect_context()
    
    
    def main(money, type):
        """入口函数"""
        InitialStrategys()
        strategy = StrategyFactory.get_strategy_by_type(type)
        if not strategy:
            raise Exception("please input right type!")
        return strategy().pay_money(money)
    
    
    if __name__ == "__main__":
        money = int(input("show money:"))
        type = input("Pls input user Type:")
        result = main(money, type)
        print("should pay money:", result)
    
    

    通过一个工厂类StrategyFactory,在我们在调用register类方法时将策略收集到策略中,根据传入 type,即可获取到对应 Strategy

    消灭了大量的 if-else 语句。

  • 相关阅读:
    Matlab 将RGB 图像转换成YCrCb图像
    dotnet中文字符工具类
    dotnet验证参数
    dotnet + LinQ 按照指定的字段 和 排序方式排序
    Angulaur导入其他位置的样式
    Angular4.x跨域请求
    Spring Cloud微服务实战:手把手带你整合eureka&zuul&feign&hystrix
    关于JVM加载class文件和类的初始化
    JVM垃圾回收机制概述
    深入理解JVM
  • 原文地址:https://www.cnblogs.com/failymao/p/12455840.html
Copyright © 2011-2022 走看看