温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何实现在Java源代码中的替换掉所以的if else

发布时间:2020-11-04 16:33:58 来源:亿速云 阅读:232 作者:Leah 栏目:开发技术

这期内容当中小编将会给大家带来有关如何实现在Java源代码中的替换掉所以的if else,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

SmsSendService.java

public class SmsSendService{
	/**
 	 * @Param phoneNo 手机号
	 * @Param content 短信内容
	 */
	public void send(String phoneNo,String content){
		//从配置中读取 短信渠道
		String channelType=config.getChannelType();
		
		//如果是短信渠道A,则调用渠道A的api发送
		if(Objects.equals(channelType,"CHANNEL_A")){
			System.out.println("通过短信渠道A发送短信");
		}
		//如果是短信渠道B,则调用渠道B的api发送
		else if(Objects.equals(channelType,"CHANNEL_B")){
			System.out.println("通过短信渠道B发送短信");
		}
	}
}

如果某天增加了一个短信渠道C,那么接着追加一个”else if…"

//... 此处省略部分代码 ...

//从配置中读取 短信渠道
String channelType=config.getChannelType();
//如果是短信渠道A,则调用渠道A的api发送
if(Objects.equals(channelType,"CHANNEL_A")){
	System.out.println("通过短信渠道A发送短信");
}
//如果是短信渠道B,则调用渠道B的api发送
else if(Objects.equals(channelType,"CHANNEL_B")){
	System.out.println("通过短信渠道B发送短信");
}
//ADD: 如果是短信渠道C,则调用渠道C的api发送
else if(Objects.equals(channelType,"CHANNEL_C")){
	System.out.println("通过短信渠道C发送短信");
}

//... 此处省略部分代码 ...

如果又加其他短信渠道了呢?你又写一个“else if …" ?
显然这种做法不可取,也不符合SOLID原则中的”开闭原则“ ——对扩展开放,对更改封闭。
这样我们每次都需要修改原有代码(对更改没有封闭),不断的添加”if else"。
接下来我们把代码优化一下:

优化代码1

定义一个短信渠道的接口 SmsChannelService,所有的短信渠道API都实现该接口;

短信渠道接口 SmsChannelService.java

public interface SmsChannelService{
	//发送短信
	void send(String phoneNo,String content);
}

短信渠道A SmsChannelServiceImplA.java

public class SmsChannelServiceImplA implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通过短信渠道A发送短信");
	}
}

短信渠道B SmsChannelServiceImplB.java

public class SmsChannelServiceImplB implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通过短信渠道B发送短信");
	}
}

通过工厂类来初始化所有短信渠道service

SmsChannelFactory.java

public class SmsChannelFactory {
	private Map<String,SmsChannelService> serviceMap;

	//初始化工厂,将所有的短信渠道Service放入Map中
	public SmsChannelFactory(){
		//渠道类型为 key , 对应的服务类为value :
		serviceMap=new HashMap<String, SmsChannelService>(2);
		serviceMap.put("CHANNEL_A",new SmsChannelServiceImplA());
		serviceMap.put("CHANNEL_B",new SmsChannelServiceImplB());
	}

	//根据短信渠道类型获得对应渠道的Service
	public SmsChannelService buildService(String channelType){
		return serviceMap.get(channelType);
	}
}

在原来的SmsSendService中调用不同短信渠道的接口。
原来的 SmsSendService 类优化如下

public class SmsSendService {

	private SmsChannelFactory smsChannelFactory;

	public SmsSendService(){
		smsChannelFactory=new SmsChannelFactory();
	}

	public void send(String phoneNo,String content){
		//从配置中读取 短信渠道
		String channelType=config.getChannelType();
		//获取渠道类型对应的服务类
		SmsChannelService channelService=smsChannelFactory.buildService(channelType);
		//发送短信
		channelService.send(phoneNo,content);
	}

}

这样SmsSendService类非常简洁,把“if else"干掉了,
如果我要增加一个短信渠道C,无需再次更改 SmsSendService 类。
只需要增加一个类 SmsChannelServiceImplC 实现 SmsChannelService 接口,
然后在工厂类 SmsChannelFactory 中增加一行初始化 SmsChannelServiceImplC 的代码即可。

增加短信渠道C的实现 SmsChannelServiceImplC.java

public class SmsChannelServiceImplC implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通过短信渠道C发送短信");
	}
}

修改工厂类 SmsChannelFactory.java

public class SmsChannelFactory {
	private Map<String,SmsChannelService> serviceMap;

	//初始化 serviceMap ,将所有的短信渠道Service放入Map中
	public SmsChannelFactory(){
		//渠道类型为 key , 对应的服务类为value :
		serviceMap=new HashMap<String, SmsChannelService>(3);
		serviceMap.put("CHANNEL_A",new SmsChannelServiceImplA());
		serviceMap.put("CHANNEL_B",new SmsChannelServiceImplB());
		//ADD 增加一行 SmsChannelServiceImplC 的初始化代码 
		serviceMap.put("CHANNEL_C",new SmsChannelServiceImplC());
	}

	//根据渠道类型构建短信渠道Service
	public SmsChannelService buildService(String channelType){
		return serviceMap.get(channelType);
	}
}

“if else"是干掉了,但还是得修改原来的类 SmsChannelFactory ,不满足"开闭原则",有没有更好得方式呢?

我们通过使用spring的依赖注入进一步优化代码:

优化代码2

SmsChannelService 接口增加 getChannelType() 方法,这一步很关键。

public interface SmsChannelService {
	//发送短信
	void send(String phoneNo,String content);
	//关键:增加getChannelType()方法,子类实现这个方法用于标识出渠道类型
	String getChannelType();
}

子类增加该方法的实现,并加上 @Service 注解,使其让spring容器管理起来

SmsChannelServiceImplA.java

@Service
public class SmsChannelServiceImplA implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通过短信渠道A发送短信");
	}
	//关键:增加 getChannelType() 实现
	public String getChannelType() {
		return "CHANNEL_A";
	}
}

SmsChannelServiceImplB.java

@Service
public class SmsChannelServiceImplB implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通过短信渠道B发送短信");
	}
	//关键:增加 getChannelType() 实现
	public String getChannelType() {
		return "CHANNEL_B";
	}
}

修改 SmsChannelFactory 类: 这一步也很关键。

SmsChannelFactory.java

@Service
public class SmsChannelFactory {

	private Map<String,SmsChannelService> serviceMap;
	
	/*注入:通过spring容器将所有实现 SmsChannelService 接口的类的实例注入到 serviceList 中*/
	@Autowired
	private List<SmsChannelService> serviceList;

	/*通过 @PostConstruct 注解,在 SmsChannelFactory 实例化后,来初始化 serviceMap */
	@PostConstruct
	private void init(){
		if(CollectionUtils.isEmpty(serviceList)){
			return ;
		}
		serviceMap=new HashMap<String, SmsChannelService>(serviceList.size());
		//将 serviceList 转换为 serviceMap
		for (SmsChannelService channelService : serviceList) {
			String channelType=channelService.getChannelType();
			//重复性校验,避免不同实现类的 getChannelType() 方法返回同一个值。
			if(serviceMap.get(channelType)!=null){
				throw new RuntimeException("同一个短信渠道只能有一个实现类");
			}
			/*渠道类型为 key , 对应的服务类为value :
			与“优化代码1”中的通过手工设置“CHANNEL_A"、"CHANNEL_B"相比,
			这种方式更加自动化,后续在增加“CHANNEL_C"无需再改此处代码*/
			serviceMap.put(channelType,channelService);
		}
	}

	//根据渠道类型获取对应短信渠道的Service
	public SmsChannelService buildService(String channelType){
		return serviceMap.get(channelType);
	}
}

SmsSendService 加上 @Service 注解。通过 @Autowired 注入 SmsChannelFactory

SmsSendService.java

@Service
public class SmsSendService {

	@Autowired
	private SmsChannelFactory smsChannelFactory;

	public void send(String phoneNo,String content){
		//从配置中读取短信渠道类型
		String channelType=config.getChannelType();
		//构建渠道类型对应的服务类
		SmsChannelService channelService=smsChannelFactory.buildService(channelType);
		//发送短信
		channelService.send(phoneNo,content);
	}

}

这时,如果需要添加一个渠道C,那真的只需要添加一个 SmsChannelServiceImplC 即可,再也不用改原有代码,完全遵循“开闭原则”。

SmsChannelServiceImplC.java

@Service
public class SmsChannelServiceImplC implements SmsChannelService {
	public void send(String phoneNo, String content) {
		System.out.println("通过短信渠道C发送短信");
	}

	public String getChannelType() {
		return "CHANNEL_C";
	}
}

上述就是小编为大家分享的如何实现在Java源代码中的替换掉所以的if else了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI