Java设计模式之策略模式

来源:互联网 发布:波奇 假货 知乎 编辑:程序博客网 时间:2024/05/05 12:37

Java设计模式之策略模式

  • Java设计模式之策略模式
    • 模式定义
    • 关键词
    • 使用场景
    • 举个例子
    • 模式深入
      • 优缺点
        • 优点
        • 缺点
      • 体现的多态思想
      • 策略模式的重心
      • 算法的平等性与唯一性
    • Java中的应用
    • 总结

模式定义

策略模式,行为模式的一种,针对一组算法,将每一个算法封装到具有共同接口(也可能是共同的抽象类)的独立类,从而使它们可以相互替换。

关键词

  • 一组算法,对象的某个属性针对不同操作可能有不同的赋值方式(如下例中图书价格的计算方式因会员等级而异)
  • 共同接口(共同抽象类),不同算法能够相互替换的保障

使用场景

某个对象(如图书)的一些属性(如ISBN号)不变,但某些属性(如价格)是容易变化的,且该属性(价格)针对不同情况有不同的表现形式(不同的会员等级计算方式不一样)。对于这个容易变化的属性(如价格),我们不希望将其与图书这个对象绑定,而是希望图书能与计算价格的策略进行绑定。这种情形就是策略模式的体现了。也就是说策略模式是为了处理对象复杂多变的行为的。

举个例子

图书销售终端,计价策略:

  • 初级会员,无折扣
  • 中级会员,九折
  • 高级会员,不折

现在一个高级会员购买一本售价为50元的书,具体代码实现:

定义共同接口(会员计价策略抽象接口)

package com.rainmonth.pattern.behavioral.strategy.book;/** * 会员计价策略接口 * Created by RandyZhang on 2017/10/19. */public interface MemberStrategy {    /**     * 计算书籍实际销售价格     *     * @param bookSalePrice 书籍销售价格     * @return 实际售价     */    public double calculateActualSalePrice(double bookSalePrice);}

初级会员计价策略

package com.rainmonth.pattern.behavioral.strategy.book;/** * 初级会员销售策略 * Created by RandyZhang on 2017/10/19. */public class PrimaryMemberStrategy implements MemberStrategy {    @Override    public double calculateActualSalePrice(double bookSalePrice) {        System.out.println("初级会员没有折扣");        return bookSalePrice;    }}

中级会员计价策略

package com.rainmonth.pattern.behavioral.strategy.book;/** * 中级会员销售策略 * Created by RandyZhang on 2017/10/19. */public class IntermediateMemberStrategy implements MemberStrategy{    @Override    public double calculateActualSalePrice(double bookSalePrice) {        System.out.println("中级会员打九折");        return bookSalePrice * 0.9;    }}

高级会员计价策略

package com.rainmonth.pattern.behavioral.strategy.book;/** * 高级会员销售策略 * Created by RandyZhang on 2017/10/19. */public class AdvanceMemberStrategy implements MemberStrategy{    @Override    public double calculateActualSalePrice(double bookSalePrice) {        System.out.println("高级会员打八折");        return bookSalePrice * 0.9;    }}

销售终端(实际调用)

package com.rainmonth.pattern.behavioral.strategy.book;/** * 销售终端 * Created by RandyZhang on 2017/10/19. */public class SaleClient {    public static void main(String[] args) {        // 知道当前顾客是高级会员        MemberStrategy advanceStrategy = new AdvanceMemberStrategy();        // 获取他要购买的书        BookEntity bookEntity = new BookEntity(advanceStrategy);        // 获取卖给该会员的实际价格        double actualSalePrice = bookEntity.getBookActualSalePrice(50);        System.out.println("actualSalePrice=" + actualSalePrice);    }}

最终输出

高级会员打八折actualSalePrice=45.0

模式深入

优缺点

根据上面的例子,可以总结出策略模式的优缺点。

优点

  • 不同等级的计算策略容易管理。(我们可以很容易的新增或改变计算策略)
  • 避免了多重if-else的判断(不用策略模式的话单纯使用if-else不易维护)

缺点

  • 如果策略增多,策略对应的类就增多;
  • 调用策略的人必须对所有策略烂熟于心,并且要知道什么时候调用什么策略。(有一定局限性,因为调用的客户段必须知道什么情形下采用什么策略)。

体现的多态思想

BookEntity持有MemberStrategy对象引用,在生成对象实例时,将其赋值为具体的子策略对象从而调用子策略对象中的策略方法,这就是多态的体现。

策略模式的重心

设计模式的产生很大程度上都是为了代码好维护、易扩展,这些都需要在代码的组织上下功夫,因此策略模式的重心不在算法的实现上(当然实现也很重要哦),而在算法的组织上。

算法的平等性与唯一性

平等性是说,每种策略都是平等的,被调用的优先级都是相同的,只要符合调用条件(如会员等级对应就可以调用);

唯一性是说,计算的时候,只可能使用其中的一种策略

Java中的应用

File类里面有个list方法,用来列出目录里面的所有文件,这是基本功能,但如果我们想获取目录里面某种规则的文件(如以.java结尾的文件)我们怎么办呢?Java I/O为我们提供了FilenameFilter这个接口,就文件名过滤。我们自定义一个类实现该接口就可以实现不同文件名的过滤(如JavaSuffixFilter、TxtSuffixFilter等),这就是策略模式的在Java I/O设计上的一个小小应用。

总结

对于策略模式,要牢记起关键词:一组算法和共同接口(共同抽象类),因为策略模式简单来说就是“准备一组算法,并将每个算法封装起来,使得它们可以互换(取代)”。