(1)一张IC卡绑定两个账户:固定账户和自由账户。
(2)两套交易扣款策略:
固定消费场所下的消费是从IC卡中固定账户金额中扣除,当固定金额不够时,差额再从自由账户中扣除。
非固定消费场所下的消费都从IC卡中自由账户金额中扣除。
(3)IC卡交易扣款系统使用了以下几个模式 :
策略模式:负责对扣款策略进行封装,保证两个策略可以自由切换,也便于对扣款策略进行扩展。例如,增加一个新的扣款策略,只需三步就可以完成,先定义一个实现IDeduction接口的策略类,再在策略枚举StrategyMan中增加一个枚举项,最后在封装类DeductionFacade的getDeductionType()方法中增加对扣款策略的利用。
工厂方法模式:由工厂方法模式直接产生一个具体策略对象,使其他模块无需依赖具体的策略。
外观模式:负责对复杂的扣款系统进行封装,避免高层模块深入子系统内部细节,同时提高系统的高内聚、低耦合的特性。
package 交易;
//IC卡类
public class Card {
private String cardNo="";
private int steadyMoney=0;
private int freeMoney=0;
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
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;
}
}
package 交易;
//交易信息Trade类
public class Trade {
private String tradeNo="";
private int amount=0;
public String getTradeNo() {
return tradeNo;
}
public void setTradeNo(String tradeNo) {
this.tradeNo = tradeNo;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
package 交易;
//扣款接口,策略模式:两种策略:固定扣款和自由扣款
public interface IDeduction {
//扣款,提供交易和卡信息,进行扣款,并返回扣款是否成功
boolean exec(Card card,Trade trade);
}
package 交易;
public class SteadyDeduction implements IDeduction {
@Override
public boolean exec(Card card, Trade trade) {
int useMoney1=trade.getAmount();
if(useMoney1>card.getSteadyMoney()){
int useMoney2=(card.getSteadyMoney()-useMoney1);
card.setSteadyMoney(card.getSteadyMoney()-card.getSteadyMoney());
card.setFreeMoney(card.getFreeMoney()+useMoney2);
}
else{
card.setSteadyMoney(card.getSteadyMoney()-useMoney1);
}
return true;
}
}
package 交易;
public class FreeDeduction implements IDeduction {
@Override
public boolean exec(Card card, Trade trade) {
card.setFreeMoney(card.getFreeMoney()-trade.getAmount());
return true;
}
}
package 交易;
//封装角色,策略上下文
public class DeductionContext {
private IDeduction deduction=null;
public DeductionContext(IDeduction deduction){
this.deduction=deduction;
}
public boolean exec(Card card,Trade trade){
return this.deduction.exec(card, trade);
}
}
package 交易;
//负责对具体策略的映射,具体策略都在这里登记,然后提供给工厂方法模式。
public enum StrategyMan{
SteadyDeduction("交易.SteadyDeduction"),
FreeDeduction("交易.FreeDeduction");
String value="";
private StrategyMan(String value){
this.value=value;
}
public String getValue(){
return value;
}
}
package 交易;
//策略工厂,根据策略管理类的枚举创建一个策略对象
public class StrategyFactory {
public static IDeduction getDeduction(StrategyMan strategy){
IDeduction deduction=null;
try{
deduction=(IDeduction)Class.forName(strategy.getValue()).newInstance();//newInstance方法在内存中生成一个实例
}
catch(InstantiationException|IllegalAccessException|ClassNotFoundException e){
e.printStackTrace();
}
return deduction;
}
}
package 交易;
public class DeductionFacade {
//对外公布的扣款信息
public static Card deduct(Card card,Trade trade){
//获得消费策略
StrategyMan reg=getDeductionType(trade);
//初始化一个消费策略对象
IDeduction deduction=StrategyFactory.getDeduction(reg);
//产生一个策略上下文
DeductionContext context=new DeductionContext(deduction);
//进行扣款处理
context.exec(card, trade);
//返回扣款处理完毕后的数据
return card;
}
//获得对应的商户消费策略
private static StrategyMan getDeductionType(Trade trade) {
if(trade.getTradeNo().contains("abc")){
return StrategyMan.FreeDeduction;
}else{
return StrategyMan.SteadyDeduction;
}
}
}
package 交易;
import java.io.IOException;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
//初始化一张IC卡
Card card=initIC();
//显示卡信息
System.out.println("======初始卡信息======");
showCard(card);
//是否停止运行标志
boolean flag=true;
while(flag){
Trade trade=createTrade();
DeductionFacade.deduct(card, trade);
//交易成功打印出成功处理信息
System.out.println("\n======交易凭证======");
System.out.println(trade.getTradeNo()+"交易成功");
System.out.println("本次发生的交易金额为:"+trade.getAmount()*100/100.0+"元");
//展示卡内的信息
showCard(card);
System.out.print("\n是否需要退出?(Y/N)");
if(getInput().equalsIgnoreCase("y")){
flag=false;//退出
}
}
}
private static String getInput() {
Scanner input=new Scanner(System.in);
String str=input.next();
return str;
}
private static Trade createTrade() {
Trade trade=new Trade();
System.out.print("请输入交易编号:");
trade.setTradeNo(getInput());
System.out.print("请输入交易金额:");
trade.setAmount(Integer.parseInt(getInput()));
return trade;
}
private static void showCard(Card card) {
System.out.println("IC卡编号:"+card.getCardNo());
System.out.println("固定类型金额:"+card.getSteadyMoney());
System.out.println("自由类型金额:"+card.getFreeMoney());
}
private static Card initIC() {
Card card=new Card();
card.setCardNo("1100010001000");
card.setSteadyMoney(10000);
card.setFreeMoney(80000);
return card;
}
}