Skip to content

Instantly share code, notes, and snippets.

@xcaspar
Created July 21, 2015 08:41
Show Gist options
  • Save xcaspar/7aaffeb38ebd9adc6d2c to your computer and use it in GitHub Desktop.
Save xcaspar/7aaffeb38ebd9adc6d2c to your computer and use it in GitHub Desktop.

项目重构总结(一)

@(工作) ####介绍 项目系统间是通过接口进行业务调用,业务目前分B2C和C2C两种交易模式,不同游戏在相同或者不同的交易模式下,校验、支付、商品交互、发货等业务处理也不一样。这就形成相同场景下不同的业务处理需求。重构前的代码部分采用了工厂模式和抽象工厂方法,但是由于抽象工厂方法的原因导致结构设计特别冗余,编码起来特别繁琐,修改起来更麻烦。重构前还有一个不好的地方是B2C和C2C的校验是放一块的,通过交易模式来划分,但是如果不同游戏的校验不一样的话,很难扩展。

重构

重构后的设计是,按业务划分,通过交易模式和游戏类别来生成相关的交易业务Service,将相同的业务方法写到抽象父类的方法中,抽象父类对外只暴露业务接口方法,这样保证了业务入口的一致性,防止业务方法被部分调用的错误。不同游戏、不同模式的业务方法写到相关的子类中,保证业务方法的特殊性。 拿下单校验举例,代码如下:

public class TradeFactory {
	public static TradeValidateService getTradeValidteFactory(int tradeMode, int gameId) {
	if (TradeConstants.B2C_MODE == tradeMode) {
		if (gameId == 16) {
			return SpringContextHolder.getBean(B2CTradeValidateService.class);
		} else {
			return SpringContextHolder.getBean(B2CTradeValidateService.class);
		}
	}
	if (TradeConstants.C2C_MODE == tradeMode) {
		if (gameId == 16) {
			return SpringContextHolder.getBean(C2CTradeValidateService.class);
		} else {
			return SpringContextHolder.getBean(C2CTradeValidateService.class);
		}
	}
	throw new RuntimeException("invalid tradeMode: " + tradeMode);
}

注: 根据交易模式和游戏类别来生成业务处理相关的Service

@Service
public abstract class TradeValidateService {
   // 校验入口,让子类去实现
	public abstract boolean validateBuyer(int platformId, int gameId, String goodsCode, 
		long buyerUserId, String buyerOpenId, String sellerOpenId, int goodsType);

	// 共同的校验,写到父类,方便子类们的调用
	protected boolean isInSingleGoodsLimit(int platformId, int gameId, 
		String buyerOpenId, String goodsCode) {
		return buyerOrderCache.isInThisGoodsBuyLimitTime(platformId, gameId, buyerOpenId, goodsCode);
}
… 

注:抽象的父类对外只暴露一个入口;将校验拆成原子方法,让子类去选择需要的方法进行校验。

@Service
public class C2CTradeValidateService extends TradeValidateService {
	@Override
	public boolean validateBuyer(int platformId, int gameId, String goodsCode, long buyerUserId, String buyerOpenId, String sellerOpenId, int goodsType) {
		// 此商品是否在其下单限制内
		if (isInSingleGoodsLimit(platformId, gameId, buyerOpenId, goodsCode)) {
			throw new OrderException(OrderResultCode.BUYER_CANCELED_ORDER_IN_LIMIT_TIME, null, null);
		}
		…….
	}
	// 特有方法,子类实现
	protected boolean isC2CSystemClose(Integer platformId, Integer gameId) {
		….
	}
}	

注: 子类去实现父类的抽象的入口方法,自身特有的校验,子类本身去实现。

总结

以上设置增加了业务扩展性,而且保证了入口一致性。缺点是如果新增一种交易模式,开发量比较大,要将交易流程整个都要重写一下。针对此问题,下一步的解决方式是将业务原子化,即下单、支付、发货等接口做成不可拆分的模块,然各个子类选择相关原子模块进行组装,实现业务处理。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment