python---策略模式
程序员文章站
2022-03-10 18:32:38
[TOC] python–策略模式 前言 策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。 策略模式: 定义了一族算法(业务规则); 封装了每个算法; 这族的算法可互换代替(interchangeable) 不会影响到使用算法的客户. 结构图 一. 应用 ......
目录
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 语句。