Customer :
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public abstract class Customer {
protected String name;
//用户入网的时间
private Date joinTime;
private int customerType = 0;
protected List<ActionRecord> actionRecords = new ArrayList<ActionRecord>();
//积累的结果只表示当月的所有通话记录,不代表所有历史记录
private ArrayList phoneRecords = new ArrayList();
//积累的结果只表示当月的所有短信记录,不代表所有历史记录
private ArrayList messageRecords = new ArrayList();
//积累的结果只表示当月的所有数据传送记录,不代表所有历史记录
private ArrayList dataRecords = new ArrayList();
protected PackStrategy packStrategy;
public void monthBegin(){
phoneRecords.clear();
messageRecords.clear();
dataRecords.clear();
actionRecords.clear();
}
public Customer(String name,Date joinTime,int customerType){
this.name = name;
this.joinTime = joinTime;
this.customerType = customerType;
}
public String toString(){
return name;
}
public void callPhone(int times){
phoneRecords.add(times);
actionRecords.add(new ActionRecord("打电话",times + "分钟"));
}
public void sendMessage(int numbers){
messageRecords.add(numbers);
actionRecords.add(new ActionRecord("发短信",numbers + "条"));
}
public void transferData(int size){
dataRecords.add(size);
actionRecords.add(new ActionRecord("传数据",size + "k"));
}
/**
*
* @param currentMonth 正在被计费处理的当月的日期,
* 注意:日字段设置为1,以便于方法内部计算是否是新用户
*/
public int countMonthMoney(Date currentMonth) {
boolean newcome = !joinTime.before(currentMonth);//after 之后,tomorrow
int totalPhone = gatherRecords(phoneRecords);
int totalMessage = gatherRecords(messageRecords);
int totalData = gatherRecords(dataRecords);
int freePhone = 0;
int freeMessage = 0;
int freeData = 0;
if(newcome){
freePhone = ConfigManager.getNewCustomerFree(customerType,0);//phone
freeMessage = ConfigManager.getNewCustomerFree(customerType,1);
freeData = ConfigManager.getNewCustomerFree(customerType,2);
}
int chargePhone = totalPhone>freePhone?totalPhone-freePhone:0;
int chargeMessage = totalMessage>freeMessage?totalMessage-freeMessage:0;
int chargeData = totalData>freeData?totalData-freeData:0;
//汇总打印:包括姓名,入网日期,统计月份,通话清单,费用清单,总费用。
System.out.println(name + "," + DateUtil.formatDateToDay(joinTime) + "入网.");
System.out.println(" 操作清单如下-----");
for(int i=0;i<actionRecords.size();i++){
System.out.println(" " + actionRecords.get(i));
}
System.out.println(" 统计清单如下-----");
System.out.println(" 通话:" + phoneRecords + "分钟:短信" + messageRecords + "条:数据" + dataRecords + "k");
System.out.println(" 通话累计:" + totalPhone + "分钟,减除新开户" + freePhone + "分钟,实际收费" + chargePhone + "分钟");
System.out.println(" 短信累计:" + totalMessage + "条,减除新开户" + freeMessage + "条,实际收费" + chargeMessage + "条");
System.out.println(" 数据累计:" + totalData + "k,减除新开户" + freeData + "k,实际收费" + chargeData + "k");
ComputeStrategy phoneStrategy = packStrategy.getValidPhonePack(currentMonth);
ComputeStrategy messageStrategy = packStrategy.getValidMessagePack(currentMonth);
ComputeStrategy dataStrategy = packStrategy.getValidDataPack(currentMonth);
int sum = 0;
//VIP用户才有月租金或基本费
Rent rent = packStrategy.getValidRent(currentMonth);
if(rent != null){
int rentMoney = rent.coputeRent(joinTime,currentMonth);
sum += rentMoney;
System.out.println(" 月租费或基本费:" + rentMoney + "厘钱");
}
sum += phoneStrategy.computeMoney(chargePhone);
sum += messageStrategy.computeMoney(chargeMessage);
sum += dataStrategy.computeMoney(chargeData/10);
System.out.println(" 总计:" + sum/1000f + "元钱");
return sum;
}
private int gatherRecords(ArrayList records) {
int sum = 0;
for(int i=0;i<records.size();i++){
sum += (Integer)(records.get(i));
}
return sum;
}
public abstract void randomCancelPack(Date month);
public abstract void randomOrderPack(Date month);
}
CommonCustomer :
import java.util.Date;
import java.util.Random;
public class CommonCustomer extends Customer {
public CommonCustomer(String name, Date joinTime) {
super(name, joinTime,0);//0----phone
//普通用户 基本
packStrategy = new PackStrategy(0,0,null);//customerType,packType,Rent
actionRecords.add(new ActionRecord(name, DateUtil.formatDateToDay(joinTime)+"入网"));
}
@Override
public void randomCancelPack(Date orderedMonth) {
int rand = new Random().nextInt(3);
switch(rand){
case 0:
/*if(packStrategy.getOrderedPhonePack() == null || packStrategy.getOrderedPhonePack().getPackType() == 0){
System.out.println(name + "试图退订根本就没有订过的电话套餐");
return;
}*/
packStrategy.cancelPhonePack(orderedMonth);
System.out.println(name + "退订了" + "电话套餐" + "(从" + DateUtil.formatDateToMonth(orderedMonth) + "开始)");
actionRecords.add(new ActionRecord("退订电话套餐",""));
break;
case 1:
/*if(packStrategy.getOrderedMessagePack() ==null || packStrategy.getOrderedMessagePack().getPackType() == 0){
System.out.println(name + "试图退订根本就没有订过的短信套餐");
return;
}*/
packStrategy.cancelMessagePack(orderedMonth);
System.out.println(name + "退订了" + "短信套餐" + "(从" + DateUtil.formatDateToMonth(orderedMonth) + "开始)");
actionRecords.add(new ActionRecord("退订短信套餐",""));
break;
case 2:
/* if(packStrategy.getOrderedDataPack()==null || packStrategy.getOrderedDataPack().getPackType() == 0){
System.out.println(name + "试图退订根本就没有订过的数据套餐");
return;
} */
packStrategy.cancelDataPack(orderedMonth);
System.out.println(name + "退订了" + "数据套餐" + "(从" + DateUtil.formatDateToMonth(orderedMonth) + "开始)");
actionRecords.add(new ActionRecord("退订数据套餐",""));
break;
}
}
@Override
public void randomOrderPack(Date month) {
int rand = new Random().nextInt(3);
switch(rand){
case 0:
//if(packStrategy.getOrderedPhonePack()==null || packStrategy.getOrderedPhonePack().getPackType() == 0){
packStrategy.orderPhonePack(month,1);
System.out.println(name + "订购了" + "电话套餐" + "(从" + DateUtil.formatDateToMonth(month) + "开始)");
actionRecords.add(new ActionRecord("定电话套餐",""));
//}
break;
case 1:
//if(packStrategy.getOrderedMessagePack() == null || packStrategy.getOrderedMessagePack().getPackType() == 0){
packStrategy.orderMessagePack(month,1);
System.out.println(name + "订购了" + "短信套餐" + "(从" + DateUtil.formatDateToMonth(month) + "开始)");
actionRecords.add(new ActionRecord("定短信套餐",""));
//}
break;
case 2:
//if(packStrategy.getOrderedDataPack() == null || packStrategy.getOrderedDataPack().getPackType() == 0){
packStrategy.orderDataPack(month,1);
System.out.println(name + "订购了" + "数据套餐" + "(从" + DateUtil.formatDateToMonth(month) + "开始)");
actionRecords.add(new ActionRecord("定数据套餐",""));
//}
break;
}
}
}
VIPCustomer :
import java.util.Date;
import java.util.Random;
public class VIPCustomer extends Customer {
public VIPCustomer(String name, Date joinTime) {
super(name,joinTime,1);
packStrategy = new PackStrategy(1,0,new Rent(200,RentUnit.DAY));
actionRecords.add(new ActionRecord(name, DateUtil.formatDateToDay(joinTime)+"入网"));
}
public void orderPack1(Date month){
/* if(packStrategy.getOrderedPhonePack()==null || packStrategy.getOrderedPhonePack().getPackType() != 1)
{ */
packStrategy.orderRent(month,new Rent(10000,RentUnit.MONTH));
packStrategy.orderPhonePack(month,1);
packStrategy.orderMessagePack(month,1);
packStrategy.orderDataPack(month,1);
System.out.println(name+ "订购了套餐1" + "(从" + DateUtil.formatDateToMonth(month) + "开始)" );
actionRecords.add(new ActionRecord("订购套餐1",""));
//}
}
public void orderPack2(Date month){
/* if(packStrategy.getOrderedPhonePack() ==null || packStrategy.getOrderedPhonePack().getPackType() != 2)
{*/
packStrategy.orderRent(month,new Rent(20000,RentUnit.MONTH));
packStrategy.orderPhonePack(month,2);
packStrategy.orderMessagePack(month,2);
packStrategy.orderDataPack(month,2);
System.out.println(name+ "订购了套餐2" + "(从" + DateUtil.formatDateToMonth(month) + "开始)" );
actionRecords.add(new ActionRecord("订购套餐2",""));
//}
}
public void randomCancelPack(Date orderedMonth){
/*
if(packStrategy.getOrderedPhonePack() ==null ||
packStrategy.getOrderedPhonePack().getPackType() == 0){
System.out.println(name + "试图退订根本就没有订过的套餐"); return; }
*/
packStrategy.orderRent(orderedMonth, new Rent(200, RentUnit.DAY));
packStrategy.orderPhonePack(orderedMonth, 0);
packStrategy.orderMessagePack(orderedMonth, 0);
packStrategy.orderDataPack(orderedMonth, 0);
System.out.println(name + "退订了" + "套餐" + "(从"
+ DateUtil.formatDateToMonth(orderedMonth) + "开始)");
actionRecords.add(new ActionRecord("退定套餐", ""));
}
@Override
public void randomOrderPack(Date month) {
//如果以前订购过某套餐,现在仍然可以重新订购该套餐
int randType = (new Random().nextInt(10))%2;
if(randType == 0){
orderPack1(month);
}else if(randType == 1){
orderPack2(month);
}
}
}
Rent :
import java.util.Calendar;
import java.util.Date;
/**
* 只有VIP有月租 2元/天
* @author ETHAN
*
*/
public class Rent {
private int price;
private RentUnit unit = RentUnit.MONTH;
public Rent(int price,RentUnit unit){
this.price = price;
this.unit = unit;
}
public int coputeRent(Date startTime,Date currentMonth){
//首先应该想到去找开源的日期运算类
if(unit == RentUnit.DAY){
Calendar start = Calendar.getInstance();
start.setTime(startTime);
Calendar end = Calendar.getInstance();
end.setTime(currentMonth);
//将日期设置为当月的第一天
end.set(Calendar.DAY_OF_MONTH, 1);
//增加 得到下一个月份的第一天
end.add(Calendar.MONTH, 1);
//比如 3月一号 - 1 = 2月的最后一天(28 || 29)
end.add(Calendar.DAY_OF_MONTH, -1);
//这个月总天数 DAY_OF_MONTH month==2
int days = end.get(Calendar.DAY_OF_MONTH) ;
//如果在同一月份,则计算实际天数
if(end.get(Calendar.MONTH) == start.get(Calendar.MONTH)){
days -= start.get(Calendar.DAY_OF_MONTH) + 1;
}
return price*days;
}
else{
return price;
}
}
}
RentUnit :
/**
* 月租 按天 还是按月
* @author ETHAN
*
*/
public enum RentUnit {
DAY,MONTH
}
IdGenerator :
/**
* 为新用户生成新Id编号的类
* @author ETHAN
*
*/
public class IdGenerator {
private IdGenerator(){
}
private static IdGenerator instance = new IdGenerator();
public static IdGenerator getInstance(){
return instance;
}
private int lastCommonId = 15;
private int lastVipId = 5;
public synchronized int nextCommonId(){
return ++lastCommonId;
}
public synchronized int nextVipId(){
return ++lastVipId;
}
}
移动公司类MobileCorporation :
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
public class MobileCorporation {
private ArrayList<Customer> customers = new ArrayList<Customer>();
Calendar calendar = Calendar.getInstance();
public MobileCorporation(){
calendar.set(2012, 0, 1);//2012/1/1
for(int i=1;i<=15;i++){
customers.add(
new CommonCustomer(i+"号普通客户",calendar.getTime())
);
}
for(int i=1;i<=5;i++){
customers.add(
new VIPCustomer(i+"号VIP客户",calendar.getTime())
);
}
System.out.println("程序创建了运营商已有的5个VIP用户和15个普通用户,并设置他们的入网日期为2012年1月1日.");
}
//模拟某个月的业务活动
public void simulationBusiness(Date month){
for(Customer customer : customers){
customer.monthBegin();
}
System.out.println("--------being simulating " + DateUtil.formatDateToMonth(month) + "--------------");
for(int i=0;i<500;i++){
randDoOneThing(month);
}
System.out.println(DateUtil.formatDateToMonth(month)+"的计费汇总清单:");
//汇总所有人的账单
for(int i=0;i<customers.size();i++){
customers.get(i).countMonthMoney(month);
}
}
/**
* 随机调用下面的某一个方法
* */
private void randDoOneThing(Date month){
Calendar calendar = Calendar.getInstance();
calendar.setTime(month);
calendar.add(Calendar.MONTH, 1);
Date monthOfOrderPack = calendar.getTime();
/*让orderPack、cancelPack、joinNewCustomer的出现概率是其他操作的1/20。*/
int rand = new Random().nextInt(63);
if(rand>=0 && rand<20){
callPhone();
}
else if(rand>=20 && rand<40){
sendMessage();
}
else if(rand>=40 && rand<60){
transferData();
}else{
switch(rand){
case 60:
orderPack(monthOfOrderPack);
break;
case 61:
cancelPack(monthOfOrderPack);
break;
case 62:
joinNewCustomer(month);
break;
}
}
}
/**
* 随机选中一个用户,让其随机拨打的电话时长为1至10分钟不等
*/
private void callPhone(){
int rand = new Random().nextInt(customers.size());
Customer customer = customers.get(rand);
int phoneTimes = new Random().nextInt(10) + 1;
customer.callPhone(phoneTimes);
System.out.println(customer + "打了" + phoneTimes + "分钟电话");
}
/**
* 随机选中一个用户,让其随机发送的短信数目为1至10条不等
*/
private void sendMessage(){
int rand = new Random().nextInt(customers.size());
Customer customer = customers.get(rand);
int messageNumbers = new Random().nextInt(10) + 1;
customer.sendMessage(messageNumbers);
System.out.println(customer + "发了" + messageNumbers + "条短信");
}
/**
* 随机选中一个用户,让其随机获取的数据流量为50K,100K,200K,500K,1M
*/
private void transferData(){
int rand = new Random().nextInt(customers.size());
Customer customer = customers.get(rand);
int [] dataSize = new int[]{50,100,200,500,1000};
int randSizeKey = new Random().nextInt(5);
customer.transferData(dataSize[randSizeKey]);
System.out.println(customer + "传送了" + dataSize[randSizeKey] + "k数据");
}
/**
* 随机选中一个用户,为其随机订购一款套餐
*/
private void orderPack(Date month){
int rand = new Random().nextInt(customers.size());
customers.get(rand).randomOrderPack(month);
}
/**
* 随机选中一个用户,并将其已经有的套餐取消
*/
private void cancelPack(Date month){
int rand = new Random().nextInt(customers.size());
customers.get(rand).randomCancelPack(month);
}
private void joinNewCustomer(Date month){
Calendar calendar = Calendar.getInstance();
calendar.setTime(month);
int maxDay = calendar.getMaximum(Calendar.DAY_OF_MONTH);
int randDay = new Random().nextInt(maxDay) + 1;
/*下面的复制过程很重要,不能直接修改date,当然最好是对Calendar直接操作
* 这里是为了演示要注意clone而保留的。
*/
//随机的入户时间,和初始化的用户入网时间不一样了,所以boolean newcome 不一样
Date joinTime = (Date)month.clone();
joinTime.setDate(randDay);
int randType = (new Random().nextInt(10))%2;
Customer customer = null;
if(randType == 0){
int commonId = IdGenerator.getInstance().nextCommonId();
customer = new CommonCustomer(commonId+"号普通客户",joinTime);
customers.add(customer);
}else{
int vipId = IdGenerator.getInstance().nextVipId();
customer = new VIPCustomer(vipId+"号VIP客户",joinTime);
customers.add(customer);
}
System.out.println(DateUtil.formatDateToDay(joinTime) + "新注册了" + customer);
}
}
运行类:
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
/*
* 由于电信和银行实际环境的复杂性和产品一旦上线运行后对错误的容忍度几乎为0,所以,电信和银行的项目在做完后都不能直接上线测试运行,
* 而是要通过编写非常完善的模拟程序来进行测试,确保万无一失后再实际上线运行,所以,为电信和银行项目编写模拟程序和比对检查程序运行的结果就非常重要了。
*/
public class MainClass {
public static void main(String[] args) {
MobileCorporation corp = new MobileCorporation();
//设置要模拟的起始月份
Date month = new Date(112,0,1);
System.out.println("程序开始模拟从2012年1月1日开始,连续15个月的运行情况.");
//总共模拟15个连续的月份
for(int i=0;i<15;i++){
corp.simulationBusiness(month);
Calendar calendar = Calendar.getInstance();
calendar.setTime(month);
calendar.add(Calendar.MONTH, 1);
month = calendar.getTime();
}
}
}