首页 > 其他 > 详细

策略模式实战之优惠方式

时间:2016-02-29 16:42:52      阅读:147      评论:0      收藏:0      [点我收藏+]

策略模式的类图:


                       技术分享

代码结构:


优惠方式父类:


/**
 * @author hejingyuan
 *
 */
public class AbstractIncentive implements Serializable {


	private static final long serialVersionUID = 1L;
	
	private long id;
	
	private int minAccount;
	
	private Integer feeFree;

	private String incentiveType;
	
	private long incentiveTypeId;

	//省略get set 方法
	
	public PromotionResultDto calculate(Map<Integer, Integer> selectedGoods, Integer repeatTimes,PromotionActivity promotionActivity,int orderAmount,List<ProductDetail> list) {
		// TODO Auto-generated method stub
		return null;
	}
	

单品优惠子类:

/**
 * @author hejingyuan
 *
 */
public class IncentiveItemDiscount extends AbstractIncentive {

	private static final long serialVersionUID = 1L;
	
	public IncentiveItemDiscount(){
		super.setId(0);
		this.itemCups = new Integer(0);
		this.itemDiscount = new Integer(0);
	}

	private Integer itemCups;
	
	private Integer itemDiscount;
	
	//省略get set 方法
	
	@Override
	public PromotionResultDto calculate(Map<Integer, Integer> selectedGoods, Integer repeatTimes,PromotionActivity promotionActivity,int orderAmount,List<ProductDetail> list) {
		// 单品折扣
		
		PromotionResultDto promotionResultDto=new PromotionResultDto();
		promotionResultDto.setId(promotionActivity.getId());
		promotionResultDto.setName(promotionActivity.getName());
		IncentiveItemDiscount incentiveItemDiscount=(IncentiveItemDiscount)promotionActivity.getPromotionTemplate().getIncentive();
		// 商品或商品类别的限制
		String promotionRule=promotionActivity.getPromotionTemplate().getLimitedProduct();
		
		int cups=0;
				
		//订单包含商品为不限时,选择价格最便宜的优惠
		if(promotionActivity.getPromotionTemplate().getTypes().equals(0)||promotionRule.equals("")||promotionRule==null){
			for (Map.Entry<Integer, Integer> entry : selectedGoods.entrySet()) {  
	            cups += entry.getValue();//订单中包含的总杯数
	        }
			//倍数
			if(promotionActivity.getPromotionTemplate().getMinCups()!=0){				
				cups=cups/promotionActivity.getPromotionTemplate().getMinCups();
			}
			
			//repeatTimes=0 不限制重复次数
			if(repeatTimes<cups && repeatTimes!=0){	
				int promotionProductPrice=getPromotionProductPrice(incentiveItemDiscount,list,repeatTimes);//优惠商品数的总价格
				promotionResultDto.setAmount(incentiveItemDiscount.getItemDiscount()*promotionProductPrice/100);	
				promotionResultDto.setTimes(repeatTimes);
			}else{				
				int promotionProductPrice=getPromotionProductPrice(incentiveItemDiscount,list,cups);//优惠商品数的总价格
				promotionResultDto.setAmount(incentiveItemDiscount.getItemDiscount()*promotionProductPrice/100);	
				promotionResultDto.setTimes(cups);
			}
			return promotionResultDto;
		}
		Integer relation=promotionActivity.getPromotionTemplate().getRelation();
		String[] rules = StringUtils.split(promotionRule, ",");			
		//and
		if(relation.equals(1)){
			//整除(订单中某商品的杯数/活动中此商品的最小杯数)
			if(promotionActivity.getPromotionTemplate().getCups()!=0){
    			cups=selectedGoods.get(Integer.parseInt(rules[0]))/promotionActivity.getPromotionTemplate().getCups();	
    			for(int i=0;i<rules.length;i++){
    				//取最小值
    				if((selectedGoods.get(Integer.parseInt(rules[i]))/promotionActivity.getPromotionTemplate().getCups())<cups){
    					cups=selectedGoods.get(Integer.parseInt(rules[i]))/promotionActivity.getPromotionTemplate().getCups();
    				}
    			}
			}
		}else{
			
			//or 或者 无关系时,即只选择了一种类型或者一种商品的情况
			cups=0;
			for(int i=0;i<rules.length;i++){
				//累加所有商品杯数
				if(null!=selectedGoods.get(Integer.parseInt(rules[i]))&&selectedGoods.get(Integer.parseInt(rules[i]))>=promotionActivity.getPromotionTemplate().getCups()){
					cups+=selectedGoods.get(Integer.parseInt(rules[i]));	
				}				
			}
			if(promotionActivity.getPromotionTemplate().getCups()!=0){
				cups=cups/promotionActivity.getPromotionTemplate().getCups();
			}
			
		}					
		
		//repeatTimes=0 不限制重复次数
		if(repeatTimes<cups && repeatTimes!=0){	
			int promotionProductPrice=getPromotionProductPrice(incentiveItemDiscount,list,repeatTimes);//优惠商品数的总价格
			promotionResultDto.setAmount(incentiveItemDiscount.getItemDiscount()*promotionProductPrice/100);	
			promotionResultDto.setTimes(repeatTimes);
		}else{				
			int promotionProductPrice=getPromotionProductPrice(incentiveItemDiscount,list,cups);//优惠商品数的总价格
			promotionResultDto.setAmount(incentiveItemDiscount.getItemDiscount()*promotionProductPrice/100);	
			promotionResultDto.setTimes(cups);
		}
		return promotionResultDto;
	}

	private int getPromotionProductPrice(IncentiveItemDiscount incentiveItemDiscount, List<ProductDetail> list,int cups) {
		//从list中找出优惠商品,进行优惠金额计算
		int promotionProductPrice=0;
		for(int i=0;i<cups*incentiveItemDiscount.getItemCups();i++){
			promotionProductPrice+=list.get(i).getPrice();
		}
		return promotionProductPrice;
	}

}

直减,整单折扣 省略...


优惠模板:

/**
 * @author hejingyuan
 *
 */
public class PromotionTemplate implements Serializable{


	private static final long serialVersionUID = 1L;
	
	private long id;
			
	private String name;
	
	private Integer minCups;

	private String limitedProduct;
		
	private AbstractIncentive incentive;
	
	//去掉部分属性及get set方法
}

策略模式应用:


优惠计算及结构:

                              技术分享



部分代码:

public TotalPromotionResultDto calcPromotion(long providerId, long cityId, long zoneId, int customerId,
			Map<Integer, Integer> selectedGoods, PurchaseFunction functionEntry, long platformId) {
		
		
		//根据开始时间从小到大排序
		List<PromotionActivity> activityList = selectPromotionActivities(providerId, cityId, zoneId,customerId,selectedGoods, functionEntry,
				platformId);
		logger.debug("acquire promotion activity. list.size:{}", activityList.size());
		if(activityList.size()==0||null==activityList){
			return null;
		}
		
		List<PromotionResultDto> results = new ArrayList<PromotionResultDto>();
		List<PromotionResultDto> result = new ArrayList<PromotionResultDto>();
		TotalPromotionResultDto totalPromotionResultDto=new TotalPromotionResultDto();
		int amount=0;
		for (PromotionActivity item : activityList) {
			PromotionActivity pa=promotionActivitySbo.loadPromotionActivityById(item.getId());
			// 商品id和对应杯数 或者 类别id和对应杯数
			Map<Integer, Integer> goods=ProductType(selectedGoods,item);
			//订单总金额(分)
			int orderAmount=getTotalAmount(selectedGoods);
			List<ProductDetail> list=mapToList(selectedGoods);
			PromotionResultDto pr = pa.calculatePromotionResult(goods,item.getRepeatTimes(),pa,orderAmount,list);
			logger.debug("calculate promotion activity. activityId:{}, amount:{}", pr.getId(), pr.getAmount());
			//如果优惠金额相同,再找开始时间最近的。最终选中一个优惠金额最大的(分)
			if(pr.getAmount()>amount){
				amount=pr.getAmount();
				results.add(0,pr);
			}
			//处理优惠金额大于订单总金额问题
			if(amount>orderAmount){
				amount=orderAmount;
			}
		}
		
		PromotionActivity promotionActivity=promotionActivityDaoProxy.get(results.get(0).getId());
		PromotionTemplate pt=promotionTemplateDaoProxy.get(promotionActivity.getPromotionTemplate().getId());
		
		Integer isFeeFree=pt.getIncentive().getFeeFree();
		
		if(isFeeFree.equals(0)){
			totalPromotionResultDto.setFeeFree(false);
		}else{
			totalPromotionResultDto.setFeeFree(true);
		}
		result.add(0, results.get(0));
		totalPromotionResultDto.setTotalFreeAmount(amount);
		totalPromotionResultDto.setPromotionList(result);
		return totalPromotionResultDto;
		
	}

public PromotionActivity loadPromotionActivityById(long promotionActivityId) {
		PromotionActivity promotionActivity=promotionActivityDaoProxy.get(promotionActivityId);
		
		PromotionTemplate pt=promotionTemplateDaoProxy.get(promotionActivity.getPromotionTemplate().getId());
		
		String incentiveType=pt.getIncentive().getIncentiveType();
		long id=pt.getIncentive().getIncentiveTypeId();
		switch(incentiveType){
		case "p"://直减			
			promotionActivity.setRebatesEngine(orderPricecutDaoProxy.get(id));
			break;
		case "o"://整单折扣			
			promotionActivity.setRebatesEngine(orderDiscountDaoProxy.get(id));
			break;	
		case "i"://单品优惠
			promotionActivity.setRebatesEngine(itemDiscountDaoProxy.get(id));
			break;	
		}

		return promotionActivity;
	}
public void setRebatesEngine(AbstractIncentive incentive){
        
         this.getPromotionTemplate().setIncentive(incentive);
    }

public PromotionResultDto calculatePromotionResult(Map<Integer, Integer> selectedGoods,Integer repeatTimes,PromotionActivity promotionActivity,int orderAmount,List<ProductDetail> list) {
		
		PromotionResultDto promotionResultDto;
		promotionResultDto = this.getRebatesEngine().calculate(selectedGoods, repeatTimes,promotionActivity,orderAmount,list);
		return promotionResultDto;
	}
public AbstractIncentive getRebatesEngine(){
        
        return  this.getPromotionTemplate().getIncentive();
    }

通过这个calculate方法,会调用各自的子类的实现即直减,整单折扣或者是单品折扣。如果不理解这句话,那么接着往下看...


多态:

多态,是面向对象的程序设计语言最核心的特征。多态,意味着一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。通俗的说,同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

从程序设计的角度而言,多态可以这样来实现

public interface Parent//父类接口
{
    public void simpleCall();
}
public class Child_A implements Parent
{
    public void simpleCall();
    {
    //具体的实现细节;
    }
}
 
public class Child_B implements Parent
{
    public void simpleCall();
    {
    //具体的实现细节;
    }
}

//当然还可以有其他的实现
然后,我们就可以看到多态所展示的特性了:
Parent pa = new Child_A();
pa.simpleCall()则显然是调用Child_A的方法;
Parent pa = new Child_B();
pa.simpleCall()则是在调用Child_B的方法。
所以,我们对于抽象的父类或者接口给出了我们的具体实现后,pa 可以完全不用管实现的细节,只访问我们定义的方法,就可以了。事实上,这就是多态所起的作用,可以实现控制反转这在大量的J2EE轻量级框架中被用到,比如Spring的依赖注入机制。

多态原理:当方法被调用时,无论对象是否被转换为其父类,都只有位于对象继承最末端的方法实现会被调用。也就是说它是按照其运行时类型而非编译时类型进行动态绑定调用的。




策略模式实战之优惠方式

原文:http://blog.csdn.net/hejingyuan6/article/details/50765621

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!