精华内容
下载资源
问答
  • python策略模式
    千次阅读
    2020-07-04 18:52:56

    python设计模式之策略模式

    大多数问题都可以使用多种方法来解决。以排序问题为例,对于以一定次序把元素放入一个列表,排序算法有很多。通常来说,没有公认最适合所有场景的算法一些不同的评判标准能帮助我们为不同的场景选择不同的排序算法,其中应该考虑的有以下几个。

    • 需要排序的元素数量:这被称为输入大小。当输入较少时,几乎所有排序算法的表现都很好,但对于大量输入,只有部分算法具有不错的性能。
    • 算法的最佳/平均/最差时间复杂度:时间复杂度是算法运行完成所花费的(大致)时间长短,不考虑系数和低阶项①。这是选择算法的最常见标准,但这个标准并不总是那么充分。
    • 算法的空间复杂度:空间复杂度是充分地运行一个算法所需要的(大致)物理内存量。在我们处理大数据或在嵌入式系统(通常内存有限)中工作时,这个因素非常重要。
    • 算法的稳定性:在执行一个排序算法之后,如果能保持相等值元素原来的先后相对次序,则认为它是稳定的。
    • 算法的代码实现复杂度:如果两个算法具有相同的时间/空间复杂度,并且都是稳定的,那么知道哪个算法更易于编码实现和维护也是很重要的。

    可能还有更多的评判标准值得考虑,但重要的是,我们真的只能使用单个排序算法来应对所有情况吗?答案当然不是。一个更好的方案是把所有排序算法纳为己用,然后使用上面提到的标准针对当前情况选择最好的算法。这就是策略模式的目的。

    策略模式( Strategy pattern)鼓励使用多种算法来解决一个问题,其杀手级特性是能够在运行时透明地切换算法(客户端代码对变化无感知)。因此,如果你有两种算法,并且知道其中一种对少量输入效果更好,另一种对大量输入效果更好,则可以使用策略模式在运行时基于输入数据决定使用哪种算法。

    1. 现实生活的例子

    去机场赶飞机是现实中使用策略模式的一个恰当例子。

    • 如果想省钱,并且早点出发,那么可以坐公交车/地铁。
    • 如果不介意支付停车费,并且有自己的汽车,那么可以开车去。
    • 如果没有自己的车,又比较急,则可以打车。

    这是费用、时间、便利性等因素之间的一个折中权衡。

    2. 软件的例子

    Python的sorted()和list.sort()函数是策略模式的例子。两个函数都接受一个命名参数key,这个参数本质上是实现了一个排序策略的函数的名称。

    下面的例子展示了如何用以下方式使用两种不同的策略对编程语言进行排序。

    • 按字母顺序
    • 基于它们的流行度

    namedtuple编程语言用于保存编程语言的统计数据。命名元组是一种易于创建、轻量、不可变的对象类型,与普通元组兼容,但也可以看作一个对象(可以使用常见的类表示法通过名称调用)。

    • 在我们关注不可变特性时,替代一个类
    • 在值得使用对象表示法来创建可读性更高的代码时,替代一个元组

    顺便说明一下pprint和attrgetter模块。 pprint模块用于美化输出一个数据结构,attrgetter用于通过属性名访问class或namedtuple的属性。也可以使用一个lambda函数来替代使用attrgetter,但我觉得attrgetter的可读性更高。

    import pprint
    from collections import namedtuple
    from operator import attrgetter
    if __name__ == '__main__':
        ProgrammingLang = namedtuple('ProgrammingLang', 'name ranking')
        stats = (('Ruby', 14), ('Javascript', 8), ('Python', 7),('Scala', 31), ('Swift', 18), ('Lisp', 23))
        lang_stats = [ProgrammingLang(n, r) for n, r in stats]
        pp = pprint.PrettyPrinter(indent=5)
        pp.pprint(sorted(lang_stats, key=attrgetter('name')))
        print()
        pp.pprint(sorted(lang_stats, key=attrgetter('ranking')))	
    

    输出如下:

    [ ProgrammingLang(name='Javascript', ranking=8),
    ProgrammingLang(name='Lisp', ranking=23),
    ProgrammingLang(name='Python', ranking=7),
    ProgrammingLang(name='Ruby', ranking=14),
    ProgrammingLang(name='Scala', ranking=31),
    ProgrammingLang(name='Swift', ranking=18)]
    [ ProgrammingLang(name='Python', ranking=7),
    ProgrammingLang(name='Javascript', ranking=8),
    ProgrammingLang(name='Ruby', ranking=14),
    ProgrammingLang(name='Swift', ranking=18),
    ProgrammingLang(name='Lisp', ranking=23),
    ProgrammingLang(name='Scala', ranking=31)]
    

    Java API也使用了策略设计模式。 java.util.Comparator是一个接口, 包含一个compare()方法,该方法本质上是一个策略,可传给排序方法,比如Collections.sort和Arrays.sort。

    3. 应用案例

    策略模式是一种非常通用的设计模式,可应用的场景很多。一般来说,不论何时希望动态、透明地应用不同算法,策略模式都是可行之路。这里所说不同算法的意思是,目的相同但实现方案不同的一类算法。这意味着算法结果应该是完全一致的,但每种实现都有不同的性能和代码复杂性(举例来说,对比一下顺序查找和二分查找)。

    我们已看到Python和Java如何使用策略模式来支持不同的排序算法。然而,策略模式并不限于排序问题,也可用于创建各种不同的资源过滤器(身份验证、日志记录、数据压缩和加密等)。

    策略模式的另一个应用是创建不同的样式表现,为了实现可移植性(例如,不同平台之间断行的不同)或动态地改变数据的表现。

    另一个值得一提的应用是模拟;例如模拟机器人,一些机器人比另一些更有攻击性,一些机器人速度更快,等等。机器人行为中的所有不同之处都可以使用不同的策略来建模。

    4. 实现

    关于策略模式的实现没有太多可说的。在函数非一等公民的语言中,每个策略都要用一个不同的类来实现。在Python中,我们可以把函数看作是普通的变量,这就简化了策略模式的实现。

    假设我们要实现一个算法来检测在一个字符串中是否所有字符都是唯一的。例如,如果输入字符串dream,算法应返回true,因为没有字符是重复的。如果输入字符串pizza,算法应返回false,因为字母z出现了两次。注意,重复字符不一定是连续的,并且字符串也不一定是一个合法单词。对于字符串1r2a3ae,算法也应该返回false,因为其中字母a出现了两次。

    在仔细考虑问题之后,我们提出一种实现:对字符串进行排序并逐对比较所有字符。我们首先实现pairs()函数,它会返回所有相邻字符对的一个序列seq。

    def pairs(seq):
        n = len(seq)
        for i in range(n):
        	yield seq[i], seq[(i + 1) % n]	
    

    接下来,实现allUniqueSort()函数。它接受一个字符串参数s,如果该字符串中所有字符都是唯一的,则返回True;否则,返回False。为演示策略模式,我们进行一些简化,假设这个算法的伸缩性不好,对于不超过5个字符的字符串才能工作良好。对于更长的字符串,通过插入一条sleep语句来模拟速度减缓。

    SLOW = 3 # 单位为秒
    LIMIT = 5 # 字符数
    WARNING = 'too bad, you picked the slow algorithm :('
    def allUniqueSort(s):
        if len(s) > LIMIT:
            print(WARNING)
            time.sleep(SLOW)
        srtStr = sorted(s)
        for (c1, c2) in pairs(srtStr):
            if c1 == c2:
            	return False
        return True
    

    我们对allUniqueSort()的性能并不满意,所以尝试考虑优化的方式。一段时间之后,我们提出一个新算法allUniqueSet(),消除排序的需要。在这里,我们使用一个集合来实现算法。如果正在检测的字符已经被插入到集合中,则意味着字符串中并非所有字符都是唯一的。

    def allUniqueSet(s):
        if len(s) < LIMIT:
            print(WARNING)
            time.sleep(SLOW)
        return True if len(set(s)) == len(s) else False
    

    不幸的是, allUniqueSet()虽然没有伸缩性问题,但出于一些奇怪的原因,它检测短字符串的性能比allUniqueSort()更差。这样的话我们能做点什么呢?没关系,我们可以保留两个算法,并根据待检测字符串的长度来选择最合适的那个算法。函数allUnique()接受一个输入字符串s和一个策略函数strategy,在这里是allUniqueSort()和allUniqueSet()中的一个。函数allUnique执行输入的策略,并向调用者返回结果。

    使用main()函数可以执行以下操作。

    • 输入待检测字符唯一性的单词
    • 选择要使用的策略

    该函数还进行了一些基本的错误处理,并让用户能够正常退出程序。

    def main():
        while True:
            word = None
            while not word:
                word = input('Insert word (type quit to exit)> ')
                if word == 'quit':
                	print('bye')
                    return
                strategy_picked = None
                strategies = { '1': allUniqueSet, '2': allUniqueSort }
                while strategy_picked not in strategies.keys():
                    strategy_picked = input('Choose strategy: [1] Use a set, [2] Sort and pair> ')
                    try:
                        strategy = strategies[strategy_picked]
                        print('allUnique({}): {}'.format(word, allUnique(word,strategy)))
                    except KeyError as err:
                        print('Incorrect option: {}'.format(strategy_picked))
    

    下面是该示例的完整代码:

    import time
    SLOW = 3 # 单位为秒
    LIMIT = 5 # 字符数
    WARNING = 'too bad, you picked the slow algorithm :('
    def pairs(seq):
        n = len(seq)
        for i in range(n):
        	yield seq[i], seq[(i + 1) % n]
    def allUniqueSort(s):
        if len(s) > LIMIT:
        	print(WARNING)
        	time.sleep(SLOW)
        	srtStr = sorted(s)
        for (c1, c2) in pairs(srtStr):
        	if c1 == c2:
        		return False
        return True
    def allUniqueSet(s):
        if len(s) < LIMIT:
        	print(WARNING)
        	time.sleep(SLOW)
        return True if len(set(s)) == len(s) else False
    def allUnique(s, strategy):
    	return strategy(s)
    def main():
        while True:
            word = None
            while not word:
            	word = input('Insert word (type quit to exit)> ')
            	if word == 'quit':
                    print('bye')
                    return
                strategy_picked = None
                strategies = { '1': allUniqueSet, '2': allUniqueSort }
                while strategy_picked not in strategies.keys():
                    strategy_picked = input('Choose strategy: [1] Use a set, [2] Sort and pair> ')
                    try:
                    	strategy = strategies[strategy_picked]
                    	print('allUnique({}): {}'.format(word, allUnique(word,strategy)))
                    except KeyError as err:
                        print('Incorrect option: {}'.format(strategy_picked))
                    print()
    if __name__ == '__main__':
    	main()
    

    输出:

    Insert word (type quit to exit)> balloon
    Choose strategy: [1] Use a set, [2] Sort and pair> 1
    allUnique(balloon): False
    Insert word (type quit to exit)> balloon
    Choose strategy: [1] Use a set, [2] Sort and pair> 2
    too bad, you picked the slow algorithm :(
    allUnique(balloon): False
    Insert word (type quit to exit)> bye
    Choose strategy: [1] Use a set, [2] Sort and pair> 1
    too bad, you picked the slow algorithm :(
    allUnique(bye): True
    Insert word (type quit to exit)> bye
    Choose strategy: [1] Use a set, [2] Sort and pair> 2
    allUnique(bye): True
    Insert word (type quit to exit)> h
    Choose strategy: [1] Use a set, [2] Sort and pair> 1
    too bad, you picked the slow algorithm :(
    allUnique(h): True
    Insert word (type quit to exit)> h
    Choose strategy: [1] Use a set, [2] Sort and pair> 2
    allUnique(h): False
    Insert word (type quit to exit)> quit
    bye
    

    第一个单词( ballon)多于5个字符,并且不是所有字符都是唯一的。这种情况下,两个算法都返回了正确结果( False),但allUniqueSort()更慢,用户也收到了警告。

    第二个单词( bye)少于5个字符,并且所有字符都是唯一的。再一次,两个算法都返回了期望的结果( True),但这一次, allUniqueSet()更慢,用户也再一次收到警告。

    最后一个单词( h)是一个特殊案例。 allUniqueSet()运行慢,处理正确,返回期望的True;算法allUniqueSort()返回超快,但结果错误。你能明白为什么吗?作为练习,请修复allUniqueSort()算法。你也许想禁止处理单字符的单词,我觉得这样挺不错(相比返回一个错误结果,这样更好)。

    通常,我们想要使用的策略不应该由用户来选择。策略模式的要点是可以透明地使用不同的算法。修改一下代码,使得程序始终选择更快的算法。

    我们的代码有两种常见用户。一种是最终用户,他们不应该关心代码中发生的事情。为达到这个效果,我们可以遵循前一段给出的提示来实现。另一类用户是其他开发人员。假设我们想创建一个供其他开发人员使用的API。如何做到让他们不用关心策略模式?一个提示是考虑在一个公用类(例如, AllUnique)中封装两个函数。这样,其他开发人员只需要创建一个AllUnique类实例,并执行单个方法,例如test()。

    5. 实现

    策略模式通常用在我们希望对同一个问题透明地使用多种方案时。如果并不存在针对所有输入数据和所有情况的完美算法,那么我们可以使用策略模式,动态地决定在每种情况下应使用哪种算法。现实中,在我们想赶去机场乘飞机时会使用策略模式。

    Python使用策略模式让客户端代码决定如何对一个数据结构中的元素进行排序。我们看到了一个例子,基于TIOBE指数排行榜对编程语言进行排序。

    策略设计模式的使用并不限于排序领域。加密、压缩、日志记录及其他资源处理的领域都可以使用策略模式来提供不同的数据处理方式。可移植性是策略模式的另一个用武之地。模拟也是另一个策略模式适用的领域。

    更多相关内容
  • 本文实例讲述了Python设计模式之策略模式。分享给大家供大家参考,具体如下: 策略模式(Strategy Pattern):它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. ...
  • 本文实例为大家分享了python策略模式代码,供大家参考,具体内容如下 策略模式 import types class StrategyExample: def __init__(self, func=None): self.name = '策略例子0' if func is not None: 给实例...
  • Python策略模式实例

    千次阅读 2022-03-12 19:37:01
    本文介绍策略模式以及其示例

    一 策略模式

    完成一件事通常有很多种方式,每一种方式都是一个策略。

    策略模式(Strategy)定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。

    经典的策略模式由三部分组成:

    • Context:上下文环境类
    • Stragety:策略基类
    • ConcreteStragety:具体策略

    Context用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。

    UML结构图如下:

     二 策略模式的优缺点

         优点

    • 算法可以自由切换
    • 避免使用多重条件判断(如果不用策略模式我们可能会使用多重条件语句,不利于维护)
    • 扩展性良好,增加一个策略只需实现接口即可

       缺点

    • 策略类数量会增多,每个策略都是一个类,复用的可能性很小
    • 所有的策略类都需要对外暴露

    三 策略模式的示例

    以超市优惠打折的三种策略为例,演示策略模式:

    策略模式的三部分对应示例中的类如下:

    • Context:Order类
    • Stragety:Promotion类
    • ConcreteStragety:BonusPointPromo、BulkPromo、LargeOrderPromo类

    一些例子中用到的别的类:

    class Item(object):
        '''商品类 :商品种类、价格、数量,该商品的总价'''
        def __init__(self,issue, price, quantity):
            self.issue = issue
            self.price = price
            self.quantity = quantity
    
        def itemtotal(self):  #返回购买该商品的总价
            return self.price * self.quantity
    
    
    class Customer(object):
        '''顾客类 :顾客名字、顾客的积分'''
        def __init__(self, name ,bonuspoint):
            self.name = name
            self.bonuspoint = bonuspoint
            

    Context:Order类

    class Order(object):
        '''订单类:顾客(主要用来查看其原始积分情况)、选择的优惠方案'''
        def __init__(self, customer, promotion=None):
            self.cart = []
            self.customer = customer
            self.promotion = promotion
    
        def add_to_cart(self, *items):  #加入购物车方法,传入不定长的Item类实例
            for item in items:
                self.cart.append(item)
    
        def total(self):    #计算订单的总价 为每种商品的总价和
            total = 0
            for item in self.cart:
                total += item.itemtotal()
            return total
    
        def pay(self):  #计算该订单需要实际出的钱
            if not self.promotion:  #如果没有优惠促销活动 那么折扣为0
                discount = 0
            else:
                discount  = self.promotion.discount(self) #有的话 计算折扣
            payment = self.total() - discount  #payment为最后需要付的钱
            print(f'折扣策略{type(self.promotion).__name__}:原价{self.total()},折扣价: {payment}')
            return payment

     Stragety:Promotion类

    from abc import ABC, abstractmethod
    
    class Promotion(ABC):
        @abstractmethod     #定义抽象方法,子类必须重写discount方法
        def discount(self, order):
            pass

    这里介绍一下上述用到的@abstractmethod的用法:

    由于python 没有抽象类、接口的概念,所以要实现这种功能得abc.py 这个类库。

    @abstractmethod:抽象方法,含abstractmethod方法的类不能实例化,继承了含abstractmethod方法的子类必须复写所有abstractmethod装饰的方法,未被装饰的可以不重写。

    ConcreteStragety:BonusPointPromo、BulkPromo、LargeOrderPromo类

    class BonusPointPromo(Promotion):  #积分兑换的优惠策略,继承Promotion类
        '''
        积分满1000分,可以兑换20元现金券。该方法不能与别的优惠方案叠加使用
        '''
        def discount(self, order):
            return 20 if order.customer.bonuspoint >=1000 else 0
    
    
    class BulkPromo(Promotion):   #大宗购买的优惠策略,继承Promotion类
        '''
        商品总数购买10件,总订单可打9折。该方法不能与别的优惠方案叠加使用
        '''
        def discount(self, order):
            discount = 0
            totalQuantity=0
            for item in order.cart:
                totalQuantity += item.quantity
            if totalQuantity >= 10:
                discount = order.total() * 0.1
                
            return discount
    
    
    class LargeOrderPromo(Promotion):  #高额订单的优惠策略,继承Promotion类
        '''
        订单总金额大于等于500元,立减50元
        '''
        def discount(self, order):
            discount = 0
            if order.total() >= 500:
                discount = 50
    
            return discount
    
    

     测试

    if __name__ == '__main__':
        
        ZhangSan = Customer('张三',1200)  #有1200积分的张三去超市买东西
        item1 = Item('卫生纸', 20, 10)
        item2 = Item('玩偶', 100, 2)
        item3 = Item('牛奶', 50, 4)
        
        order = Order(ZhangSan, BonusPointPromo())
        order.add_to_cart(item1, item2, item3)
        pay1 = order.pay()
        
        order = Order(ZhangSan, BulkPromo())
        order.add_to_cart(item1, item2, item3)
        pay2 = order.pay()
        
        order = Order(ZhangSan, LargeOrderPromo())
        order.add_to_cart(item1, item2, item3)
        pay3 = order.pay()

    结果如下: 

    展开全文
  • 策略模式:定义一系列算法,把它们一一封装起来,并且使它们之间可以相互替换。此模式让算法的变化不会影响到使用算法的客户。 电商领域有个使用“策略”模式的经典案例,即根据客户的属性或订单中的商品计算折扣。 ...
  • python策略模式

    2022-06-28 19:12:20
    策略模式。抽空学习下常见的20几种设计模式,python2.7来设计实现。基本就根据某设计模式书籍来实现python版本。希望能坚持下来全部介绍完。

    【python】策略模式

    【python】简单工厂模式
    【python】策略模式



    摘要

    抽空学习下常见的20几种设计模式,python2.7来设计实现。基本就根据某设计模式书籍来实现python版本。希望能坚持下来全部介绍完。设计模式介绍中可能会涉及到一些UML类图,忘了的可以看一下https://blog.csdn.net/zhaxun/article/details/124048871


    一、策略模式的官方解释

    策略模式作为一种软件设计模式,指对象有某个行为,但是在不同的场景中,该行为有不同的实现算法。比如每个人都要“交个人所得税”,但是“在美国交个人所得税”和“在中国交个人所得税”就有不同的算税方法。
    策略模式:
    定义了一组算法(业务规则);
    封装了每个算法;
    这族的算法可互换代替(interchangeable)。

    二、私人解释

    策略模式就是用来封装算法的,就像待会举例的get_result(),把不同策略的算法统一起来。

    三、优缺点

    优点
    1、 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
    2、 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
    3、 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。
    缺点
    1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道所有的算法或行为的情况。
    2、 策略模式造成很多的策略类,每个具体策略类都会产生一个新类。

    四、图与代码

    学习了简单工厂模式以后 我们先来简单复习一下。
    商场需要一个收银软件,营业员根据不同折扣模式来进行收费,例如有正常收费,打折收费,满减收费三种,请利用简单工厂模式设计实现。

    1.简单工厂的回顾

    1.UML类图

    在这里插入图片描述

    2.python代码

    代码如下:

    # encoding: utf-8
    import math
    
    
    # 现金收费基类
    class CashSuper(object):
        def accept_cash(self, money):
            raise NotImplementedError
    
    
    # 正常收费子类
    class CashNormal(CashSuper):
        def accept_cash(self, money):
            return money
    
    
    # 打折收费子类
    class CashRebate(CashSuper):
        def __init__(self, rebate=1.0):
            self._rebate = rebate
    
        def accept_cash(self, money):
            return money * self._rebate
    
    
    # 返利收费子类
    class CashReturn(CashSuper):
        def __init__(self, condition=0, money_return=0):
            self._condition = condition
            self._return = money_return
    
        def accept_cash(self, money):
            result = money
            if money >= self._condition:
                result = money - math.floor(money / self._condition) * self._return
            return result
    
    
    # 现金收费工厂类
    class CashFactory(object):
        @staticmethod
        def create_cash_accept(cash_type):
            cash_type_instance = None
            if cash_type == '正常收费':
                cash_type_instance = CashNormal()
            elif cash_type == '打8折':
                cash_type_instance = CashRebate(0.8)
            elif cash_type == '满300返100':
                cash_type_instance = CashReturn(300, 100)
            return cash_type_instance
    
    
    if __name__ == '__main__':
        print CashFactory.create_cash_accept('正常收费').accept_cash(400)
        print CashFactory.create_cash_accept('打8折').accept_cash(400)
        print CashFactory.create_cash_accept('满300返100').accept_cash(400)
    

    2.策略模式

    1.UML类图

    在这里插入图片描述

    2.python代码

    代码如下:

    # encoding: utf-8
    import math
    
    
    # 现金收费基类
    class CashSuper(object):
        def accept_cash(self, money):
            raise NotImplementedError
    
    
    # 正常收费子类
    class CashNormal(CashSuper):
        def accept_cash(self, money):
            return money
    
    
    # 打折收费子类
    class CashRebate(CashSuper):
        def __init__(self, rebate=1.0):
            self._rebate = rebate
    
        def accept_cash(self, money):
            return money * self._rebate
    
    
    # 返利收费子类
    class CashReturn(CashSuper):
        def __init__(self, condition=0, money_return=0):
            self._condition = condition
            self._return = money_return
    
        def accept_cash(self, money):
            result = money
            if money >= self._condition:
                result = money - math.floor(money / self._condition) * self._return
            return result
    
    
    # 上下文类,维护一个对收费模型的引用
    class CashContext(object):
        def __init__(self, cash_type_instance):
            self.cash_type_instance = cash_type_instance
    
        def get_result(self, money):
            return self.cash_type_instance.accept_cash(money)
    
    
    if __name__ == '__main__':
        def init_cash_accept(cash_type):
            cash_content = None
            if cash_type == '正常收费':
                cash_content = CashContext(CashNormal())
            elif cash_type == '打8折':
                cash_content = CashContext(CashRebate(0.8))
            elif cash_type == '满300返100':
                cash_content = CashContext(CashReturn(300, 100))
            return cash_content
    
        print init_cash_accept('正常收费').get_result(400)
        print init_cash_accept('打8折').get_result(400)
        print init_cash_accept('满300返100').get_result(400)
    
    

    单纯用策略模式,客户端需要去判断具体选哪种算法,这里我们把策略模式和简单工厂相互结合一下。

    代码如下:

    # encoding: utf-8
    import math
    
    
    # 现金收费基类
    class CashSuper(object):
        def accept_cash(self, money):
            raise NotImplementedError
    
    
    # 正常收费子类
    class CashNormal(CashSuper):
        def accept_cash(self, money):
            return money
    
    
    # 打折收费子类
    class CashRebate(CashSuper):
        def __init__(self, rebate=1.0):
            self._rebate = rebate
    
        def accept_cash(self, money):
            return money * self._rebate
    
    
    # 返利收费子类
    class CashReturn(CashSuper):
        def __init__(self, condition=0, money_return=0):
            self._condition = condition
            self._return = money_return
    
        def accept_cash(self, money):
            result = money
            if money >= self._condition:
                result = money - math.floor(money / self._condition) * self._return
            return result
    
    
    # 上下文类,维护一个对收费模型的引用
    class CashContext(object):
        def __init__(self, cash_type):
            self._cash_type = cash_type
            self.cash_type_instance = None
            self.init_cash_accept()
    
        def init_cash_accept(self):
            if self._cash_type == '正常收费':
                self.cash_type_instance = CashNormal()
            elif self._cash_type == '打8折':
                self.cash_type_instance = CashRebate(0.8)
            elif self._cash_type == '满300返100':
                self.cash_type_instance = CashReturn(300, 100)
    
        def get_result(self, money):
            return self.cash_type_instance.accept_cash(money)
    
    
    if __name__ == '__main__':
        print CashContext('正常收费').get_result(400)
        print CashContext('打8折').get_result(400)
        print CashContext('满300返100').get_result(400)
    

    总结

    简单工厂模式和策略模式的形式很像,对比一下上面两张UML类图可以知道,工厂Factory对CashSuper持有依赖关系,策略Context对CashSuper持有的是聚合关系。在对比客户端代码。简单工厂模式要让客户端认识CashFactory和CashSuper两个类,而策略模式只需要暴露给客户端CashContext一个类即可,客户端实例化CashContext对象,调用get_result方法,使得具体的收费算法彻底和客户端分离。

    # 简单工厂
    if __name__ == '__main__':
        print CashFactory.create_cash_accept('正常收费').accept_cash(400)
        print CashFactory.create_cash_accept('打8折').accept_cash(400)
        print CashFactory.create_cash_accept('满300返100').accept_cash(400)
    # 策略
    if __name__ == '__main__':
        print CashContext('正常收费').get_result(400)
        print CashContext('打8折').get_result(400)
        print CashContext('满300返100').get_result(400)
    

    但是话说回来,在CashContext中,还是有需要if和else判断类型,增加策略,就得增加elif。或许会有什么更好的方法等着我们。听说反射技术是个不错的选择,等后续介绍吧。

    展开全文
  • python策略模式

    2019-01-05 11:18:19
    #策略模式 class Strategy(): def process(self): pass class FaultStrategy(Strategy): def process(self): print("fault") class NormalStrategy(Strategy): def process(self): ...
    #策略模式
    class Strategy():
        def process(self):
            pass
    class FaultStrategy(Strategy):
        def process(self):
            print("fault")
    class NormalStrategy(Strategy):
        def process(self):
            print("normal")
    class Park():
        def __init__(self,strategy):
            self.__strategy=strategy
        def geoProcess(self):
            self.__strategy.process()
    p=Park(NormalStrategy())
    p.geoProcess()
    p=Park(FaultStrategy())
    p.geoProcess()
    

    在这里插入图片描述

    展开全文
  • 主要介绍了Python设计模式编程中观察者模式与策略模式的运用,观察者模式和策略模式都可以归类为结构型的设计模式,需要的朋友可以参考下
  • Python设计模式:策略模式

    万次阅读 2020-01-25 06:52:23
    设计模式十六:策略模式 什么是策略模式 鼓励使用多种算法来解决一个问题,其杀手级特性是能够在运行的时候透明地切换算法。 如果有两种算法,其中一种少量输入效果好,另一种对大量输入效果好, 则可以使用策略莫斯...
  • 原文取自大话设计模式,不同之处在于原文是基于C#编写的,这里用Python表述 需求:使用python语言开发实现一个商场消费打折、优惠活动,保证其可扩展性 初学者代码如下: # if __name__ == "__main__": # print...
  • 设计模式(python实现):策略模式
  • Python设计模式--策略模式

    千次阅读 2017-11-07 21:07:48
    例如策略模式,利用作为一等对象的函数,使用函数可以有效减少代码行数。例子:处理订单折扣电商领域有个功能明显可以使用“策略”模式,即根据客户的属性或订单中的商品计算折 扣。假如一个网店制定了下述折扣规则...
  • python 实现 策略模式

    千次阅读 2018-07-05 17:23:55
    Python的sorted()和list.sort()函数是策略模式的例子。两个函数都接受一个命名参数key,这个参数本质上是实现了一个排序策略的函数的名称。 下面的例子(代码文件 langs.py )展示了如何用以下方式使用两种不同的...
  • Python中的策略模式-电商大促销

    千次阅读 2021-03-18 09:56:39
    前言设计模式是我们实际应用开发中必不可缺的,对设计模式的理解有助于我们写出可读性和扩展更高的应用...对于Python来说就相对要少很多,特别是python语言具有很多高级的特性,而不需要了解这些照样能满足开发中...
  • Python设计模式之策略模式

    千次阅读 2017-11-14 09:18:10
    前言设计模式是我们实际应用开发中必不可缺的,对设计模式的理解有助于我们写出可读性和扩展更高的应用程序...对于Python来说就相对要少很多,特别是python语言具有很多高级的特性,而不需要了解这些照样能满足开发中的
  • 模式特点:定义算法家族并且分别封装,它们之间可以相互替换而不影响客户端。 程序实例:商场收银软件,需要根据不同的销售策略方式进行收费 代码特点:不同于同例1,这里使用字典是为了避免关键字不在字典导致bug的...
  • Python 使用函数实现策略模式原文地址:Python 使用函数实现策略模式
  • Python常用的设计模式

    千次阅读 多人点赞 2022-07-21 20:02:11
    抽象工厂模式和建造者模式相比于简单工厂模式和工厂方法模式而言更加灵活也更加复杂。通常情况下,软件设计以简单工厂模式或工厂方法模式开始,当发现设计需要更大的灵活性的时候,则向更加复杂的设计模式演化。.......
  • 设计模式之策略模式python实现)

    千次阅读 2012-08-10 23:19:57
     下面将要介绍的就是书中的第一个设计模式:策略模式 书中以模拟鸭子应用问题作为实例,一款游戏应用中要求有各种各样的鸭子。  先用继承来实现了这一个应用,其设计如下:  这个设计主要是以Du
  • 替代 if else ---策略模式

    万次阅读 2021-05-17 18:24:16
    替代 if else ---策略模式什么是策略模式策略模式的优点策略模式的缺点:策略模式实战1.定义策略接口策略接口订单信息类返回结果类2.定义各种策略微信支付实现支付宝实现云闪付实现3.使用策略测试一下: 什么是...
  • python设计模式策略、观察者、责任链、模板、代理、享元、外观等。 地址位于README.txt内的百度网盘内。
  • python设计模式

    2021-12-26 15:18:00
    python设计模式 ...行为型模式(11种):解释器模式、责任链模式、命令模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、访问者模式、模版方法模式 提示:以下是本篇文章正文内
  • 设计模式专题之(十六)策略模式---设计模式策略模式示例代码(python--c++)
  • python策略模式

    2016-09-14 20:37:44
    转载自 http://www.imooc.com/article/5039 我的理解是:1、不用if else做一些事  2、把行为和人分开来 其它没有了,目前还没办法做进一步的总结。
  • 3.9策略模式 3.10模板方法模式 3.11访问者模式 3.12案例研究:图像处理程序包 3.12.1通用的图像处理模块 3.12.2Xpm模块概述 3.12.3PNG包装器模块 第4章Python的高级并发技术 4.1计算密集型并发 4.1.1用队列...
  • 文章目录目录策略模式应用场景代码示例 策略模式 策略模式中,首先定义了一系列不同的算法,并把它们一一封装起来,然后在策略类中,使这些算法可以相互替换。 优点: 定义了一系列可重用的算法和行为。 消除了一些...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 81,078
精华内容 32,431
关键字:

python策略模式

友情链接: XMLClass.rar