设计模式必知必会:策略模式

本文介绍策略模式对if-else业务分派逻辑的优化

应用场景

最近写了一个服务:根据优惠券的类型resourceType和编码resourceId来 查询 发放方式grantType

实现方式:

  • 根据优惠券类型resourceType -> 确定查询哪个数据表
  • 根据编码resourceId -> 查询派发方式grantType

优惠券有多种类型,分别对应了不同的数据库表:

  • 红包
  • 购物券
  • QQ会员
  • 外卖会员

实际的优惠券远不止这些,这个需求是要我们写一个业务分派的逻辑

第一思路一般是if-else 、swtich case:

switch(resourceType){
    
    
	case "红包": 
		查询红包的派发方式 
		break;
	case "购物券": 
		查询购物券的派发方式
		break;
	case "QQ会员" :
		...
		break;
	case "外卖会员" :
		...
		break;
		
	......
	default : logger.info("查找不到该优惠券类型resourceType以及对应的派发方式");
		break;
}

这么写if-else有个坏处:

  • 就是如果判断的情况很多且单个if 语句块的代码很多行 的话,那 整个if-else的代码块就太长了,可读性下降。
  • 并且由于 整个 if-else的代码有很多行,也不方便修改,可维护性低。

那么我们就尝试对 if-else 的业务分派 逻辑优化一下

策略模式

定义就不念了,说人话,策略模式的结构就是:

  • 一个支持所有算法的公共抽象类 /接口:即任意一个 if 判断完后,都会执行该接口的方法
  • 具体策略的实现类:查询红包派发方式的逻辑写在一个类里面,购物券写在另一个类
  • 客户端调用的入口:通过持有 公共接口的引用,在创建对象的时候利用多态来执行具体的策略算法。

上代码:

一、公共接口

public abstract class Strategy{
    
    
    //定义支持所有算法的公共接口
    public abstract String query();
}

客户端执行具体的策略的时候,就Strategy strategy = new ConcreteStrategy01()

二、具体的策略实现类

继承公共接口,给里面的抽象方法加内容:

查询红包的发放方式:

//查询红包redPaper 发放方式
class ConcreteStrategy01 extends Strategy{
    
    
    public  String query(){
    
    
    	return "每周末9点发放";
    }
}

查询购物券的发放方式:

//查询购物券shopping的发放方式
class ConcreteStrategy02 extends Strategy{
    
    
    public  String query(){
    
    
    	return "每周三20点发放";
    }
}

三、客户端调用的入口

要持有 公共接口的引用,不然没法通过多态 new ConcreteStrategy01() 或者 new ConcreteStrategy02() 来获得具体的策略实现 [红包的查询方式、购物券的查询方式]

class Context{
    
    
    //持有公共接口的引用,后续通过多态来获取[红包、购物券]的实现类
    Strategy strategy;
    public Context(Strategy strategy){
    
    
        this.strategy=strategy;
    }
    public String ContextInterface(){
    
    
        return strategy.query();
    }
}

客户端执行具体策略:

值得注意的是:策略模式在具体的业务分派的时候,依然采用if-else的方式,只是说它比单纯的if-else好在可维护性比较好,如果要更改某一个业务逻辑,只需要去修改对应的类即可。

比如:查询红包的派发方式grantType

回顾一下产品需求:根据优惠券类型resourceType和编码resourceId来查询派发方式grantType

具体操作是由优惠券类型resourceType判断去哪个表查,然后根据编码resourceId查出对应的派发方式grantType

class Test{
    
    
	//客户端执行具体策略的测试方法
	public static void main(String[] args){
    
    
		String resourceType="红包";
		String grantType;
		switch(resourceType){
    
    
			case "红包":
				Context context01=new Context(new ConcreteStrategy01());
				grantType=context01.ContextInterface();
				break;
			case "购物券":
				Context context02=new Context(new ConcreteStrategy02());
				grantType=context02.ContextInterface();
				break;
		default:
                throw new IllegalStateException("Unexpected value: " + resourceType);
		}
	}
}

我把策略的具体实现给简化了

执行的结果:
在这里插入图片描述

策略模式的优点和缺点

优点

  • 可维护性好,如果要修改红包的派发逻辑,只需要去修改对应的类ConcreteStrategy01 即可。

缺点

  • 没法俯视整个业务分派逻辑
  • 策略类增多

猜你喜欢

转载自blog.csdn.net/qq_44384533/article/details/109224694