Java设计模式之策略模式

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设计上的一个小小应用。

总结

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

你可能感兴趣的:(Java基础)