[Strategy Pattern] of Java Design Patterns

At the beginning of Dr. Yan Hong's "JAVA and Patterns" book, the Strategy pattern is described as follows:

  The strategy pattern belongs to the behavior pattern of the object. The intent is to encapsulate a set of algorithms into separate classes with a common interface, making them interchangeable. The strategy pattern allows the algorithm to be changed without affecting the client.


Structure of the Strategy Pattern

  The strategy mode is the packaging of the algorithm, which separates the responsibility of using the algorithm from the algorithm itself, and delegates the management to different objects. The strategy pattern usually wraps a series of algorithms into a series of strategy classes as a subclass of an abstract strategy class. In one sentence, it is: "Prepare a set of algorithms and encapsulate each algorithm so that they are interchangeable". The structure of the strategy pattern instance is explained below with a schematic implementation.

  This mode involves three roles:

  ●  Environment (Context) role: holds a reference to a Strategy.

  ●  Abstract strategy (Strategy) role: This is an abstract role, usually implemented by an interface or abstract class. This role gives all the interfaces required by concrete policy classes.

  ●  Concrete Strategy (ConcreteStrategy) role: packaging related algorithms or behaviors.

source code

  Environment role class

copy code
public  class Context {
     // An object holding a specific strategy 
    private Strategy strategy;
     /**
     * Constructor, passing in a specific strategy object
     * @param strategy specific strategy object
      */ 
    public Context(Strategy strategy){
         this .strategy = strategy;
    }
    /**
     * Strategy method
     */ 
    public  void contextInterface(){
        
        strategy.strategyInterface();
    }
    
}
copy code

  abstract strategy class

copy code
public interface Strategy {
    /**
     * Strategy method
     */
    public void strategyInterface();
}
copy code

  specific strategy class

copy code
public class ConcreteStrategyA implements Strategy {

    @Override
    public  void strategyInterface() {
         // related business 
    }

}
copy code
copy code
public class ConcreteStrategyB implements Strategy {

    @Override
    public  void strategyInterface() {
         // related business 
    }

}
copy code
copy code
public class ConcreteStrategyC implements Strategy {

    @Override
    public void strategyInterface() {
        //相关的业务
    }

}
copy code

  

使用场景

  假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。一个最简单的情况就是把所有货品的单价乘上数量,但是实际情况肯定比这要复杂。比如,本网站可能对所有的高级会员提供每本20%的促销折扣;对中级会员提供每本10%的促销折扣;对初级会员没有折扣。

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

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

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

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

  使用策略模式来实现的结构图如下:

源代码

  抽象折扣类

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

  初级会员折扣类

copy code
public class PrimaryMemberStrategy implements MemberStrategy {

    @Override
    public double calcPrice(double booksPrice) {
        
        System.out.println("对于初级会员的没有折扣");
        return booksPrice;
    }

}
copy code

  中级会员折扣类

copy code
public class IntermediateMemberStrategy implements MemberStrategy {

    @Override
    public double calcPrice(double booksPrice) {

        System.out.println("对于中级会员的折扣为10%");
        return booksPrice * 0.9;
    }

}
copy code

  高级会员折扣类

copy code
public class AdvancedMemberStrategy implements MemberStrategy {

    @Override
    public double calcPrice(double booksPrice) {
        
        System.out.println("对于高级会员的折扣为20%");
        return booksPrice * 0.8;
    }
}
copy code

   价格类

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

  客户端

copy code
public class Client {

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

}
copy code

   从上面的示例可以看出,策略模式仅仅封装算法,提供新的算法插入到已有系统中,以及老算法从系统中“退休”的方法,策略模式并不决定在何时使用何种算法。在什么情况下使用什么算法是由客户端决定的。

认识策略模式

  策略模式的重心

  策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。

  算法的平等性

  策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法,大家的地位是完全一样的,正因为这个平等性,才能实现算法之间可以相互替换。所有的策略算法在实现上也是相互独立的,相互之间是没有依赖的。

  所以可以这样描述这一系列策略算法:策略算法是相同行为的不同实现。

  运行时策略的唯一性

  运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。

  公有的行为

  经常见到的是,所有的具体策略类都有一些公有的行为。这时候,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。

  这其实也是典型的将代码向继承等级结构的上方集中的标准做法。

 

策略模式的优点

  (1)策略模式提供了管理相关的算法族的办法。策略类的等级结构定义了一个算法或行为族。恰当使用继承可以把公共的代码移到父类里面,从而避免代码重复。

  (2)使用策略模式可以避免使用多重条件(if-else)语句。多重条件语句不易维护,它把采取哪一种算法或采取哪一种行为的逻辑与算法或行为的逻辑混合在一起,统统列在一个多重条件语句里面,比使用继承的办法还要原始和落后。

策略模式的缺点

  (1) The client must know all the policy classes and decide which one to use. This means that clients must understand the difference between these algorithms in order to choose the right algorithm class at the right time. In other words, the strategy pattern only works when the client knows the algorithm or behavior.

  (2) Since the strategy pattern encapsulates each specific strategy implementation as a class, if there are many alternative strategies, the number of objects will be considerable.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326023611&siteId=291194637