案例分析:设计模式与代码的结构特性

蜗牛慢爬的李成广 2019-12-07

使用策略模式,用python实现一个淘宝优惠策略,输入原价,输出优惠之后的价格。

策略模式:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化,在对象中封装算法是策略模式的目的。

模式的主要参与者是策略对象(这些对象中封装了不同的算法)和它们的操作环境。

策略模式应用的关键点在于为策略和它的环境设计足够通用的接口,以支持一系列的算法。你不必为了支持一个新的算法而改变策略或它的环境。

需要换行功能的客户程序如果直接包含换行算法代码的话将会变得复杂,这使得客户程序庞大并且难以维护, 尤其当其需要支持多种换行算法时问题会更加严重。

不同的时候需要不同的算法,我们不想支持我们并不使用的换行算法。当换行功能是客户程序的一个难以分割的成分时 ,增加新的换行算法或改变现有算法将十分困难。

我们可以定义一些类来封装不同的换行算法,从而避免这些问题。一个以这种方法封装的算法称为一个策略。

存在以下情况时使用策略模式:

许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。

需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间/时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式。

算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。

一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的策略类中以代替这些条件语句。

双十一淘宝促销策略:

1:直接打折,原价300元,现价六折,180元销售,这种打折的方式是最简单明了的,消费者也很容易理解。

2:满减:满100元减40元,满200减90元,满300元减150元。

3:满150元,高于150元打5折。

类图如下:

案例分析:设计模式与代码的结构特性

使用抽象类,将IStrategy作为抽象类,构建了三个类,ReduceStrategy,RebateStrategy,PromotionalStrategy继承IStrategy,其中包括通过原价来计算优惠之后价格的realPrice方法和获得优惠策略名的strategyName方法。

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

抽象类往往用来表征对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。

构建了Context类,其中包含所使用的的是哪种策略的strategy属性,同时包含设置属性的setStrategy方法,和开始计算的cul方法。

构建了Client类,其中包括用户的名字的name属性和提供的原价price属性,同时包括设置name的setname方法,设置price的setprice方法和printResult方法输出结果。

各模块之前存在数据耦合,耦合度较低,存在顺序内聚,内聚度较高。

全部代码如下:

from abc import ABC, abstractmethod

class IStrategy(ABC):            
    @abstractmethod
    def realPrice(self, consumePrice):
        pass
    
    @abstractmethod
    def strategyName(self):
        pass
    
class RebateStrategy(IStrategy):    #6折商品促销策略
    @classmethod
    def realPrice(self, consumePrice):
        return consumePrice * 0.6

    def strategyName(self):
        return "RebateStrategy"

class PromotionalStrategy(IStrategy):  #150以上打5折商品促销策略
    @classmethod
    def realPrice(self, consumePrice):
        if consumePrice > 150:
            consumePrice = 150 + (consumePrice-150) * 0.5
        return consumePrice

    def strategyName(self):
        return "PromotionalStrategy"

class ReduceStrategy(IStrategy):  #满100元减40元,满200减90元,满300元减150元商品促销案策略
    @classmethod
    def realPrice(self, consumePrice):
        if consumePrice >= 100 and consumePrice < 200:
            consumePrice -= 40
        elif consumePrice >= 200 and consumePrice <300:
            consumePrice -= 90
        elif consumePrice >= 300:
            consumePrice -= 150
        return consumePrice

    def strategyName(self):
        return "ReduceStrategy"

class Context:
    def __init__(self, strategy = None):
        self.strategy = strategy

    def setStrategy(self, strategy):
        self.strategy = strategy

    def cul(self, consumePrice):
        realPrice = self.strategy.realPrice(consumePrice)
        print((‘打折策略:{}\n打折前:{}\n打折后:{}‘).format(self.strategy.strategyName(self), consumePrice, realPrice))

class Client:
    def __init__(self, name = None, price = None):
        self.name = name
        self.price = price
        
    def setname(self, name):
        self.name = name

    def setprice(self, price):
        self.price = price
    
    def printResult(self):
        print((‘用户名:{}‘).format(self.name))
        self.context = Context()
        self.context.setStrategy(RebateStrategy)
        self.context.cul(self.price)
        self.context.setStrategy(PromotionalStrategy)
        self.context.cul(self.price)
        self.context.setStrategy(ReduceStrategy)
        self.context.cul(self.price)
        
client = Client()
client.setname(‘Tom‘)
client.setprice(200)
client.printResult()

执行过程为:实例化一个Client类,对象名为client,使用Client的setname方法,设置name属性,通过setprice方法,设置price,最后使用printResult方法,输出结果。

代码:https://github.com/lc120798654/gaoruan

相关推荐

80374192 / 0评论 2017-02-06
Mr丶Yang / 0评论 2016-11-04