文档章节

研磨设计模式之 策略模式-1

We911
 We911
发布于 2017/02/08 10:12
字数 1645
阅读 1
收藏 0

研磨设计模式之 策略模式-1

首先感谢众多朋友的支持、评论和鼓励,只有多多努力,写点好的博文来回报大家的好意! 

接下来想写写另外一个虽然较简单,但是使用很频繁的模式——策略模式

 

策略模式(Strategy)

1  场景问题

1.1  报价管理

        向客户报价,对于销售部门的人来讲,这是一个非常重大、非常复杂的问题,对不同的客户要报不同的价格,比如:

 

  (1)对普通客户或者是新客户报的是全价

  (2)对老客户报的价格,根据客户年限,给予一定的折扣

  (3)对大客户报的价格,根据大客户的累计消费金额,给予一定的折扣

  (4)还要考虑客户购买的数量和金额,比如:虽然是新用户,但是一次购买的数量非常大,或者是总金额非常高,也会有一定的折扣 

  (5)还有,报价人员的职务高低,也决定了他是否有权限对价格进行一定的浮动折扣

 

        甚至在不同的阶段,对客户的报价也不同,一般情况是刚开始比较高,越接近成交阶段,报价越趋于合理。
        总之,向客户报价是非常复杂的,因此在一些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  有何问题

        上面的写法是很简单的,也很容易想,但是仔细想想,这样实现,问题可不小,比如:

  (1)第一个问题:价格类包含了所有计算报价的算法,使得价格类,尤其是报价这个方法比较庞杂,难以维护。

        有朋友可能会想,这很简单嘛,把这些算法从报价方法里面拿出去,形成独立的方法不就可以解决这个问题了吗?据此写出如下的实现代码,示例代码如下: 

/**

 * 价格管理,主要完成计算向客户所报价格的功能

 */

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个或者更多这样的计算方式,这会让这个价格类非常庞大,难以维护。而且,维护和扩展都需要去修改已有的代码,这是很不好的,违反了开-闭原则。 

 

  (2)第二个问题:经常会有这样的需要,在不同的时候,要使用不同的计算方式。

        比如:在公司周年庆的时候,所有的客户额外增加3%的折扣;在换季促销的时候,普通客户是额外增加折扣2%,老客户是额外增加折扣3%,大客户是额外增加折扣5%。这意味着计算报价的方式会经常被修改,或者被切换。
        通常情况下应该是被切换,因为过了促销时间,又还回到正常的价格体系上来了。而现在的价格类中计算报价的方法,是固定调用各种计算方式,这使得切换调用不同的计算方式很麻烦,每次都需要修改if-else里面的调用代码。
        看到这里,可能有朋友会想,那么到底应该如何实现,才能够让价格类中的计算报价的算法,能很容易的实现可维护、可扩展,又能动态的切换变化呢?

  

  

 

未完待续......

本文转载自:http://blog.csdn.net/liduanw/article/details/8192923

共有 人打赏支持
We911
粉丝 1
博文 63
码字总数 0
作品 0
深圳
程序员
编程中的那些套路——关于策略模式

该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天讲讲策略模式,策略模式 和工厂模式十分相像(或者说在代码逻辑层面,他们是一样的)。 但策略模式与...

gzchen
08/27
0
0
代理模式(Proxy Pattern):动态代理 - 最易懂的设计模式解析

前言 今天我来全面总结开发中最常用的设计模式 - 代理模式中的动态代理模式 其他设计模式介绍 1分钟全面了解“设计模式” 单例模式(Singleton) - 最易懂的设计模式解析 简单工厂模式(Sim...

Carson_Ho
04/09
0
0
javascript 设计模式之工厂(Factory)模式

工厂模式介绍 工厂模式是一个创建型的模式,主要就是创建对象。其中工厂模式又分为简单工厂模式和抽象工厂模式。简单工厂模式是通过工厂方法确定创建 对应类型的对象。抽象工厂模式是通过子类...

hlxiong
2014/04/14
0
0
设计模式-工厂模式/委派模式/代理模式/单例模式

1.工厂模式:spring中运用的都是工厂模式,不参与业务的枚举就是工厂模式,所有人均可以调用,工厂模式就是在底层框架中写好. 例如:new 了一个Map 那这个Map创造的过程其实是底层工厂模式代码创造...

森火
09/11
0
0
编程中的那些经典套路——设计模式汇总

在正式阅读前,我先谈谈我们该用什么姿势和心态学习设计模式: 如果你还没有过多的编程经验(泛指半年以下),我建议你把它当做小说来看,能看懂多少是多少,因为半年以下经验的程序员用到设...

gzchen
08/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

权限框架Shiro学习之表结构设计

权限框架Shiro学习之表结构设计 Shiro是一款优秀的开源安全框架,学习Shiro大家可以参考张开涛老师的博客:跟我学Shiro,当然也可参考我之前的笔记:Shiro实现身份认证、Shiro实现授权。 在学...

TyCoding
25分钟前
1
0
find命令和文件名后缀

9月18日任务 2.23/2.24/2.25 find命令 2.26 文件名后缀 which which 搜索可执行文件,必须在PATH环境变量目录中!!否则无法搜到! [root@centos7 ~]# which lsalias ls='ls --color=auto'...

robertt15
28分钟前
1
0
阿里Java程序员必备的Intellij IDEA 插件

善用Intellij插件可大幅提升我们的效率,以下是我用过不错的Intellij插件,分享给大家希望能帮到大家。 1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 2. lom...

我是你大哥
38分钟前
1
0
为什么Java大神,都在看Spring Boot和Spring Cloud的书?

如果你是一名Java开发人员,并且最近正打算学习Spring Boot和Spring Cloud框架并寻找一些关于它们的最好的书籍,那么,你今天就来对地方了。 本文,我们将讨论一些学习Spring Boot和Spring ...

Java小铺
56分钟前
12
0
springboot logback日志配置

springboot 如果不使用外部tomcat的话,日志是需要自己配置的,不然的话就只有控制台的日志,但是日志又是我们在项目上了生产环境,出问题时,检查问题的唯一途径,所以我们要配置详细的日志...

曾大大胖
56分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部