场景:设计一个交易系统中的子模块------扣款子模块
扣款子模块中主要包括两部分:
1.IC卡类和交易信息类
其中IC卡中包括两种金额:固定金额和自由金额;交易信息类负责记录每一笔交易。
2.扣款策略类
扣款策略有以下两种:
a. IC卡固定金额 = IC卡现有固定金额-交易金额/2
IC卡自由金额 = IC卡自由金额-交易金额/2
b. 全部消费从IC卡自由金额中扣除
类图实现:
主要涉及如下几个角色:
1.IC卡类和交易类
2.扣款策略接口
3.扣款策略的封装类
4.策略枚举类
5.策略工厂
6.扣款模块封装
7.场景类
代码实现
Card类:
package org.apache.java.designpatter.factoryandstrategy; public class Card { private String No; private int steadyMoney; //卡内固定交易金额 private int freeMoney; //卡内自由交易金额 public String getNo() { return No; } public void setNo(String no) { No = no; } public int getSteadyMoney() { return steadyMoney; } public void setSteadyMoney(int steadyMoney) { this.steadyMoney = steadyMoney; } public int getFreeMoney() { return freeMoney; } public void setFreeMoney(int freeMoney) { this.freeMoney = freeMoney; } }
Trade类:
public class Trade { private String tradeNo; private int mount; //交易金额 public String getTradeNo() { return tradeNo; } public void setTradeNo(String tradeNo) { this.tradeNo = tradeNo; } public int getMount() { return mount; } public void setMount(int mount) { this.mount = mount; } }
扣款策略接口
public interface IDeduction { public boolean exec(Card card, Trade trade); }
扣款策略类
public class SteadyDeduction implements IDeduction { public boolean exec(Card card, Trade trade) { int halfMoney = (int) Math.rint(trade.getMount() / 2.0); card.setSteadyMoney(card.getSteadyMoney() - halfMoney); card.setFreeMoney(card.getFreeMoney() - halfMoney); return true; } } public class FreeDeduction implements IDeduction { public boolean exec(Card card, Trade trade) { card.setFreeMoney(card.getFreeMoney() - trade.getMount()); return true; } }
扣款策略封装
public class DeductionContext { private IDeduction deduction; public DeductionContext(IDeduction deduction) { this.deduction = deduction; } public boolean exec(Card card, Trade trade) { return this.deduction.exec(card, trade); } }
策略枚举
public enum StrategyManage { SteadyDeduction("org.apache.java.designpatter.factoryandstrategy.SteadyDeduction"), FreeDeducation("org.apache.java.designpatter.factoryandstrategy.FreeDeduction"); String value = ""; private StrategyManage(String value) { this.value = value; } public String getValue() { return value; } }
策略工厂
public class StrategyFactory { public static IDeduction getDeduction(StrategyManage strategy) { IDeduction deduction = null; try { deduction = (IDeduction) Class.forName(strategy.getValue()).newInstance(); } catch (Exception e) { e.printStackTrace(); } return deduction; } }
扣款模块封装
public class DeductionFacade { public static Card deduct(Card card, Trade trade) { StrategyManage reg = getDeducationType(trade); //获得消费策略 IDeduction deduction = StrategyFactory.getDeduction(reg); //初始化一个消费策略 对象 DeductionContext context = new DeductionContext(deduction); //执行封装 context.exec(card, trade); //执行扣款 return card; } private static StrategyManage getDeducationType(Trade trade) { if (trade.getTradeNo().contains("abc")) { return StrategyManage.FreeDeducation; }else { return StrategyManage.SteadyDeduction; } } }
场景类
public class Client { private static Card initCard() { Card card = new Card(); card.setNo(""); card.setFreeMoney(0); card.setSteadyMoney(0); return card; } private static Trade initTrade() { Trade trade = new Trade(); trade.setMount(0); trade.setTradeNo(""); return trade; } public static void main(String[] args) { Card card = initCard(); boolean flag = true; while (flag) { Trade trade = initTrade(); DeductionFacade.deduct(card, trade); } } }
在该场景中用到如下几个设计模式:
策略(strategy)模式:负载对扣款策略进行封装,保证了两个策略可以自由的切换。
工厂(factory)模式:修正策略模式必须对外暴露具体策略的问题,由工厂模式直接产生一个具体策略对象,其他模块则不需要依赖具体策略。
门面(facade)模式:负责对复杂的扣款系统进行封转,封转的结果就是避免高层模块深入子系统内部,同时提供系统高内聚、低耦合的特性。