策略模式(行为型)

思考问题:
一个书店的某类书是免费的,某类书是固定1元的,某类书是按折扣算的(比如88%)(同一类别的书本价格一样)。假定顾客只买一类书,在设计书店BookStore类时应该如何计算顾客买书的费用?

解答:
1. 你有可能不知道如何设计,毕竟上面的计算规则不一样(并不是一类书8折另一类书9折那样好计算);
2. 既然这样,我们就定义一个接口(策略接口),规定一个方法(strategyInterface())为计算金额的方法,BookStore类构造对象时传入该策略接口的实现类对象(在构造该对象时告诉它买多少本书,单价多少钱),那么调用该接口的方法即可获得计算好的金额。
策略模式(行为型)_第1张图片

上面实例的代码就不编了,给出一个通用的策略模式模板吧:

抽象策略类(用于规定策略类的策略方法签名):

package com.shusheng.srategy;

/**抽象策略类*/
public abstract class Strategy {

    //策略方法
    public abstract void strategyInterface();
}

具体策略实现类:

package com.shusheng.srategy;
/**具体策略实现类*/
public class ConcreteStrategy1 extends Strategy{

    /**具体策略函数*/
    @Override
    public void strategyInterface() {
        System.out.println("我是具体策略1,我将执行算法1");
    }
}

具体策略类2:

package com.shusheng.srategy;
/**具体策略*/
public class ConcreteStrategy2 extends Strategy {

    /**策略函数*/
    @Override
    public void strategyInterface() {
        System.out.println("我是具体策略2,我将执行算法2");
    }

}

上下文类(上下文角色,作用:封装策略模式,避免外界直接调用策略类的方法)

package com.shusheng.srategy;
/**上下文类(上下文角色)*/
public class Context {

    public Strategy strategy;//策略对象的引用

    public Context(Strategy strategy) {//构造函数,构造上下文对象时要初始化策略对象
        this.strategy = strategy;
    }

    /**调用策略,比如这个就是BookStore的计算金额的方法*/
    public void contextInterface(){//暴露给外界的方法,避免外界直接调用策略模式内部方法(如strategyInterface()就是策略模式内部的)
        this.strategy.strategyInterface();
    }
}

测试类:

package com.shusheng.srategy;

public class StrategyTest {

    public static void main(String[] args) {
        Context context = new Context(new ConcreteStrategy1());//初始化上下文对象时也要初始化策略类对象
        context.contextInterface();//调用上下文对象的方法而不是直接调用策略对象内部的方法

        Context context2 = new Context(new ConcreteStrategy2());//初始化上下文对象时也要初始化策略类对象
        context2.contextInterface();//调用上下文对象的方法而不是直接调用策略对象内部的方法
    }
}

策略模式(行为型)_第2张图片

策略模式优点:
1. 策略模式提供了管理相关的算法族的办法。(外界不需要知道内部是怎么实现的,只需要调用Context类的方法即可)
2. 使用策略模式可以避免使用多重条件if-else语句,实现细节:定义一个策略类接口(规定好策略方法),将if内部代码封装为一个策略实现类的方法,else内部代码也封装为另一个策略实现类的方法。(假设含if-else语句的类为Context),Context类中使用到if-else的地方直接替换为调用策略接口类的策略方法,当构造Context时传入具体的策略对象即可。这样在原先调用if-else的地方就会调用策略类的方法。

策略模式缺点:
1. 正如优点中对if-else的解说,客户端类必须知道哪一个策略类的具体功能是什么的,才能传入正确的策略对象,这意味着:别人使用该接口是必须理解这些策略算法的区别;即策略模式只适用于客户知道所有的算法或行为的情况。
2. 使用策略模式会造成很多的策略类,正如if-(else if) - (else if) -(else if) -else这样,就会产生很多策略类(每种情况一个类)。当然也可以用享元模式来减少对象的数量。

策略模式 的应用场景:
1. 多个类只是在算法或行为上稍有不同的场景(就可以把不同的算法或行为部分提取出来设计成策略模式)
2. 算法需要自由切换的场景
3. 需要屏蔽算法规则的场景(就是策略函数内部实现是屏蔽的,外界只是调用Context的方法)

你可能感兴趣的:(策略模式,行为型模式,Strategy模式,政策模式)