设计模式——策略模式

策略模式:定义了算法家族,分别封装起来,让算法之间可以互相替换,使得算法的改变,不会影响到使用算法的客户。

  算法是随时可以被替换的,这是一个变幻点,封装变化点是面向对象的一种重要思维,

  策略模式是一种定义一系列算法的方法,从概念上就是用不同的算法完成相同的工作,只是实现不同,可以用相同的方式调用这些算法,减少各种算法类与使用算法类之间的耦合

  在实践中,策略模式可以用来封装几乎任何类型的规则,只要在分析过程中发现不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化

  在基本的策略模式中,选择需要具体实现类的职责有客户端对象来承担,并传给ContextStrategy对象,并没有解除客户端需要选择判断的压力,但是策略模式和简单工厂模式结合后选择具体的实现类的职责也可以由ContextStrategy来承担,最大化的减轻客户端的职责。

  

 

下面使用java代码诠释上面的类图

 1 package com.zr.pattern.strategy;
 2 /**
 3  * 公共的算法接口
 4  * @author Administrator
 5  */
 6 public interface Strategy {
 7     public void algorithmic();
 8 }
 9 //策略一
10 public class AlgorithmicOne implements Strategy {
11     @Override
12     public void algorithmic() {
13         System.out.println("算法一的实现!!!");
14     }
15 }
16 //策略二
17 public class AlgorithmicTwo implements Strategy {
18     @Override
19     public void algorithmic() {
20         System.out.println("算法二的实现!!!");
21     }
22 
23 }
24 
25 public class ContextStrategy {
26     private Strategy strategy ;
27     
28     public ContextStrategy(Strategy strategy) {
29         this.strategy = strategy;
30     }
31     
32     public void invokeStrategy(){
33         strategy.algorithmic();//调用算法
34     }
35     
36 }

 

客户端类:

public class Client {

    public static void main(String[] args) {
        //由于实例化不同的策略,最终得到的结果就不相同
        ContextStrategy contextStrategy = new ContextStrategy(new AlgorithmicOne());
        contextStrategy.invokeStrategy();
        
        ContextStrategy contextStrategy2 = new ContextStrategy(new AlgorithmicTwo());
        contextStrategy2.invokeStrategy();
    }
//    输出内容:
//    算法一的实现!!!
//    算法二的实现!!!
}

上面的例子代码清晰但却理解起来很生硬,下面举一个具有实际意义的例子。

  lz 经常去网吧LOL,发现网吧经常搞充值活动,例如:

  充值超过50元,送20元。

  充值超过100元,送50元。

  会员生日持有身份证享受冲多少送多少。(活动不叠加参与)

  这种充值优惠经常变化,并且需要经常性的互相替换,有可能过几天又加个充20送瓶雪碧。

 

首先需要一个计算网费的策略接口。如下

package com.zr.pattern.strategy.two;

/**
 * 网费计算策略接口
 * @author zr
 */
public interface CostCountStrategy {
    public void getMoney();//计算网费
}

 

给出三种优惠策略

/**
 * 策略一:充50送20
 * @author zr
 */
public class StrategyOne implements CostCountStrategy {
    @Override
    public void getMoney(int money) {
        int total  = money + 20;
        System.out.println("客户充值网费"+ money + "赠送20" + "实际金额" + total);
    }
}

/**
 * 策略二:充100送50
 * @author zr
 */
public class StrategyTwo implements CostCountStrategy {
    @Override
    public void getMoney(int money) {
        int total  = money + 50;
        System.out.println("客户充值网费"+ money + "赠送50" + "实际金额" + total);
    }
}

/**
 * 策略三:充多少送多少
 * @author zr
 */
public class StrategyThree implements CostCountStrategy {

    @Override
    public void getMoney(int money) {
        int total  = money*2;
        System.out.println("客户充值网费"+ money + "赠送"+ money + "实际金额" + total);
    }

}

 

  使用策略工厂来生成具体的策略((简单的实现,别的情况不考虑 例如 充60))

/**
 * 策略工厂
 * @author zr
 */
public class ContextStrategy {

    private CostCountStrategy costCountStrategy;

    public ContextStrategy(String strategy) {
        //使用简单工厂模式,将客户端的职责转移过来
        switch (strategy) {
        case "充值50送20":
            costCountStrategy = new StrategyOne();
            break;
        case "充值100送50":
            costCountStrategy = new StrategyTwo();
            break;
        case "充值多少送多少":
            costCountStrategy = new StrategyThree();
            break;
        }
    }
    
    public void invokeStrategy(int money){
        costCountStrategy.getMoney(money);
    }
}

  客户端类调用

public class client {
    public static void main(String[] args) {
        ContextStrategy contextStrategy = new ContextStrategy("充值50送20");
        contextStrategy.invokeStrategy(50);
        
        ContextStrategy contextStrategy2 = new ContextStrategy("充值100送50");
        contextStrategy2.invokeStrategy(100);
        
        ContextStrategy contextStrategy3 = new ContextStrategy("充值多少送多少");
        contextStrategy3.invokeStrategy(200);
    }
//    输出结果:
//    客户充值网费50赠送20实际金额70
//    客户充值网费100赠送50实际金额150
//    客户充值网费200赠送200实际金额400
}

   策略模式还是有点不太完美,例如:如果要增加一个新的算法就必须修改ContextStrategy类的switch代码。

 

posted @ 2016-08-20 16:17  99°的开水  阅读(224)  评论(0编辑  收藏  举报