Java面向对象综合实战——嗖嗖移动大厅
主页上传文件有源码
1.项目需求
- 嗖嗖移动是一个假定的通信运营商,提供了话痨套餐、网虫套餐、超人套餐,各种套餐所包含服务内容及资费如表所示:
嗖嗖移动套餐服务内容及资费
品牌套餐 | 话痨套餐 | 网虫套餐 | 超人套餐 |
---|---|---|---|
通话时长(分钟) | 500 | / | 200 |
上网流量(GB) | / | 3 | 1 |
短信条数(条) | 30 | / | 50 |
资费(元/月) | 58 | 68 | 78 |
- 计费规则:如实际使用中超出套餐内包含的通话时长、短信条数或上网流量,按以下规则计费。
- 超出的通话:0.2元/分钟
- 超出的短信:0.1元/条
- 超出的上网流量:0.1元/MB
- 功能介绍:
菜单级别 | 功能 | 描述 |
---|---|---|
主菜单 | 用户登录 | 输入正确的手机卡号和密码可进入二级菜单列表 |
主菜单 | 用户注册 | 录入信息并开卡,用户输入的信息包括选择卡号、选择套餐类型、输入用户的用户名和密码、预存话费金额(预存话费金额必须足以支付所选套餐一个月的资费) |
主菜单 | 使用嗖嗖 | 输入正确的手机卡号和密码后,随即进入本卡号所属套餐可支持的一个场景、消费套餐余量或话费余额,并记录消费信息。当话费余额不足, |
主菜单 | 话费充值 | 输入正确的用户名和密码后,可谓该卡号充值(单次充值最低50元) |
主菜单 | 资费说明 | 提供个品牌套餐所包含的通话时长、上网流量、短信条数、月资费等信息 |
主菜单 | 退出系统 | 推出本系统 |
二级菜单 | 本月账单查询 | 可查询该卡号的套餐资费、实际消费金额、账户余额 |
套餐余量查询 | 可查询该卡号的套餐余量 | |
二级菜单 | 打印消费详单 | 输入正确的卡号和密码,可打印当前卡号用户的消费详单 |
二级菜单 | 套餐变更 | 可变更其他套餐,变更后话费余额须减去变更后的套餐资费,余额不足时须给出信息提示,套餐变更后重新统计卡中实际消费数据以及当月消费金额 |
二级菜单 | 办理退网 | 输入正确的卡号和密码后,可从已注册卡号列表中删除本卡号,并退出系统 |
- 环境准备:我的运行环境为:
- jdk11.0.8
- IntelliJ IDEA 2020
2.项目实现
为实现程序的可维护性和可拓展性,采用面向对象的细想进行整体构架的设计
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BeeKH5D5-1647423765522)(…/images/1647411722927.png)]
1)创建类
(省略Getter/Setter和不需要特殊赋值的构造方法,idea快捷键ait+insert一键生成没有不知道的吧)
-
手机卡类(MobileCard):
package entity; /** * 嗖嗖移动卡 */ public class MobileCard { private String cardNumber; //卡号 private String userName; //用户名 private String passWord; //密码 private ServicePackage serPackage; //所属套餐 private double consumAmount; //当月消费金额 private double money; //账户余额 private int realTalkTime; //当月实际通话时长 private int realSMSCount; //当月实际发送短信条数 private int realFlow; //当月实际上网流量 //展示卡号信息 public void showMeg(){ System.out.println("卡号:"+this.cardNumber+",用户名:"+this.userName+",当前余额:"+this.money+"元"); this.serPackage.showInfo(); }
-
业务套餐类(ServicePackage):
package entity; /** * 业务套餐 抽象类 包含网虫套餐,话痨套餐,超人套餐 */ public abstract class ServicePackage { private double price; //套餐月资费 //展示套餐信息 public abstract void showInfo(); }
-
消费信息类(ConsumInfo):
package entity; /** * 消费记录 */ public class ConsumInfo { private String cardNumber; //卡号 private String type; //消费类型 private int consumData; //消费数据 }
-
使用场景类(Scene):
package entity; /** * 使用场景 */ public class Scene { private String type; //场景类型 private int data; //场景消费数据 private String description; //场景描述 }
2)创建接口:
-
通话接口(CallService):
package service; import entity.MobileCard; //通话服务 public interface CallService { /** * 通话 * @param minCount 通话分钟数 * @param card 超出套餐内的通话时长时需消费哪张卡的余额 */ int call(int minCount, MobileCard card)throws Exception; }
-
短信接口(SendService):
package service; import entity.MobileCard; //短信服务 public interface SendService { /** * 发短信 * @param count 短信数 * @param card 超过套餐范围短信需要使用哪张卡付费 */ int send(int count, MobileCard card)throws Exception; }
-
上网接口(NetService):
package service; import entity.MobileCard; //上网服务 public interface NetService { /** * 上网 * @param flow 上网流量 * @param card 超出套餐流量部分需要使用哪张卡余额 */ int netPlay(int flow, MobileCard card)throws Exception; }
3)创建业务套餐实体类的子类
-
话痨套餐类(TalkPackage):
package entity; import service.CallService; import service.SendService; /** * 话痨套餐 */ public class TalkPackage extends ServicePackage implements CallService, SendService { private int talkTime; //通话时长 private int smsCount; //可发送短信条数 //构造方法设置卡套餐内容 public TalkPackage() { this.talkTime=200; this.smsCount=50; super.setPrice(58); } @Override public void showInfo() { System.out.println("话痨套餐: 通话时长为"+this.talkTime+"分钟/月,短信条数为"+this.smsCount+"条/月,上网流量为"+0+"GB/月"); } @Override public int call(int minCount, MobileCard card) throws Exception { // 重写通话接口功能 获得套餐使用详情 int temp = 0;// 实际消耗分钟数 // 循环判断使用详情 for (int i = 0; i < minCount; i++) { // 第一种情况 套餐余额充足还可支持1分钟通话 if (this.getTalkTime() - card.getRealTalkTime() >= 1) { card.setRealTalkTime(card.getRealTalkTime() + 1);// 实际通话数据+1 temp++; } else if (card.getMoney() >= 0.2) { // 情况二:套餐通话时长已经用完,但是账户余额还可以支持1分钟通话,直接使用账户余额支付 card.setRealTalkTime(card.getRealTalkTime() + 1);// 实际使用通话时长分钟+1 temp++; // 剩余金额减少0.2元 card.setMoney(card.getMoney() - 0.2); // 总消费增加0.2元 card.setConsumAmount(card.getConsumAmount() + 0.2); } else { try { throw new Exception("本次已通话" + temp + "分钟,您的余额已不足,请充值后在使用!"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { // 报错结束返回一个实际通话时长 return temp; } } } return temp;// 返回一个实际通话时长s } @Override public int send(int count, MobileCard card) throws Exception { // 重写短信接口功能 获得套餐使用详情 int temp = 0;// 实际消耗短信次数 // 循环判断使用详情 for (int i = 0; i < count; i++) { // 第一种情况 套餐余额充足还可支持发送1次短信 if (this.getSmsCount() - card.getRealSMSCount() >= 1) { card.setRealSMSCount(card.getRealSMSCount() + 1);// 实际短信数据+1 temp++; } else if (card.getMoney() >= 0.1) { // 情况二:套餐短信次数已经用完,但是账户余额还可以支持发一次短信,直接使用账户余额支付 card.setRealSMSCount(card.getRealSMSCount() + 1);// 实际短信数据+1 temp++; // 剩余金额减少0.1元 card.setMoney(card.getMoney() - 0.1); // 总消费增加0.1元 card.setConsumAmount(card.getConsumAmount() + 0.1); } else { try { throw new Exception("本次已发送" + temp + "次短信,您的余额已不足,请充值后在使用!"); } catch (Exception e) { e.printStackTrace(); } finally { // 报错结束返回一个实际短信次数 return temp; } } } return temp;// 返回一个实际短信次数 } }
-
网虫套餐类(NetPackage):
package entity; import service.NetService; /** * 网虫套餐 */ public class NetPackage extends ServicePackage implements NetService{ private int flow; //上网流量 public NetPackage() { this.flow=5*1024; super.setPrice(68); } @Override public void showInfo() { System.out.println("话痨套餐: 通话时长为"+0+"分钟/月,短信条数为"+0+"条/月,上网流量为"+(this.flow/1024.0)+"GB/月"); } @Override public int netPlay(int flow, MobileCard card) throws Exception { // 重写上网接口功能 获得套餐使用详情 int temp = 0;// 实际消耗流量数据 // 循环判断使用详情 for (int i = 0; i < flow; i++) { // 第一种情况 套餐余额充足还可以使用1MB的流量 if (this.getFlow() - card.getRealFlow() >= 1) { card.setRealFlow(card.getRealFlow() + 1); ;// 实际流量数据+1 temp++; } else if (card.getMoney() >= 0.1) { // 情况二:套餐剩余流量已经用完,但是账户余额还可以支持使用1MB流量,直接使用账户余额支付 card.setRealSMSCount(card.getRealSMSCount() + 1);// 实际流量数据+1 temp++; // 剩余金额减少0.1元 card.setMoney(card.getMoney() - 0.1); // 总消费增加0.1元 card.setConsumAmount(card.getConsumAmount() + 0.1); } else { try { throw new Exception("本次已使用" + temp + "MB的流量,您的余额已不足,请充值后在使用!"); } catch (Exception e) { e.printStackTrace(); } finally { // 报错结束返回一个实际流量数据 return temp; } } } return temp;// 返回一个实际流量数据 } }
-
超人套餐类(SuperPackage):
package entity; import service.CallService; import service.NetService; import service.SendService; /** * 超人套餐 */ public class SuperPackage extends ServicePackage implements CallService, SendService , NetService { private int talkTime; //通话时长 private int smsCount; //可发送短信条数 private int flow; //上网流量 public SuperPackage() { this.talkTime=200; this.smsCount=100; this.flow=1*1024; super.setPrice(78); } @Override public void showInfo() { System.out.println("超人套餐:通话时长为"+this.talkTime+"分钟/月,短信条数为:"+this.smsCount+"条/月,上网流量为"+(this.flow/1024)+"GB/月"); } @Override public int call(int minCount, MobileCard card) throws Exception { // 重写通话接口功能 获得套餐使用详情 int temp = 0;// 实际消耗分钟数 // 循环判断使用详情 for (int i = 0; i < minCount; i++) { // 第一种情况 套餐余额充足还可支持1分钟通话 if (this.getTalkTime() - card.getRealTalkTime() >= 1) { card.setRealTalkTime(card.getRealTalkTime() + 1);// 实际通话数据+1 temp++; } else if (card.getMoney() >= 0.2) { // 情况二:套餐通话时长已经用完,但是账户余额还可以支持1分钟通话,直接使用账户余额支付 card.setRealTalkTime(card.getRealTalkTime() + 1);// 实际使用通话时长分钟+1 temp++; // 剩余金额减少0.2元 card.setMoney(card.getMoney() - 0.2); // 总消费增加0.2元 card.setConsumAmount(card.getConsumAmount() + 0.2); } else { try { throw new Exception("本次已通话" + temp + "分钟,您的余额已不足,请充值后在使用!"); } catch (Exception e) e.printStackTrace(); } finally { // 报错结束返回一个实际通话时长 return temp; } } } return temp;// 返回一个实际通话时长 } @Override public int netPlay(int flow, MobileCard card) throws Exception { // 重写上网接口功能 获得套餐使用详情 int temp = 0;// 实际消耗流量数据 // 循环判断使用详情 for (int i = 0; i < flow; i++) { // 第一种情况 套餐余额充足还可以使用1MB的流量 if (this.getFlow() - card.getRealFlow() >= 1) { card.setRealFlow(card.getRealFlow() + 1); ;// 实际流量数据+1 temp++; } else if (card.getMoney() >= 0.1) { // 情况二:套餐剩余流量已经用完,但是账户余额还可以支持使用1MB流量,直接使用账户余额支付 card.setRealSMSCount(card.getRealSMSCount() + 1);// 实际流量数据+1 temp++; // 剩余金额减少0.1元 card.setMoney(card.getMoney() - 0.1); // 总消费增加0.1元 card.setConsumAmount(card.getConsumAmount() + 0.1); } else { try { throw new Exception("本次已使用" + temp + "MB的流量,您的余额已不足,请充值后在使用!"); } catch (Exception e) { e.printStackTrace(); } finally { // 报错结束返回一个实际流量数据 return temp; } } } return temp;// 返回一个实际流量数据 } @Override public int send(int count, MobileCard card) throws Exception { // 重写短信接口功能 获得套餐使用详情 int temp = 0;// 实际消耗短信次数 // 循环判断使用详情 for (int i = 0; i < count; i++) { // 第一种情况 套餐余额充足还可支持发送1次短信 if (this.getSmsCount() - card.getRealSMSCount() >= 1) { card.setRealSMSCount(card.getRealSMSCount() + 1);// 实际短信数据+1 temp++; } else if (card.getMoney() >= 0.1) { // 情况二:套餐短信次数已经用完,但是账户余额还可以支持发一次短信,直接使用账户余额支付 card.setRealSMSCount(card.getRealSMSCount() + 1);// 实际短信数据+1 temp++; // 剩余金额减少0.1元 card.setMoney(card.getMoney() - 0.1); // 总消费增加0.1元 card.setConsumAmount(card.getConsumAmount() + 0.1); } else { try { throw new Exception("本次已发送" + temp + "次短信,您的余额已不足,请充值后在使用!"); } catch (Exception e) { e.printStackTrace(); } finally { // 报错结束返回一个实际短信次数 return temp; } } } return temp;// 返回一个实际短信次数 } }
4)创建工具类
工具类主要包含数据存储列表和功能实现:
package util;
import entity.*;
import jdk.swing.interop.SwingInterOpUtils;
import service.CallService;
import service.NetService;
import service.SendService;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
/**
* 工具类
*/
public class CardUtil {
//已注册用户列表
private Map<String, MobileCard> cards=new HashMap<>();
//所有卡号消费记录列表
private Map<String, List<ConsumInfo>> consumInfos=new HashMap<>();
//使用场景列表
private List<Scene> scenes = new ArrayList<>();
Scanner sc=new Scanner(System.in);
/**
* 初始化场景
* */
public void initScene(){
//初始化场景
scenes.add(new Scene("通话", 90, "问候客户,谁知其如此难缠,通话90分钟"));
scenes.add(new Scene("通话", 30, "询问妈妈身体状况,本地通话30分钟"));
scenes.add(new Scene("短信", 5, "参与环境保护实施方案问卷调查,发送短信5条"));
scenes.add(new Scene("短信", 50, "通知朋友手机换号,发送短信50条"));
scenes.add(new Scene("上网", 1024, "和女朋友用微信视频聊天,使用流量1GB"));
scenes.add(new Scene("上网", 2 * 1024, "晚上手机在线看韩剧,不留神睡着啦!使用2GB"));
}
/**
* 初始化
* 电话卡 使用记录
*/
public void init(){
//话痨
MobileCard card1=new MobileCard("13901234567", "小陈", "123456", new TalkPackage(), 58,30,600,30,0 );
//网虫
MobileCard card2=new MobileCard("13908765431", "小许", "987654", new NetPackage(), 68,200,0,0,0);
//超级
MobileCard card3=new MobileCard("13092322791", "小薛", "123123", new SuperPackage(), 78,300,0,0,0);
cards.put(card1.getCardNumber(),card1);
cards.put(card2.getCardNumber(),card2);
cards.put(card3.getCardNumber(),card3);
//初始化消费记录列表
//卡1消费记录
List<ConsumInfo> c1= new ArrayList<>();
c1.add(new ConsumInfo(card1.getCardNumber(),"通话",100));
card1.setRealTalkTime(card1.getRealTalkTime()+100);
consumInfos.put(card1.getCardNumber(),c1);
//卡2消费记录
List<ConsumInfo> c2= new ArrayList<>();
c2.add(new ConsumInfo(card2.getCardNumber(),"上网",1024));
card2.setRealFlow(card2.getRealFlow()+1024);
consumInfos.put(card2.getCardNumber(),c2);
//消费记录卡3
List<ConsumInfo> c3= new ArrayList<>();
c3.add(new ConsumInfo(card3.getCardNumber(),"通话",100));
c3.add(new ConsumInfo(card3.getCardNumber(),"上网",1024));
c3.add(new ConsumInfo(card3.getCardNumber(),"发短信",20));
card3.setRealTalkTime(card3.getRealTalkTime()+100);
card3.setRealFlow(card3.getRealFlow()+1024);
card3.setRealSMSCount(card3.getRealSMSCount()+20);
consumInfos.put(card3.getCardNumber(),c3);
}
/**
* 注册新卡
* @param card 注册卡号
*/
public void addCard(MobileCard card){
//创建选择业务对象 抽象类不能new
ServicePackage sp;
//创造数组接收随机生成的手机号
String counts[]=getNewNumbers(9);
System.out.println("************可选择的卡号**************");
//打印随机手机号
for (int i = 0; i < counts.length; i++) {
System.out.print((i+1)+"."+counts[i]+"\t\t");
//输出三次换行
if((i+1)%3==0){
System.out.println();
}
}
System.out.print("请选择卡号:");
int cardNum=sc.nextInt();
//判断选择正确性
while ((cardNum-1)>=counts.length||(cardNum-1)<0){
System.out.print("请输入正确的序号:");
cardNum=sc.nextInt();
}
System.out.println("请选择套餐:1.话痨套餐(58元/月) 2.网虫套餐(68元/月) 3.超人套餐(78元/月)(请输入序号):");
int choice=sc.nextInt();
//判断选择正确性
while (choice<=0||choice>3){
System.out.println("请输入正确的套餐序号");
choice=sc.nextInt();
}
//获取指定套餐 1.话痨套餐 2.网虫套餐 3.超人套餐
switch (choice){
case 1:
sp=new TalkPackage();
break;
case 2:
sp=new NetPackage();
break;
case 3:
sp=new SuperPackage();
break;
default:
throw new IllegalStateException("Unexpected value: " + choice);
}
System.out.print("请输入姓名:");
String name=sc.next();
System.out.print("请输入密码:");
String password=sc.next();
System.out.print("请输入预存花费金额:");
double money=sc.nextDouble();
//将基本信息添加到手机卡对象中 //卡号 用户名 密码 所属套餐 账户余额
card=new MobileCard(counts[cardNum - 1], name, password, sp, ( money-sp.getPrice()));
//循环判断预存金额是否充足 不足则重新赋值
while(card.getMoney()<0){
System.out.print("您预存的花费金额不足以支付本月固定套餐资费,请重新充值:");
money=sc.nextDouble();
card.setMoney(money-sp.getPrice());
}
System.out.println("注册成功!");
//展示信息
card.showMeg();
//添加到集合中
cards.put(card.getCardNumber(),card);
}
/**
* 话费充值
* @param number 卡号
* @param money 充值金额
*/
public void chargeMoney(String number,double money){
//判断卡号是否存在
if(cards.get(number)!=null){
//最低充值50
if(money>=50){
cards.get(number).setMoney(cards.get(number).getMoney()+money);
System.out.println("充值成功!当前的话费余额为:"+cards.get(number).getMoney()+"元");
}else{
System.out.println("最低消费50!");
}
}else {
System.out.println("该手机号不存在");
}
}
//使用嗖嗖(模拟手机消费)
public void userSoso(String number)throws Exception{
//通过手机号获取手机卡对象
MobileCard card=cards.get(number);
//随机产生场景
Random rand=new Random();
int temp=0; //各场景的实际消费数据
//遍历判断手机卡所有场景的功能类型
while(true){
//获取0-5的随机数
int randNum=rand.nextInt(6);
//根据随机数创建场景(场景在上面已初始化)
Scene scene=scenes.get(randNum);
switch (randNum){
case 0:
case 1:
//通话 判断该手机卡是否包含语音套餐(网虫套餐无)
if(card.getSerPackage() instanceof CallService){
//展示场景
System.out.println(scene.getDescription()+"\t");
//获得实际消费数据 scene中data消费数据即为call方法的通话分钟数
temp=((CallService) card.getSerPackage()).call(scene.getData(),card);
//添加消费记录
//创建消费记录对象,数据是实际消费数据(不是场景中消费数据)
ConsumInfo info=new ConsumInfo(number,scene.getType(),temp);
//修改电话卡当月实际通话数据
card.setRealTalkTime(card.getRealTalkTime()+temp);
//添加消费记录
addConsumInfo(number,info);
break;
}
continue;
case 2:
case 3:
//短信场景 判断手机卡对象的套餐是否包含短信业务
if(card.getSerPackage() instanceof SendService){
//展示场景
System.out.println(scene.getDescription()+"\t");
//获得实际消费记录 scene中data为send中短信条数
temp=((SendService) card.getSerPackage()).send(scene.getData(),card);
//添加消费记录
//创建消费记录对象,数据是实际消费数据(不是场景中消费数据)
ConsumInfo info=new ConsumInfo(number,scene.getType(),temp);
//修改电话卡当月实际短信条数
card.setRealSMSCount(card.getRealSMSCount()+temp);
addConsumInfo(number,info);
break;
}
continue;
case 4:
case 5:
//上网 判断手机卡对象的套餐是否包含上网业务
if(card.getSerPackage() instanceof NetService){
//展示场景
System.out.println(scene.getDescription()+"\t");
//获得实际消费数据 此时scene中data为netplay的流量
temp=((NetService)card.getSerPackage()).netPlay(scene.getData(),card);
//添加消费记录
ConsumInfo info=new ConsumInfo(number,scene.getType(),temp);
//修改电话卡当月实际上午数据
card.setRealFlow(card.getRealFlow()+temp);
addConsumInfo(number,info);
break;
}
continue;
}
//退出while循环
break;
}
}
//资费说明 创建套餐资费说明文件
public void showDescription()throws IOException {
//创建FileWriter对象
FileWriter fw=new FileWriter("src/serviceInfo.txt");
//创建StringBuffer接收需要写入的信息
StringBuffer sb=new StringBuffer();
sb.append("套餐类型:话唠套餐\r\n" + "通话时长:500分钟 \r\n" + "短信条数:30条\r\n" + "月资费:58元\r\n" + "——————————————\r\n"
+ "套餐类型:网虫套餐\r\n" + "上网流量:3GB\r\n" + "月资费:68元\r\n" + "——————————————\r\n" + "套餐类型:超人套餐\r\n"
+ "通话时长:200分钟 \r\n" + "短信条数:50条\r\n" + "上网流量:1GB\r\n" + "月资费:78元\r\n" + "——————————————\r\n"
+ "超出套餐计费:\r\n" + "通话时长:0.2元/分钟\r\n" + "短信条数:0.1元/分钟\r\n" + "上网流量:0.1元/分钟\r\n"
+ "————————————————\r\n");
fw.write(sb.toString());
fw.flush();
//创建FileReader对象
FileReader fr=new FileReader("src/serviceInfo.txt");
//创建BufferReader对象接收字符串
BufferedReader br=new BufferedReader(fr);
//循环打印到控制台
String line=br.readLine();
while(line!=null){
System.out.println(line);
line=br.readLine();
}
try {
br.close();
fr.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//本月账单查询
public void showAmountDetail(String number){
//根据手机号查找
MobileCard card=cards.get(number);
//判断是否存在
if(card!=null){
//创建StringBuffer类 便于字符串拼接
StringBuffer sb = new StringBuffer("您的卡号:" + number + "的当月账单:\n");
sb.append("套餐资费:"+card.getSerPackage().getPrice()+"元\n");
sb.append("合计:"+card.getConsumAmount()+"元\n");
sb.append("账户余额:"+card.getMoney()+"元。");
System.out.println(sb);
}else{
System.out.println("该手机卡号不存在!");
}
}
//套餐余量查询
public void showRemainDetail(String number){
//根据手机号查找
MobileCard card=cards.get(number);
//判断是否存在
if(card!=null) {
//创建StringBuffer类 便于字符串拼接
StringBuffer sb = new StringBuffer("您的卡号是:" + number + "\n套餐内剩余:");
// 获取卡中的真实消费数据和业务数据比较,判定
ServicePackage serPackage = card.getSerPackage();
// 判断是哪种套餐
if (serPackage instanceof SuperPackage) {
//向下转型获取超人套餐信息和功能
SuperPackage pack = (SuperPackage) serPackage;
//获取套餐余量
int minusTalkData = pack.getTalkTime() - card.getRealTalkTime();
int minusSMSData = pack.getSmsCount() - card.getRealSMSCount();
int minusFlowData = pack.getFlow() - card.getRealFlow();
sb.append("\n通话时长:" + (minusTalkData > 0 ? minusTalkData + "分钟" : "0分钟"));
sb.append("\n短信条数:" + (minusSMSData > 0 ? minusSMSData + "条" : "0条"));
sb.append("\n上网流量:" + (minusFlowData > 0 ? minusFlowData/1024 + "GB" : "0GB"));
} else if (serPackage instanceof TalkPackage) {
// 向下转型获取话痨套餐信息和功能
TalkPackage pack = (TalkPackage) serPackage;
// 获取套餐余量
int minusTalkData = pack.getTalkTime() - card.getRealTalkTime();
int minusSMSData = pack.getSmsCount() - card.getRealSMSCount();
sb.append("\n通话时长:" + (minusTalkData > 0 ? minusTalkData + "分钟" : "0分钟"));
sb.append("\n短信条数:" + (minusSMSData > 0 ? minusSMSData + "条" : "0条"));
} else if (serPackage instanceof NetPackage) {
// 向下转型获取话痨套餐信息和功能
NetPackage pack = (NetPackage) serPackage;
/// 获取套餐余量
int minusFlowData = pack.getFlow() - card.getRealFlow();
sb.append("\n上网流量:" + (minusFlowData > 0 ? minusFlowData / 1024 + "GB" :"0GB"));
}
System.out.println(sb);
} else {
System.out.println("该手机卡号不存在!");
}
}
//打印消费账单
public void printAmountDetail(String number){
//判断手机号是否存在
if(cards.get(number)!=null){
//打印消费记录到文本文件中 文件名:手机号+消费记录
try {
FileWriter fw=new FileWriter(number+"消费记录.txt");
//创建StringBuffer写入消费记录
StringBuffer sb=new StringBuffer("***********************"+number+"的消费记录***********************");
sb.append("\n序号\t类型\t数据(通话(分钟)/上网(MB)/短信(条))\n");
// 获取消费记录集合
List<ConsumInfo> infoList=consumInfos.get(number);
//判断集合是否为空
if(infoList!=null){
//遍历消费记录
for (int i = 0; i < infoList.size(); i++) {
sb.append((i+1)+".\t"+infoList.get(i).getType()+"\t"+infoList.get(i).getConsumData()+"\n");
}
System.out.println("打印完成");
}else{
System.out.println("该卡暂无消费记录");
}
// 写入文件
fw.write(sb.toString());
fw.flush();
fw.close();
}catch (IOException e) {
e.printStackTrace();
}
}else {
System.out.println("改手机号不存在");
}
}
/**
* 套餐变更
* @param number 卡号
*/
public void changingPack(String number){
//创建一个业务套餐对象 抽象类无法实例化(判断卡号类型向下转型)
ServicePackage sp;
//判断卡号是否存在
if(cards.get(number)!=null){
System.out.println("**********************");
System.out.println("1、话痨套餐\t2、网虫套餐\t3、超人套餐 请选择(序号):");
int choice=sc.nextInt();
//判断输入正误
while (choice<=0||choice>3){
System.out.print("请输入正确的序号");
choice=sc.nextInt();
}
//判断项目类型
switch (choice){
case 1:
//话痨套餐
sp=new TalkPackage();
//判断现有套餐是否与要更改套餐相同
if(cards.get(number).getSerPackage() instanceof TalkPackage){
System.out.println("对不起,您已经是改套餐用户,无需更改");
}else{
//判断剩余金额是否足以支付套餐费用
if(cards.get(number).getMoney()>sp.getPrice()){
//更改套餐
cards.get(number).setSerPackage(sp);
//余额减去套餐费用
cards.get(number).setMoney(cards.get(number).getMoney()-sp.getPrice());
//当月消费金额加上套餐费
cards.get(number).setConsumAmount(cards.get(number).getConsumAmount() + sp.getPrice());
System.out.println("更改套餐成功!");
//展示套餐信息
sp.showInfo();
}else {
System.out.println("余额不足,无法更改套餐");
}
}
break;
case 2:
//网虫套餐
sp=new NetPackage();
//判断现有套餐和要更改套餐是否相同
if(cards.get(number).getSerPackage() instanceof NetService){
System.out.println("您已经是改套餐用户,无需更改");
}else{
//判断余额要大于套餐费用
if(cards.get(number).getMoney()>sp.getPrice()){
//更改套餐
cards.get(number).setSerPackage(sp);
//余额减去套餐费
cards.get(number).setMoney(cards.get(number).getMoney()-sp.getPrice());
//月消费加上套餐费
cards.get(number).setConsumAmount(cards.get(number).getConsumAmount()+sp.getPrice());
System.out.println("套餐修改成功");
}else{
System.out.println("余额不足,无法更改套餐");
}
}
break;
case 3:
//超人套餐
sp=new SuperPackage();
//判断已有套餐和要修改套餐是否相同
if(cards.get(number).getSerPackage() instanceof SuperPackage){
System.out.println("您已经是该套餐用户,无法修改");
}else {
//判断余额是否足以修改套餐
if(cards.get(number).getMoney()>sp.getPrice()){
//更改套餐
cards.get(number).setSerPackage(sp);
//更改余额
cards.get(number).setMoney(cards.get(number).getMoney()-sp.getPrice());
//更改月消费
cards.get(number).setConsumAmount(cards.get(number).getConsumAmount()+sp.getPrice());
}else{
System.out.println("余额不足,无法更改套餐");
}
}
break;
}
}else{
System.out.println("该手机号不存在");
}
}
/**
* 办理退网
* @param number 卡号
*/
public void delCard(String number){
//判断集合中卡号是否存在
if(cards.get(number)!=null){
System.out.println("*********办理退网**********");
//二次确定
System.out.print("您确定注销此手机号吗?(Y/N):");
String choice=sc.next();
if(choice.equalsIgnoreCase("Y")){
//通过 key手机号删除
cards.remove(number);
System.out.println("卡号:"+number+"退网成功!\n感谢使用");
}
}else{
System.out.println("该手机卡号不存在!");
}
}
//根据卡密验证该卡是否已注册(登录验证)
public boolean isExistCard(String number,String passWord){
Set<String> numbers = cards.keySet();
Iterator<String> it = numbers.iterator();
boolean flag=false;
while (it.hasNext()){
String searchNum = it.next();
if(searchNum.equals(number) && (cards.get(searchNum)).getPassWord().equals(passWord)){
flag=true;
}
}
return flag;
}
//根据卡号验证卡号是否注册
public boolean isExistCard(String number){
Set<String> numbers = cards.keySet();
Iterator<String> it = numbers.iterator();
boolean flag=false;
while (it.hasNext()){
String searchNum = it.next();
if(searchNum.equals(number)){
flag=true;
}
}
return flag;
}
//生成随机卡号
public String createNumber(){
String fixedNum="130";
String cardNumber="";
Random rand=new Random();
String randNumber="";
//随机生成八位数字
for (int i = 0; i < 8; i++) {
randNumber+=rand.nextInt(10);
}
cardNumber=fixedNum+randNumber;
return cardNumber;
}
/**
* 生成指定个数的卡号列表
* @param count 返回手机号码数量
* @return
*/
public String[] getNewNumbers(int count){
//创建一个数组接收随机生成卡号
String[] numbers=new String[count];
//遍历赋值
for (int i = 0; i < numbers.length; i++) {
numbers[i]=createNumber();
//判断是否注册
if(isExistCard(numbers[i])){
//如果被注册就重新赋值
i--;
}
//判断生成是否有重复
for (int j = 0; j < i; j++) {
//判断新生成的号码与之前生成的号码是否有重复,如果有重新生成
if(numbers[i].equals(numbers[j])){
//有重复重新赋值
i--;
break;
}
}
}
return numbers;
}
/**
* 添加指定卡号的消费记录
* @param number 手机卡号
* @param info 一条消费记录
*/
public void addConsumInfo(String number,ConsumInfo info){
//创建消费对象集合
List<ConsumInfo> consumList=null;
//有消费记录(集合已存在)
if(consumInfos.containsKey(number)){
consumList=consumInfos.get(number);
consumList.add(info);
System.out.println("添加消费记录成功");
}else {
//没有消费记录(该卡号不存在集合中)
consumList=new ArrayList<>();
consumList.add(info);
//添加到map中
consumInfos.put(number,consumList);
System.out.println("该卡还未进行消费,新增一条消费记录");
}
}
}
5)创建菜单类
功能菜单的实现
package manager;
import entity.MobileCard;
import util.CardUtil;
import java.io.IOException;
import java.util.Scanner;
public class SosoMgr {
private Scanner sc=new Scanner(System.in);
private CardUtil cardUtil=new CardUtil();
/**
* 启动
*/
public void start(){
//初始化
cardUtil.init();
cardUtil.initScene();
int choose; //用户选择
boolean isExit=false;// 标记用户是否退出系统,true为退出
String cardNum=null; //手机卡号
//遍历菜单
do {
mainMenu();
choose=sc.nextInt();
switch (choose){
case 1:
System.out.println("***用户登录***");
System.out.print("请输入手机号:");
cardNum = sc.next();
System.out.print("请输入密码:");
String passWord=sc.next();
//判断注册状态
if (cardUtil.isExistCard(cardNum,passWord)){
cardMenu(cardNum);
}else{
System.out.println("账号或密码输入错误");
}
break;
case 2:
System.out.println("***用户注册***");
MobileCard card=null;
cardUtil.addCard(card);
break;
case 3:
System.out.println("***使用嗖嗖***");
System.out.print("请输入手机卡号");
cardNum=sc.next();
if(cardUtil.isExistCard(cardNum)){
try {
cardUtil.userSoso(cardNum);
} catch (Exception e) {
e.printStackTrace();
}
}else {
System.out.println("该手机号不存在");
}
break;
case 4:
System.out.println("***话费充值***");
System.out.print("请输入要充值的手机号:");
cardNum=sc.next();
System.out.print("请输入充值金额:");
double money=sc.nextDouble();
cardUtil.chargeMoney(cardNum,money);
break;
case 5:
System.out.println("***资费说明***");
try {
cardUtil.showDescription();
} catch (IOException e) {
e.printStackTrace();
}
break;
case 6:
System.out.println("退出系统");
isExit=true;
break;
default:
System.out.println("业务开发中...");
continue;
}
if(!isExit){
System.out.println("按任意数字键返回");
try {
choose=sc.nextInt();
} catch (Exception e) {
e.printStackTrace();
}
}else{
break;
}
} while (true);
System.out.println("欢迎下次光临嗖嗖移动服务大厅");
}
//主菜单
public static void mainMenu(){
System.out.println("******欢迎使用嗖嗖移动业务大厅******");
System.out.println("1.用户登录\t2.用户注册\t3.使用嗖嗖\t4.话费充值\t5.资费说明\t6.退出系统");
System.out.println("请选择(输入1-6选择功能,其他键返回主菜单):");
}
//二级菜单
public void cardMenu(String number){
do {
int choice;
System.out.println("******嗖嗖移动用户菜单******");
System.out.println("1.本月账单查询\t2.套餐余量查询\t3.打印消费详单\t4.套餐变更\t5.办理退网");
System.out.println("请选择(输入1-5选择功能,其他键返回上一级):");
choice=sc.nextInt();
switch (choice) {
case 1:
System.out.println("1、本月账单查询");
cardUtil.showAmountDetail(number);
break;
case 2:
System.out.println("2、套餐余量查询");
cardUtil.showRemainDetail(number);
break;
case 3:
System.out.println("3、打印消费祥单");
cardUtil.printAmountDetail(number);
break;
case 4:
System.out.println("4、套餐变更");
cardUtil.changingPack(number);
break;
case 5:
System.out.println("5、办理退网");
cardUtil.delCard(number);
break;
default:
System.out.println("返回主菜单");
return;
}
}while (true);
}
}
5)创建测试类
package manager;
public class Test {
public static void main(String[] args) {
SosoMgr soso=new SosoMgr();
soso.start();
//可使用可以多进行几遍使用嗖嗖来测试话费不足提醒
}
}
3.使用技能
实现嗖嗖移动大厅项目主要运用到以下Java技能:
- 面向对象思想进行程序设计
- 使用异常处理机制抛出并处理异常
- 使用集合存储和操作数据
- 使用I/O读写文本文件
- 使用Random类、String类等实用类