【设计模式一】策略模式项目上的使用

前言

一般来说,项目上常常会碰到,某一个功能,根据传过来的业务类型,返回不同的结果,基本上是业务类型的逻辑或计算方法不一致,而这个业务类型不是通常固定的字典数据,时不时会因业务的需要,进行增加,当碰到这种情况,基本上就可以使用策模式来解决扩展问题,而不是在一个类里,定义不同的方法来实现。

举个例子

在个人开发过的项目中,因项目需要,与终端通信时,有部分使用HTTP协议不能满足需要,重新自定义了一个协议ufo(具体协议就不在此说明),约定了统一的参数,根据传输入数据中,指令部分的Code,返回不同数据。

从实现的角度来说,首先想的就是if-elseswitch-case来判断Code,调用不同的方法实现。

@Service
public class UfoService {  

	public PacketData processData(PacketData input) {
        switch (input.getCode()) {
            // A指令
            case "A":
                return A(input);
            // B指令
            case "B":
                return B(input);
            // C指令
            case "C":
                return C(input);
        }
    }

	private PacketData A(PacketData input){
	    ...
	}
	
	private PacketData B(PacketData input){
	    ...
	}
	
	private PacketData C(PacketData input){
	    ...
	}
    
}

因指令一开始在设计时,是没办法定义全的,根据产品经理对产品功能的迭代,时不时需要增加指令来满足功能的需要,如果把这些方法写在一个类里,那么每次增加指令都需要变动这个类,这个对程序的扩展性来说,不太友好。

改造

那么使用策略模式的话,可以解决扩展性问题,同时结合Spring的注入,对进行switch-case进行优化

1. 定义接口

接口里有一个方法(一个还是多个根据实际需要),此方法的定义就是处理数据,并返回结果:

public interface BaseProcessStrategy {  

    /** 
     * 数据处理
     * PacketData 为自定义数据转的对象
     */
    public PacketData process(PacketData input);
    
}

2. 实现接口

各指令实现BaseProcessStrategy接口就可以(注意:因下一步环境类的构造函数中,注入所有BaseProcessStrategy接口bean,所以在使用注解@Component时需要显示指定名称),如:

/**
 * A指令
 */
@Component("StrategyA")
public class StrategyA implements BaseProcessStrategy {  

    /** 
     * 数据处理
     * PacketData 为自定义数据转的对象
     */
    @Override
    public PacketData process(PacketData input) {
    	PacketData output = new PacketData();
    	... // 数据处理省略
    	output.setData(data);
    	return output;
    }
    
}

3. 定义环境

定义Context,用于连接上下文,也就是使用方用的类

/**
 * 上下文
 */
@Component
public class UfoContext {  

    private final static String PREFIX = "strategy";
    
	private final Map<String, BaseProcessStrategy> strategyMap = new ConcurrentHashMap<>();
	
    /**
     * Spring自动注入所以实现了BaseProcessStrategy接口的Bean
     */
    @Autowired
    public UfoContext(Map<String, BaseProcessStrategy> strategyMap) {
        this.strategyMap.clear();
        strategyMap.forEach((k, v)-> this.strategyMap.put(k, v));
    }
    
    /**
     * 执行指令
     * @param packet 入包
     * @return 出包
     */
    public PacketData execute(PacketData input) {
        return strategyMap.get(PREFIX + packet.getCode()).process(input);
    }
}

4. 调用方代码改造

@Service
public class UfoService {
    
    @Autowired
    private UfoContext context;

	public PacketData processData(PacketData input) {
        return context.execute(input);
    }
    
}

之后,这部分代码就可以不用动,只要增加实现BaseProcessStrategy接口的指令类就可以。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值