• 算法的封装与切换—策略模式(一)


    俗话说:条条大路通罗马。在很多情况下,实现某个目标的途径不止一条,例如我们在外 出旅游时可以选择多种不同的出行方式,如骑自行车、坐汽车、坐火车或者坐飞机,可根据实际情况(目的地、旅游预算、旅游时间等)来选择一种最适合的出行方 式。在制订旅行计划时,如果目的地较远、时间不多,但不差钱,可以选择坐飞机去旅游;如果目的地虽远、但假期长、且需控制旅游成本时可以选择坐火车或汽 车;如果从健康和环保的角度考虑,而且有足够的毅力,自行车游或者徒步旅游也是个不错的选择,大笑

          在软件开发中,我们也常常会遇到类似的情况,实现某一个功能有多条途径,每一条途径对应一种算法,此时我们可以使用一种设计模式来实现灵活地选择解决途径,也能够方便地增加新的解决途径。本章我们将介绍一种为了适应算法灵活性而产生的设计模式——策略模式

     

    24.1 电影票打折方案

          Sunny软件公司为某电影院开发了一套影院售票系统,在该系统中需要为不同类型的用户提供不同的电影票打折方式,具体打折方案如下:

          (1) 学生凭学生证可享受票价8折优惠;

          (2) 年龄在10周岁及以下的儿童可享受每张票减免10元的优惠(原始票价需大于等于20元);

          (3) 影院VIP用户除享受票价半价优惠外还可进行积分,积分累计到一定额度可换取电影院赠送的奖品。

          该系统在将来可能还要根据需要引入新的打折方式。

          为了实现上述电影票打折功能,Sunny软件公司开发人员设计了一个电影票类MovieTicket,其核心代码片段如下所示:

    1. //电影票类  
    2. class MovieTicket  
    3.     private double price; //电影票价格  
    4.     private String type; //电影票类型  
    5.       
    6.     public void setPrice(double price)  
    7.         this.price price;  
    8.      
    9.       
    10.     public void setType(String type)  
    11.         this.type type;  
    12.      
    13.       
    14.     public double getPrice()  
    15.         return this.calculate();  
    16.      
    17.       
    18.          //计算打折之后的票价  
    19.     public double calculate()  
    20.                   //学生票折后票价计算  
    21.         if(this.type.equalsIgnoreCase("student"))  
    22.             System.out.println("学生票:");  
    23.             return this.price 0.8 
    24.          
    25.                   //儿童票折后票价计算  
    26.         else if(this.type.equalsIgnoreCase("children"&& this.price >= 20  
    27.             System.out.println("儿童票:");  
    28.             return this.price 10 
    29.          
    30.                   //VIP票折后票价计算  
    31.         else if(this.type.equalsIgnoreCase("vip"))  
    32.             System.out.println("VIP票:");  
    33.             System.out.println("增加积分!");  
    34.             return this.price 0.5 
    35.          
    36.         else  
    37.             return this.price; //如果不满足任何打折要求,则返回原始票价  
    38.          
    39.      
    40.  

          编写如下客户端测试代码:

    1. class Client  
    2.     public static void main(String args[])  
    3.         MovieTicket mt new MovieTicket();  
    4.         double originalPrice 60.0//原始票价  
    5.         double currentPrice; //折后价  
    6.           
    7.         mt.setPrice(originalPrice);  
    8.         System.out.println("原始价为:" originalPrice);  
    9.         System.out.println("---------------------------------");  
    10.               
    11.         mt.setType("student"); //学生票  
    12.         currentPrice mt.getPrice();  
    13.         System.out.println("折后价为:" currentPrice);  
    14.         System.out.println("---------------------------------");  
    15.           
    16.         mt.setType("children"); //儿童票  
    17.         currentPrice mt.getPrice();  
    18.         System.out.println("折后价为:" currentPrice);  
    19.      
    20.  

          编译并运行程序,输出结果如下所示:

    原始价为:60.0

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

    学生票:

    折后价为:48.0

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

    儿童票:

    折后价为:50.0

          通过MovieTicket类实现了电影票的折后价计算,该方案解决了电影票打折问题,每一种打折方式都可以称为一种打折算法,更换打折方式只需修改客户端代码中的参数,无须修改已有源代码,但该方案并不是一个完美的解决方案,它至少存在如下三个问题:

          (1) MovieTicket类的calculate()方法非常庞大,它包含各种打折算法的实现代码,在代码中出现了较长的if…else…语句,不利于测试和维护

          (2) 加新的打折算法或者对原有打折算法进行修改时必须修改MovieTicket类的源代码,违反了“开闭原则”,系统的灵活性和可扩展性较差。

          (3) 法的复用性差,如果在另一个系统(如商场销售管理系统)中需要重用某些打折算法,只能通过对源代码进行复制粘贴来重用,无法单独重用其中的某个或某些算法(重用较为麻烦)。

          如何解决这三个问题?导致产生这些问题的主要原因在于MovieTicket类职责过重,它将各种打折算法都定义在一个类中,这既不便于算法的重用,也不便于算法的扩展。因此我们需要对MovieTicket类进行重构,将原本庞大的MovieTicket类的职责进行分解,将算法的定义和使用分离,这就是策略模式所要解决的问题,下面将进入策略模式的学习。

    【作者:刘伟 http://blog.csdn.net/lovelion

  • 相关阅读:
    socket.io带中文时客户端无法响应
    JQ树插件 — zTree笔记
    cecium 笔记
    express处理跨域问题,中间件 CORS
    一些接口
    express 3.5 Err: request aborted
    ovirt kvm嵌套虚拟化
    kvm实现快速增量盘模式的克隆脚本
    kvm命令
    kvm 中 Guest Is already in use 处理办法
  • 原文地址:https://www.cnblogs.com/luckForever/p/7254753.html
Copyright © 2020-2023  润新知