溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

if-else嵌套的用法

發(fā)布時間:2021-06-22 16:37:59 來源:億速云 閱讀:1398 作者:chen 欄目:編程語言

本篇內容主要講解“if-else嵌套的用法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“if-else嵌套的用法”吧!

一、傳統(tǒng)的實現(xiàn)方式

先說一下具體的需求:公司推廣入口很多,每一個下單來源在下單時都做特殊的邏輯處理,可能每兩天就會加一個來源。

那么按照傳統(tǒng)的實現(xiàn)方式代碼就是如下:

public class OrderServiceImpl implements IOrderService {
    @Override
    public String handle(OrderDTO dto) {
        String type = dto.getType();
        if ("1".equals(type)) {
            return "處理普通訂單";
        } else if ("2".equals(type)) {
            return "處理團購訂單";
        } else if ("3".equals(type)) {
            return "處理促銷訂單";
        }
        return null;
    }
}

為什么非得寫的這么臃腫?很多同事會說:“哎呀,沒辦法呀,業(yè)務催的緊,這樣開發(fā)效率快省事”。的確是句大實話,很多時候業(yè)務方確實像催命鬼一樣的讓你趕工期,想快速實現(xiàn)功能,這樣寫是最好的選擇。

上邊的代碼看似還算清晰,可如果我告訴你公司訂單來源有上百種,你想象一下那種臃腫的if-else,去翻代碼時是什么感受?

二、策略模式的實現(xiàn)方式

策略模式是oop中最著名的設計模式之一,是對方法行為的抽象,可以歸類為行為設計模式,也是oopinterface經(jīng)典的應用。其特點簡單又實用,是我最喜歡的模式之一。

策略模式定義了一個擁有共同行為的算法族,每個算法都被封裝起來,可以互相替換,獨立于客戶端而變化。

不少人說:Java的設計模式背了很多,可日常還不就是寫if-else的業(yè)務,根本就不用到。其實不是用不到是沒有用到合適的位置!

1、策略模式的使用場景:
  • 針對同一問題的多種處理方式,僅僅是具體行為有差別時;

  • 需要安全地封裝多種同一類型的操作時;

  • 同一抽象類有多個子類,而客戶端需要使用if-else 或者 switch-case 來選擇具體子類時。

這個是用策略模式修改后代碼:

@Component
@OrderHandlerType(16)
public class DispatchModeProcessor extends AbstractHandler{

	@Autowired
	private OrderStencilledService orderStencilledService;
	
	@Override
	public void handle(OrderBO orderBO) {
		
		/**
    	 * 訂單完結廣播通知(1 - 支付完成)
    	 */
    	orderStencilledService.dispatchModeFanout(orderBO);
		
    	/**
    	 *  SCMS 出庫單
    	 */
    	orderStencilledService.createScmsDeliveryOrder(orderBO.getPayOrderInfoBO().getLocalOrderNo());
	}
}

每個訂單來源都有自己單獨的邏輯實現(xiàn)類,而每次需要添加訂單來源,直接新建實現(xiàn)類,修改@OrderHandlerType(16)的數(shù)值即可,再也不用去翻那幾百行的if-lese,一勞永逸!

2、具體的實現(xiàn)過程:

1、定義一個標識訂單來源的注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface OrderHandlerType {
	int value() default 0;
}

2、抽象出來一個具體的業(yè)務處理器

public abstract class AbstractHandler {
	abstract public void handle(OrderBO orderBO);
}

3、項目啟動掃描 handler 入口

@Component
@SuppressWarnings({"unused","rawtypes"})
public class HandlerProcessor implements BeanFactoryPostProcessor {
	
	private String basePackage = "com.ecej.order.pipeline.processor";
	
    public static final Logger log = LoggerFactory.getLogger(HandlerProcessor.class);
	
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		
		Map<Integer,Class> map = new HashMap<Integer,Class>();
		
		ClassScaner.scan(basePackage, OrderHandlerType.class).forEach(x ->{
			int type = x.getAnnotation(OrderHandlerType.class).value();
			map.put(type,x);
		});
		
		beanFactory.registerSingleton(OrderHandlerType.class.getName(), map);
		
		log.info("處理器初始化{}", JSONObject.toJSONString(beanFactory.getBean(OrderHandlerType.class.getName())));
	}
}

4、掃描需要用到的工具類

public class ClassScaner {
	private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

	private final List<TypeFilter> includeFilters = new ArrayList<TypeFilter>();

	private final List<TypeFilter> excludeFilters = new ArrayList<TypeFilter>();

	private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resourcePatternResolver);
	
	/**
	 * 添加包含的Fiter
	 * @param includeFilter
	 */
	public void addIncludeFilter(TypeFilter includeFilter) {
		this.includeFilters.add(includeFilter);
	}

	/**
	 * 添加排除的Fiter
	 * @param includeFilter
	 */
	public void addExcludeFilter(TypeFilter excludeFilter) {
		this.excludeFilters.add(excludeFilter);
	}
	
	/**
	 * 掃描指定的包,獲取包下所有的Class
	 * @param basePackage 包名
	 * @param targetTypes 需要指定的目標類型,可以是pojo,可以是注解
	 * @return Set<Class<?>>
	 */
	public static Set<Class<?>> scan(String basePackage,
			Class<?>... targetTypes) {
		ClassScaner cs = new ClassScaner();
		for (Class<?> targetType : targetTypes){
			if(TypeUtils.isAssignable(Annotation.class, targetType)){
				cs.addIncludeFilter(new AnnotationTypeFilter((Class<? extends Annotation>) targetType));
			}else{
				cs.addIncludeFilter(new AssignableTypeFilter(targetType));
			}
		}
		return cs.doScan(basePackage);
	}
	
	/**
	 * 掃描指定的包,獲取包下所有的Class
	 * @param basePackages 包名,多個
	 * @param targetTypes 需要指定的目標類型,可以是pojo,可以是注解
	 * @return Set<Class<?>>
	 */
	public static Set<Class<?>> scan(String[] basePackages,
			Class<?>... targetTypes) {
		ClassScaner cs = new ClassScaner();
		for (Class<?> targetType : targetTypes){
			if(TypeUtils.isAssignable(Annotation.class, targetType)){
				cs.addIncludeFilter(new AnnotationTypeFilter((Class<? extends Annotation>) targetType));
			}else{
				cs.addIncludeFilter(new AssignableTypeFilter(targetType));
			}
		}
		Set<Class<?>> classes = new HashSet<Class<?>>();
		for (String s : basePackages){
			classes.addAll(cs.doScan(s));
		}
		return classes;
	}
	
	/**
	 * 掃描指定的包,獲取包下所有的Class
	 * @param basePackages 包名
	 * @return Set<Class<?>>
	 */
	public Set<Class<?>> doScan(String [] basePackages) {
		Set<Class<?>> classes = new HashSet<Class<?>>();
		for (String basePackage :basePackages) {
			classes.addAll(doScan(basePackage));
		}
		return classes;
	}
	
	/**
	 * 掃描指定的包,獲取包下所有的Class
	 * @param basePackages 包名
	 * @return Set<Class<?>>
	 */
	public Set<Class<?>> doScan(String basePackage) {
		Set<Class<?>> classes = new HashSet<Class<?>>();
		try {
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
					+ ClassUtils.convertClassNameToResourcePath(
							SystemPropertyUtils.resolvePlaceholders(basePackage))+"/**/*.class";
			Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
			for (int i = 0; i < resources.length; i++) {
				Resource resource = resources[i];
				if (resource.isReadable()) {
					MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
					if ((includeFilters.size() == 0 && excludeFilters.size() == 0)|| matches(metadataReader)) {
						try {
							classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
						} catch (ClassNotFoundException ignore) {}
					}
				}
			}
		} catch (IOException ex) {
			throw new RuntimeException("I/O failure during classpath scanning", ex);
		}
		return classes;
	}
	
	/**
	 * 處理 excludeFilters和includeFilters
	 * @param metadataReader
	 * @return boolean
	 * @throws IOException
	 */
	private boolean matches(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, this.metadataReaderFactory)) {
				return false;
			}
		}
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, this.metadataReaderFactory)) {
				return true;
			}
		}
		return false;
	}
}

5、 根據(jù)類型實例化抽象類

@Component
public class HandlerContext {

	@Autowired
	private ApplicationContext beanFactory;

	public  AbstractHandler getInstance(Integer type){
		
		Map<Integer,Class> map = (Map<Integer, Class>) beanFactory.getBean(OrderHandlerType.class.getName());
		
		return (AbstractHandler)beanFactory.getBean(map.get(type));
	}
	
}

6、調用入口,我這里是接的MQ消息,會批量的處理多個訂單來源

@Component
@RabbitListener(queues = "OrderPipelineQueue")
public class PipelineSubscribe{
 
	private final Logger LOGGER = LoggerFactory.getLogger(PipelineSubscribe.class);
	
	@Autowired
	private HandlerContext HandlerContext;
	
	@Autowired
	private OrderValidateService orderValidateService;
	
    @RabbitHandler
    public void subscribeMessage(MessageBean bean){
    	
    	OrderBO orderBO = JSONObject.parseObject(bean.getOrderBO(), OrderBO.class);
    	
    	if(null != orderBO &&CollectionUtils.isNotEmpty(bean.getType()))
    	{
    		for(int value:bean.getType())
    		{
       		 AbstractHandler handler = HandlerContext.getInstance(value);
       		 handler.handle(orderBO);
    		}
		}
	}
}

接收實體 MessageBean 類代碼

public class MessageBean implements Serializable {
    private static final long serialVersionUID = 5454831432308782668L;
    private String cachKey;
    private List<Integer> type;
    private String orderBO;

    public MessageBean(List<Integer> type, String orderBO) {
        this.type = type;
        this.orderBO = orderBO;
    }
}
三、策略模式的優(yōu)缺點
優(yōu)點
  • 易于擴展,增加一個新的策略只需要添加一個具體的策略類即可,基本不需要改變原有的代碼,符合開放封閉原則

  • 避免使用多重條件選擇語句,充分體現(xiàn)面向對象設計思想 策略類之間可以自由切換,由于策略類都實現(xiàn)同一個接口,所以使它們之間可以自由切換

  • 每個策略類使用一個策略類,符合單一職責原則 客戶端與策略算法解耦,兩者都依賴于抽象策略接口,符合依賴反轉原則

  • 客戶端不需要知道都有哪些策略類,符合最小知識原則

缺點
  • 策略模式,當策略算法太多時,會造成很多的策略類

  • 客戶端不知道有哪些策略類,不能決定使用哪個策略類,這點可以通過封裝common公共包解決,也可以考慮使IOC容器依賴注入的方式來解決。

以下是訂單來源策略類的一部分,不得不說策略類確實比較多。 if-else嵌套的用法

總結:

凡事都有他的兩面性,if-else多層嵌套和也都有其各自的優(yōu)缺點:

if-else的有點就是簡單,想快速迭代功能,邏輯嵌套少且不會持續(xù)增加,if-else更好些,缺點也是顯而易見,代碼臃腫繁瑣不便于維護。

策略模式 將各個場景的邏輯剝離出來維護,同一抽象類有多個子類,需要使用if-else 或者 switch-case 來選擇具體子類時,建議選策略模式,他的缺點就是會產(chǎn)生比較多的策略類文件。

兩種實現(xiàn)方式各有利弊,如何選擇還是要依據(jù)具體業(yè)務場景,還是那句話設計模式不是為了用而用,一定要用在最合適的位置。

到此,相信大家對“if-else嵌套的用法”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI