策略模式

Posted 温布利往事

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了策略模式相关的知识,希望对你有一定的参考价值。

一、概念

  1、定义

  策略模式定义了一系列的算法,并将每一个算法封装起来,而且使他们可以相互替换。策略模式让算法独立于使用它的客户而独立变化。

  策略模式就要应对规则变化和新规则加入对程序带来的影响。

 

  通过接口可以避免直接调用规则,从而使得业务变化不会对规则产生影响,同时,添加新规则也不会影响业务流程。

  

  2、优点  

  • 策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码转移到父类里面,从而避免重复的代码。
  • 策略模式提供了可以替换继承关系的办法。继承可以处理多种算法或行为。如果不是用策略模式,那么使用算法或行为的环境类就可能会有一些子类,每一个子类提供一个不同的算法或行为。但是,这样一来算法或行为的使用者就和算法或行为本身混在一起。决定使用哪一种算法或采取哪一种行为的逻辑就和算法或行为的逻辑混合在一起,从而不可能再独立演化。继承使得动态改变算法或行为变得不可能。
  • 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重转移语句里面,比使用继承的办法还要原始和落后。

  3、应用场景

  •  多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
  • 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
  • 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。

二、策略模式组成

  策略模式通常包含下面三种角色:

  1、Context环境角色(应用场景)

  持有一个策略类的引用,需要使用ConcreteStrategy提供的算法,负责动态设置运行时Strategy具体的实现算法  

  2、Strategy抽象策略角色

  策略类,通常由一个接口或者抽象类实现,定义了一个公共接口,各种不同的算法以不同的方式实现这个接口,Context使用这个接口调用不同的算法,一般使用接口或抽象类实现。

  3、ConcreteStrategy具体策略角色

  包装了相关算法和行为,实现了Strategy定义的接口,提供具体的算法实现。

三、策略模式实现方式

  示例代码

  环境角色类

public class Context
{
    //持有一个具体策略的对象
    private Strategy strategy;
    /**
     * 构造函数,传入一个具体策略对象
     * @param strategy    具体策略对象
     */
    public Context(Strategy strategy)
    {
        this.strategy = strategy;
    }
    /**
     * 策略方法
     */
    public void contextInterface()
    {
        strategy.strategyInterface();
    }
}    

  抽象策略角色

public interface Strategy 
{
    //策略方法
    public void strategyInterface();
}

  具体策略角色

public class ConcreteStrategyA implements Strategy
{
    @Override
    public void strategyInterface() 
    {
        //相关的业务A
    }
}
public class ConcreteStrategyB implements Strategy
{
    @Override
    public void strategyInterface()
    {
        // 相关的业务B
    }
}

四、应用场景举例

  假设现在要设计一个购物车系统。该网站对所有的高级会员提供每本20%的促销折扣;对中级会员提供每本10%的促销折扣;对初级会员没有折扣。

  根据描述,折扣是根据以下的几个算法中的一个进行的:

  算法一:对初级会员没有折扣。

  算法二:对中级会员提供10%的促销折扣。

  算法三:对高级会员提供20%的促销折扣。

  1、折扣类(抽象策略角色)

public interface DiscountStrategy 
{
    /**
     * 计算图书的价格
     * @param booksPrice 图书的原价
     * @return    计算出打折后的价格
     */
    public double calcPrice(double booksPrice);
}

  2、价格类(Context环境角色类)

public class Price
{
    // 持有一个具体的策略对象
    private DiscountStrategy strategy;
    /**
     * @param strategy 具体的策略对象
     */
    public Price(DiscountStrategy strategy)
    {
        this.strategy = strategy;
    }
    /**
     * 计算图书的价格
     * 
     * @param booksPrice 图书的原价
     * @return 计算出打折后的价格
     */
    public double quote(double booksPrice)
    {
        return this.strategy.calcPrice(booksPrice);
    }
}

  3、具体策略角色

/**
 * 初级会员折扣
 */
public class PrimaryMemberStrategy implements DiscountStrategy
{
    @Override
    public double calcPrice(double booksPrice)
    {
        System.out.println("对于初级会员的没有折扣");
        return booksPrice;
    }
}
/*
 * 中级会员折扣
 */
public class IntermediateMemberStrategy implements DiscountStrategy 
{
    @Override
    public double calcPrice(double booksPrice) 
    {

        System.out.println("对于中级会员的折扣为10%");
        return booksPrice * 0.9;
    }
}
/*
 * 高级会员折扣
 */
public class AdvancedMemberStrategy implements DiscountStrategy 
{
    @Override
    public double calcPrice(double booksPrice) 
    {
        System.out.println("对于高级会员的折扣为20%");
        return booksPrice * 0.8;
    }
}

  4、测试

public class Test
{
    public static void main(String[] args)
    {
        // 选择并创建需要使用的策略对象
        DiscountStrategy strategy = new AdvancedMemberStrategy();
        // 创建环境
        Price price = new Price(strategy);
        // 计算价格
        double quote = price.quote(100);
        System.out.println("图书的最终价格为:" + quote);
    }
}

  运行截图:

  

 五、参考资料

  1、http://baike.baidu.com/link?url=b4W6TWr4LT4NebaYpHRp55xSOi3OCcaEiALs3jRpHKe0F6Lg6uq5HqY6kP9L9KjdCr-YTsLVWANhw4gqSajPjq

  2、http://www.cnblogs.com/java-my-life/archive/2012/05/10/2491891.html

以上是关于策略模式的主要内容,如果未能解决你的问题,请参考以下文章

Redis实现分布式锁(设计模式应用实战)

用于从 cloudkit 检索单列的代码模式/片段

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式

代码片-策略模式+工厂模式