策略模式(Strategy) 1

来源:互联网 发布:java子类重写父类权限 编辑:程序博客网 时间:2024/06/06 01:52

1  场景问题

1.1  报价管理

        向客户报价,对于销售部门的人来讲,这是一个非常重大、非常复杂的问题,对不同的客户要报不同的价格,比如:
  • 对普通客户或者是新客户报的是全价
  • 对老客户报的价格,根据客户年限,给予一定的折扣
  • 对大客户报的价格,根据大客户的累计消费金额,给予一定的折扣
  • 还要考虑客户购买的数量和金额,比如:虽然是新用户,但是一次购买的数量非常大,或者是总金额非常高,也会有一定的折扣
  • 还有,报价人员的职务高低,也决定了他是否有权限对价格进行一定的浮动折扣
        甚至在不同的阶段,对客户的报价也不同,一般情况是刚开始比较高,越接近成交阶段,报价越趋于合理。 
        总之,向客户报价是非常复杂的,因此在一些CRM(客户关系管理)的系统中,会有一个单独的报价管理模块,来处理复杂的报价功能。 
        为了演示的简洁性,假定现在需要实现一个简化的报价管理,实现如下的功能: 
           (1)对普通客户或者是新客户报全价 
           (2)对老客户报的价格,统一折扣5% 
           (3)对大客户报的价格,统一折扣10% 
        该怎么实现呢?

1.2  不用模式的解决方案

        要实现对不同的人员报不同的价格的功能,无外乎就是判断起来麻烦点,也不多难,很快就有朋友能写出如下的实现代码,示例代码如下:
 
 
/**
价格管理,主要完成计算向客户所报价格的功能
*/
public class Price {
    /**
    * 报价,对不同类型的,计算不同的价格
    * @param goodsPrice 商品销售原价
    * @param customerType 客户类型
    * @return 计算出来的,应该给客户报的价格
    */
    public double quote(double goodsPrice,String customerType){
       if(customerType.equals("普通客户 ")){
           System.out.println("对于新客户或者是普通客户,没有折扣 ");
           return goodsPrice;
       }else if(customerType.equals("老客户 ")){
           System.out.println("对于老客户,统一折扣 5%");
           return goodsPrice*(1-0.05);
       }else if(customerType.equals("大客户 ")){
           System.out.println("对于大客户,统一折扣 10%");
           return goodsPrice*(1-0.1);        
       }
       //其余人员都是报原价
       return goodsPrice;
    }
}
 

1.3  有何问题

        上面的写法是很简单的,也很容易想,但是仔细想想,这样实现,问题可不小,比如:
  • 第一个问题:价格类包含了所有计算报价的算法,使得价格类,尤其是报价这个方法比较庞杂,难以维护。
        有朋友可能会想,这很简单嘛,把这些算法从报价方法里面拿出去,形成独 立的方法不就可以解决这个问题了吗?据此写出如下的实现代码,示例代码如下:
 
 
/**
价格管理,主要完成计算向客户所报价格的功能
*/
public class Price {
    /**
    * 报价,对不同类型的,计算不同的价格
    * @param goodsPrice 商品销售原价
    * @param customerType 客户类型
    * @return 计算出来的,应该给客户报的价格
    */
    public double quote(double goodsPrice,String customerType){
       if(customerType.equals("普通客户 ")){
           return this.calcPriceForNormal(goodsPrice);
       }else if(customerType.equals("老客户 ")){
           return this.calcPriceForOld(goodsPrice);
       }else if(customerType.equals("大客户 ")){
           return this.calcPriceForLarge(goodsPrice);       
       }
       //其余人员都是报原价
       return goodsPrice;
    }
    /**
    * 为新客户或者是普通客户计算应报的价格
    * @param goodsPrice 商品销售原价
    * @return 计算出来的,应该给客户报的价格
    */
    private double calcPriceForNormal(double goodsPrice){
       System.out.println("对于新客户或者是普通客户,没有折扣 ");
       return goodsPrice;
    }
    /**
    * 为老客户计算应报的价格
    * @param goodsPrice 商品销售原价
    * @return 计算出来的,应该给客户报的价格
    */
    private double calcPriceForOld(double goodsPrice){
       System.out.println("对于老客户,统一折扣 5%");
       return goodsPrice*(1-0.05);
    }
    /**
    * 为大客户计算应报的价格
    * @param goodsPrice 商品销售原价
    * @return 计算出来的,应该给客户报的价格
    */
    private double calcPriceForLarge(double goodsPrice){
       System.out.println("对于大客户,统一折扣 10%");
       return goodsPrice*(1-0.1); 
    }
}
 
        这样看起来,比刚开始稍稍好点,计算报价的方法会稍稍简单一点,这样维护起来也稍好一些,某个算法发生了变化,直接修改相应的私有方法就可以了。扩展起来也容易一点,比如要增加一个“战略合作客户”的类型,报价为直接8折,就只需要在价格类里面新增加一个私有的方法来计算新的价格,然后在计算报价的方法里面新添一个else-if即可。看起来似乎很不错了。 
        真的很不错了吗? 
        再想想,问题还是存在,只不过从计算报价的方法挪动到价格类里面了,假如有100个或者更多这样的计算方式,这会让这个价格类非常庞大,难以维护。而且,维护和扩展都需要去修改已有的代码,这是很不好的,违反了开-闭原则。
 
  • 第二个问题:经常会有这样的需要,在不同的时候,要使用不同的计算方式。
        比如:在公司周年庆的时候,所有的客户额外增加3%的折扣;在换季促销的时候,普通客户是额外增加折扣2%,老客户是额外增加折扣3%,大客户是额外增加折扣5%。这意味着计算报价的方式会经常被修改,或者被切换。 
        通常情况下应该是被切换,因为过了促销时间,又还回到正常的价格体系上来了。而现在的价格类中计算报价的方法,是固定调用各种计算方式,这使得切换调用不同的计算方式很麻烦,每次都需要修改if-else里面的调用代码。 
        看到这里,可能有朋友会想, 那么到底应该如何实现,才能够让价格类中的计算报价的算法,能很容易的实现可维护、可扩展,又能动态的切换变化呢?


---------------------------------------------------------------------------

私塾在线学习网原创内容  跟着cc学设计系列 之 研磨设计模式

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/90.html】

---------------------------------------------------------------------------


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 qq音乐停止运行怎么办 做事效率低怎么办教案 孩子做事效率低怎么办 百度搜不到答案怎么办 学乐云账号忘了怎么办 wps云空间不足怎么办 超星密码忘了怎么办 百度钱包忘记密码怎么办 宝宝吃了粉笔怎么办 粉笔灰进眼睛怎么办 讲公开课紧张怎么办 课堂派考勤旷课怎么办 2018qq音乐付费怎么办 不满一个月社保怎么办 试用期未买社保怎么办 小视频转发黑屏怎么办 听歌要钱的怎么办 手机歌曲要付费怎么办 安装包已损坏怎么办 方舟 安装包损坏怎么办 安装包已删除怎么办 超大附件过期了怎么办 邮箱被黑客盯上怎么办 云闪付安全问题忘记了怎么办 不知道网易账号怎么办 登录过程初始化失败怎么办 登录进程初始化失败怎么办 网易邮箱地址忘了怎么办 电脑电源短路了怎么办 电脑电源有问题怎么办 手机账号忘了怎么办 简历周五发了怎么办 网易邮箱被注销怎么办 foxmail接收密码忘记怎么办 招才猫企业邮箱认证没有怎么办 管理员账号被删除怎么办 我想办个信用卡怎么办 qq邮箱支付宝怎么办 12306忘记了邮箱怎么办 12306邮箱被占用怎么办 xp不能安装软件怎么办