设计模式-策略模式和工厂模式结合使用

  • 怎么把策略模式和工厂模式结合起来使用

如果大家对策略模式和工厂模式不是很了解的话可以先看前面文章
策略模式:https://www.jianshu.com/p/958281936901
工厂模式:https://www.jianshu.com/p/9078481e00c6

大家可能都用过微信支付,在使用微信支付付钱时候:

1、当我们的付款金额大于我们的余额时,会让我们使用银行卡支付,
2、余额充足的时候会让我们优先使用余额里面的钱
扣款策略一:
余额(blance) >= 付款金额(tradeAmout) 使用余额
扣款策略二:
余额(blance) < 付款金额(tradeAmout) 使用银行卡
很明显这是一个策略模式的实际应用,但是你还记得策略模式的缺陷吗?它的具体策略必须暴露出去,而且还要由上层模块初始化,这不适合,与迪米特法则不符( 迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),就是说一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。注:摘自百度百科,这个迪米特法则下次再细讲)冲突。高层模块对底层模块仅仅在接触层次上,而不应该是耦合关系。问题出了,我们应该想办法解决,正好工厂模式可以帮我们解决这个问题。但是引入工厂模式也有问题,工厂方法要指定一个类,它才能生产对象,我们用枚举来完成。
首先我们先建两个实体类WxBlance和WxTrade

import java.math.BigDecimal;

/**
 * @author shuliangzhao * @Title: WxBlance * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:50 */ public class WxBlance { //余额 private BigDecimal blance; public BigDecimal getBlance() { return blance; } public void setBlance(BigDecimal blance) { this.blance = blance; } } 
import java.math.BigDecimal;

/**
 * @author shuliangzhao * @Title: Trade * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:51 */ public class WxTrade { private BigDecimal tradeAmout; private String tradeNo; private BigDecimal userAmout; public BigDecimal getUserAmout() { return userAmout; } public void setUserAmout(BigDecimal userAmout) { this.userAmout = userAmout; } public String getTradeNo() { return tradeNo; } public void setTradeNo(String tradeNo) { this.tradeNo = tradeNo; } public BigDecimal getTradeAmout() { return tradeAmout; } public void setTradeAmout(BigDecimal tradeAmout) { this.tradeAmout = tradeAmout; } } 

扣款策略接口

/**
 * @author shuliangzhao * @Title: Deduction * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:53 */ public interface Deduction { public boolean exec(WxBlance wxBlance,WxTrade wxTrade); } 

扣款策略一

/**
 * @author shuliangzhao * @Title: BlanceDeduction * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:54 */ public class BlanceDeduction implements Deduction { @Override public boolean exec(WxBlance wxBlance, WxTrade wxTrade) { if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) >= 0) { wxTrade.setUserAmout(wxBlance.getBlance()); } return true; } } 

扣款策略二

/**
 * @author shuliangzhao * @Title: IdCardDeduction * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:54 */ public class IdCardDeduction implements Deduction { @Override public boolean exec(WxBlance wxBlance, WxTrade wxTrade) { if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) < 0) { wxTrade.setUserAmout(wxTrade.getTradeAmout()); } return true; } } 

扣款策略封装

/**
 * @author shuliangzhao * @Title: DedutionContext * @ProjectName design-parent * @Description: TODO * @date 2019/5/28 23:58 */ public class DedutionContext { private Deduction deduction; public DedutionContext(Deduction deduction) { this.deduction = deduction; } public boolean exec(WxBlance wxBlance,WxTrade wxTrade) { return deduction.exec(wxBlance,wxTrade); } } 

典型的策略上下文。策略模式的缺陷把所有策略类都暴露出去,怎么修改呢?使用工厂模式根据映射产生策略对象

策略枚举

/**
 * @author shuliangzhao * @Title: StrategyEnum * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:00 */ public enum StrategyEnum { BlanceDeduction("com.sl.factorystrategy.BlanceDeduction"), IdCardDeduction("com.sl.factorystrategy.IdCardDeduction"); String value = ""; private StrategyEnum(String value) { this.value = value; } public String getValue() { return value; } } 

策略工厂

/**
 * @author shuliangzhao * @Title: StrategyFactory * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:03 */ public class StrategyFactory { public static Deduction getDeduction(StrategyEnum strategyEnum) { Deduction deduction = null; try { deduction = (Deduction)Class.forName(strategyEnum.getValue()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return deduction; } } 

扣款调用类

/**
 * @author shuliangzhao * @Title: DeductionFacade * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:06 */ public class DeductionFacade { //扣款 public static void deduct(WxBlance wxBlance,WxTrade wxTrade) { StrategyEnum strate = getStrate(wxBlance, wxTrade); Deduction deduction = StrategyFactory.getDeduction(strate); deduction.exec(wxBlance,wxTrade); } //获取扣款策略 private static StrategyEnum getStrate(WxBlance wxBlance,WxTrade wxTrade) { if (wxBlance.getBlance().compareTo(wxTrade.getTradeAmout()) < 0) { return StrategyEnum.IdCardDeduction; }else { return StrategyEnum.BlanceDeduction; } } } 

调用客户端client

/**
 * @author shuliangzhao * @Title: Client * @ProjectName design-parent * @Description: TODO * @date 2019/5/29 0:10 */ public class Client { public static void main(String[] args) { WxTrade wxTrade = new WxTrade(); wxTrade.setTradeAmout(new BigDecimal("1000")); WxBlance wxBlance = new WxBlance(); wxBlance.setBlance(new BigDecimal("999")); DeductionFacade.deduct(wxBlance,wxTrade); System.out.println(wxTrade.getUserAmout()); } } 

执行结果

 

小结:
策略模式:负责对扣款封装,保证两个策略自由切换,以后增加策略也很容易

工厂模式:修正策略模式必须对外暴露问题,由工厂模式产生一个具体策略对象

猜你喜欢

转载自www.cnblogs.com/treeshu/p/10959615.html