设计模式之——浅谈strategy模式(策略模式)

Posted 博客王大锤

tags:

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

strategy模式,即策略模式。个人觉得吧,策略模式更多的是一种思维方式。

首先我们要知道,为什么需要策略模式。举个例子,比如用程序输出今天下午去玩什么。

  • PlayGame 玩游戏
package site.wangxin520.gof.strategy.demo;

/**
 * 玩游戏的类
 * @author wangXgnaw
 *
 */
public class PlayGame {

    /**
     * 玩游戏的方法
     */
    public void playGame(){
        System.out.println("玩游戏");
    }
    
}
  • PlayBall  打球
package site.wangxin520.gof.strategy.demo;

/**
 * 玩球的类
 * @author wangXgnaw
 *
 */
public class PlayBall {

    /**
     * 打球的方法
     */
    public void playBall(){
        System.out.println("打球");
    }
    
    
}
  • Test测试类
package site.wangxin520.gof.strategy.demo;

/**
 * 测试
 * @author wangXgnaw
 *
 */
public class Test {
    public static void main(String[] args) {
        
        System.out.println("今天下午做什么事情呢?");
        
        PlayBall p1=new PlayBall();
        p1.playBall();
        
//        PlayGame p2=new PlayGame();
//        p2.playGame();
        
    }
}

这里就需要注意一点了,因为我们下午只能做一件事情,所以我们只能去注释掉其中一个事情,结果就是:(这里先把打游戏给注释掉了,下一个案例就是把打球给注释掉,因为相同所以略)

image

由此可见,如果我们想改变自己的下午的安排的话,需要很麻烦的,先去new 一个对应类的实现,然后再调用相应的方法。

既然原来方法很麻烦,那么我们就想办法改变它,当改变选择/安排时候,简化我们的操作。这就需要我们使用策略的设计模式。

策略模式里面就要求我们去在对应安排的类里面提取出一个策略类出来。就比如上面的案例,提取出一个play的策略类,在这个策略类里面判断是哪种安排:

  • play类
package site.wangxin520.gof.strategy.demo;

/**
 * 策略类
 * @author wangXgnaw
 *
 */
public class Play {
    
    //定义了常量,方便调用选择策略
    public final static String PLAY_GAME="playGame";
    public final static String PLAY_BALL="playBall";
    
    //保存策略的安排
    private String playName;
    //使用单例模式,避免资源浪费。这两个属性是用于后面对应策略的调用的
    private static PlayBall playBall=new PlayBall();
    private static PlayGame playGame=new PlayGame();
    
    /**
     * 构造函数,传入需要的安排
     * @param planName
     */
    public Play(String planName) {
        this.playName=planName;
    }
    
    /**
     * 这个是玩的类,在这个类中判断,传入的策略是哪一种,并进行对应的操作
     */
    public final void play(){
        if(PLAY_GAME==playName){
            playGame.playGame();
        }else if(PLAY_BALL==playName){
            playBall.playBall();
        }else{
            System.out.println("策略安排错误");
        }
    }
    
}
  • 这时候测试语句则为:
package site.wangxin520.gof.strategy.demo;

/**
 * 测试
 * @author wangXgnaw
 *
 */
public class Test {
    public static void main(String[] args) {
        
        System.out.println("今天下午做什么事情呢?");
        
        Play p=new Play(Play.PLAY_GAME);
        p.play();
        
    }
}
  • 结果为:(当改变方案时候,只需要将参数改变即可,没必要去重新new实现类了,测试打球略)

image

由此可见,测试方面的代码量大大减少了,也不需要我们再去new新的类了。这种思维模式就是策略模式。

也许你会问,白白多写了play一个类,却只减少了play中的两行代码,这压根也没有简化操作。对此,我就要告诉你了,如果play相关的类都是其他人给你编写好的,而你只需要在test里面简单调用一下,改变参数即可,也不需要你去new出类了,这样对你来说是不是简化了你很多操作。并且,如果使用了spring框架,完全可以把参数放到配置文件中,这样一来,你都不需要去修改代码了,不就是更简化了你的操作了?

策略模式也有第二种方法,提取一个父类的抽象类或者接口,然后面向接口/抽象父类(使用多态)进行编程,这样就更能大大简化开发,并且方便后期维护。

在实际操作中,在切换redis客户端集群版和单机版时候,就采用了这种方法,因为集群版和单机版对redis的NOSQL数据库操作的api是不同的,所以提取出了一个接口,在我们程序中只要面对这个接口进行编程,不管是否是集群版或者单机版。当切换的时候,只需要在配置文件中切换一下相应的配置,而不需要去重新修改已经编号的代码。可见,操作大大简化了。

最后呢,策略模式是一种很好的思维模式,有多种实现方法,熟练运用,能大大提高编码开发效率。与君共勉,好好努力!

以上是关于设计模式之——浅谈strategy模式(策略模式)的主要内容,如果未能解决你的问题,请参考以下文章

编程基础系列--之--浅谈ListSetMap和泛型——单列集合

HTTP协议与www浅谈

浅谈Java三大特性之继承

设计模式

浅谈 Flask 框架

设计模式:命令模式——命令模式扩展之队列请求