锦囊妙计——策略模式

策略模式

​ Strategy Pattern:策略模式是GoF23中设计模式中属于行为型设计模式的一种。

​ 策略模式的关键点就在于策略两字,策略是一种方法,一种方式,一种计策。用术语来讲的话,可以将其理解为算法,不同的策略也就是不同的算法。

​ 策略模式的作用呢,就是使得用户在执行某个操作的时候得到一个结果,而这个结果可能是由不同的算法所得到的,但是用户并不知道这些,算法的改变影响不到用户自己对这个功能的使用。

结构

策略模式类图

可以看到上图是一个对于策略模式来说一个简单的类图,可以看到有着三个角色:

  • 策略抽象类:这个角色仅仅是将所有的策略进行了一个抽象而已(当然,你也可以定义一个接口带代替抽象类)
  • 算法实现类:这个角色就是具体的策略,也可以说是具体的算法的逻辑实现了。
  • 配置类:也可以说是环境类,这个是给用户调用的,里面维护者一个策略对象,用来通过用户的需求选择执行特定的算法。
举例说明
  1. 策略两字一出,最先想到的估摸着就是“锦囊妙计”啦,诸葛亮在刘备去江东的时候就给了赵云三个锦囊妙计,特定的时候需要取出一个特定的锦囊,这也是策略模式的一种体现。
  2. 贴近我们生活的就是例子就是出行了,在自己待着的一个城市去往另一个城市,是坐汽车呢,做火车呢,做高铁呢,做飞机呢,还是说自驾行或者直接来个11路公交车去?都可以的,这也是策略模式的一种体现。
  3. 最容易体现的就是限制点外卖的各种商家的优惠卷了,打折的优惠券,满减的优惠券,直减的优惠券,等等。这种类型在最后计算实际的金额的时候,就是需要使用不同的算法来实现,这个例子更能体现出策略模式的意义了。
注意
  1. 通过上面的例子,其实我们可以发现,这不就是多条件的选择吗?可以使用if-else条件分支啊,还可以通过switch语句不是更加的实现简单?

    但是,需要注意的是,通过if-else或switch语句编写出来的代码,虽然可以得到正确的效果,但是仅仅是当前的效果,如果忽然出现了一个新的需求,那岂不是要去改源码,这显然违犯了开闭原则,而策略模式可以规避这一点,使得程序具有扩展性。

  2. 策略模式的一个缺点就是所有的策略应该是需要用户知道的,不能仅仅想诸葛亮一样直接给藏了起来,赵云完全不知道里面的东西,但是也不是完全不知道,起码赵云知道什么时候用哪一个。

    也就是说,对于所有的策略,需要完全暴露给用户,使得用户自己选择通过使用哪个策略才行。

  3. 策略的定义,也需要有抽象的概念,比如满300减100的优惠券和满1000减300的优惠券应该是算作是一种策略;再说打五折和打七折都是打折,这也是一样的策略,只是具体的数字不同而已。

一个小DEMO
  1. 场景

    写个简单的Demo,体现出策略模式的使用规则。嗯,就比如说我们平常上班吧,有的朋友是骑着共享单车去上班的,有的是挤着满满的人的公交,也有的是地铁公交一起来,笔者还算不错,可以直接走着去,沿途还可以看看风景呢。

  2. 首先定义个顶层抽象的策略接口吧

    package com.strategy;
    /**
     * 策略模式——策略抽象接口
     * @author WQ
     */
    public interface IStrategy {
    	/**
    	 * 定义个方法,显示出各种策略选择的不同
    	 */
    	void show();
    }
    
  3. 创建各种不同的策略了,这里就是骑自行车,公交,和走路吧,简单一点点

    package com.strategy;
    /**
     * 策略模式——实际策略——自行车
     * @author WQ
     */
    public class Bicycle implements IStrategy{
    	@Override
    	public void show() {
    		System.out.println("Go to work by bike!");
    	}
    }
    //---------------------------------------------------------------
    package com.strategy;
    /**
     * 策略模式——实际策略——公交车
     * @author WQ
     */
    public class Bus implements IStrategy{
    	@Override
    	public void show() {
    		System.out.println("Go to work by bus");
    	}
    }
    //------------------------------------------------------------------
    package com.strategy;
    /**
     * 策略模式——实际策略——步行
     * @author WQ
     */
    public class Walk implements IStrategy {
    	@Override
    	public void show() {
    		System.out.println("Walk to work!");
    	}
    }
    
  4. 写一个配置类(也可以叫环境类,也可以叫用户需要调用的类,都可以)

    package com.strategy;
    /**
     * 策略模式——上下文配置类/环境类
     * @author WQ
     */
    public class Context {
    	/**
    	 * 需要注意的就是,这个类需要维护一个抽象策略对象
    	 * 因为这个类需要指定具体的策略,才能进行使用
    	 */
    	private IStrategy strategy;
    	
    	/**
    	 * 加个setter,用于实时改变策略
    	 * @param strategy
    	 */
    	public void setStrategy(IStrategy strategy) {
    		this.strategy = strategy;
    	}
    	
    	/**
    	 * 通过构造函数定义策略,这里使用IStrategy 可以实现多态的特性
    	 * @param strategy
    	 */
    	public Context(IStrategy strategy) {
    		this.strategy = strategy;
    	}
    	
    	/**
    	 * 这里就是使用方法的位置,
    	 * 用户只需要通过指定的策略创建这个类,调用这个方法进行实际的调用即可
    	 */
    	public void work() {
    		this.strategy.show();
    	}
    }
    
  5. 加个测试类

    package com.strategy;
    /**
     * 策略模式——测试类部分
     * @author WQ
     */
    public class Main {
    	public static void main(String[] args) {
    		/**
    		 * 用户需要的创建自己想要的策略
    		 * 然后使用这个策略创建配置类进行方法的调用。
    		 */
    		Context context = new Context(new Bicycle());
    		context.work();
    		
    		context.setStrategy(new Bus());
    		context.work();
    		
    		context.setStrategy(new Walk());
    		context.work();
    	}
    }
    
  6. 测试走一波

    Go to work by bike!
    Go to work by bus
    Walk to work!
    

完成!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值