场景:设计一个交易系统中的子模块------扣款子模块
扣款子模块中主要包括两部分:
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)模式:负责对复杂的扣款系统进行封转,封转的结果就是避免高层模块深入子系统内部,同时提供系统高内聚、低耦合的特性。