一、说明
博客内容:B站韩顺平老师的视频,以及代码的整理。此项目分为两个版本:
- 面向过程思路实现
- 面向对象思路实现
韩老师视频地址:【【零基础 快速学Java】韩顺平 零基础30天学会Java】 https://www.bilibili.com/video/BV1fh411y7R8/?p=342&share_source=copy_web&vd_source=656bca56998f14127313f0283f22ac0a
【注意】:仅限学习,如有侵权,请联系本人删除。
项目实现–面向过程思路
先贴代码,项目的完整代码如下:
package smallchange;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/**
* @author cdj
* @Version1.0
*/
public class SmallChangeSys {
// 1. 先完成显示菜单,并可以选择菜单,给出对应提示
// 2. 完成零钱通明细
// 3. 完成收益入账
// 4. 完成消费
// 5. 退出
// 6. 用户输入4退出时,给出提示”你要退出吗? y/n“,必须要正确的输入y/n,否则循环输入指令,直到输入y 或者 n
// 7. 在收益入账和消费时,判断金额是否合理,并给出相应的提示
public static void main(String[] args) {
// 定义相关的变量
boolean loop = true;
Scanner sc = new Scanner(System.in);
String key = "";
// 2.完成零钱通明细
// (1) 可以把收益入账和消费,保存到数组 (2)可以使用对象 (3)简单的会可以使用String拼接
String detils = "------------------零钱通明细--------------------";
// 3. 完成收益入账,完成功能驱动程序员增加新的变化和代码
// 定义新的变量
double money = 0;
double balance = 0;
Date date = null; // data 是 java.util.Data类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 可以用于日期格式化的
// 4. 消费
// 定义新的变量,保存消费的原因
String note = null;
do{
System.out.println("\n===================零钱通菜单================");
System.out.println("\t\t\t\t\t1 零钱通明细");
System.out.println("\t\t\t\t\t2 收益入账");
System.out.println("\t\t\t\t\t3 消费");
System.out.println("\t\t\t\t\t4 退 出");
System.out.print("请选择(1-4): ");
key = sc.nextLine();
// 使用 switch 分支控制
switch (key){
case "1":
System.out.println(detils);
break;
case "2":
System.out.print("收益入账金额:");
money = sc.nextDouble();
// 清空输入缓冲区
sc.nextLine();
// money 的值应该校验
// 找出不正确的金额条件,然后给出提示,就直接break
if(money <= 0){
System.out.println("收益入账金额需要大于0");
break;
}
balance += money;
// 获取当前日期
date = new Date();
// 拼接收益入账信息到details
detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
break;
case "3":
System.out.print("收益消费金额:");
money = sc.nextDouble();
sc.nextLine(); // 清空输入缓冲区
// money 的值应该校验 TODO
// 找出金额不正确的情况
if(money <= 0 || money > balance){
System.out.println("你的消费金额应该在 0-" + balance);
break;
}
System.out.print("消费说明: ");
note = sc.next();
sc.nextLine();
balance -= money;
// 拼接消费信息到details
date = new Date(); // 获取到当前时间
detils += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;
break;
case "4":
// 用户输入4退出时,给出提示”你要退出吗? y/n“,必须要正确的输入y/n
// (1) 定义一个变量 choice,接收用户的输入
// (2) 使用 while + break,来处理接收的输入时 y 或者 n
// (3) 退出while后,再判断choice是y还是n,就可以决定是否退出。
// (4) 建议一段代码完成一个小功能,尽量不要混在一起
String choice = "";
while (true) { // 要求用户必须输入 y/n,否则就一直循环
System.out.println("你确定要退出吗? y/n");
choice = sc.nextLine();
if ("y".equals(choice) || "n".equals(choice)) {
break;
}
}
// 当用户退出后,再进行判断
if (choice.equals("y")) {
loop = false;
}
break;
default:
System.out.println("选择有误,请重新选择");
}
}while(loop);
System.out.println("------------------退出了零钱通项目------------------");
}
}
代码思路
先看一下项目需求(资料来源:【【零基础 快速学Java】韩顺平 零基础30天学会Java】 https://www.bilibili.com/video/BV1fh411y7R8/?p=335&share_source=copy_web&vd_source=656bca56998f14127313f0283f22ac0a)
首先先理一下需要完成的几个功能:
- 界面显示
- 零钱通明细
- 收益入账
- 消费
- 退出
将这几个功能分别完成(一个代码块只实现一个功能)
1.界面显示
在界面显示的时候,我们需要完成的任务有以下两个:
- (1) 完成显示菜单
- (2) 可以选择菜单,并给出对应提示
关于任务(1),我们可以考虑直接使用Println
语句将菜单打印出来:
System.out.println("\n===================零钱通菜单================");
System.out.println("\t\t\t\t\t1 零钱通明细");
System.out.println("\t\t\t\t\t2 收益入账");
System.out.println("\t\t\t\t\t3 消费");
System.out.println("\t\t\t\t\t4 退 出");
实现了任务(1)之后,我们需要考虑的就是如何使得我们可以根据提示进行选择。那我们就需要去思考,哪个语句可以提供选择功能,很自然的想到了switch
语句。先看一下switch
语句的语法:
switch (expression) {
case value1:
// 当 expression 的值等于 value1 时执行这里的代码
// 可以有多行代码
break;
case value2:
// 当 expression 的值等于 value2 时执行这里的代码
// 可以有多行代码
break;
// 可以有更多的 case 语句
default:
// 当 expression 的值与所有 case 不匹配时执行这里的代码
}
由switch
语法可以得出:我们需要定义一个expression
让我们去选择哪条case
语句。根据菜单给的提示,我们选择定义一个String
类型的变量,去存储我们的选择。由于我们需要去输入我们的选择,那我们就需要一个输入的功能Scanner
。
由以上分析,我们就可以搭建一个程序框架:
public class SmallChangeSys {
// 1. 先完成显示菜单,并可以选择菜单,给出对应提示
public static void main(String[] args) {
// 定义相关的变量
Scanner sc = new Scanner(System.in);
String key = "";
System.out.println("\n===================零钱通菜单================");
System.out.println("\t\t\t\t\t1 零钱通明细");
System.out.println("\t\t\t\t\t2 收益入账");
System.out.println("\t\t\t\t\t3 消费");
System.out.println("\t\t\t\t\t4 退 出");
System.out.print("请选择(1-4): ");
key = sc.nextLine();
// 使用 switch 分支控制
switch (key){
case "1":
// TODO
break;
case "2":
// TODO
break;
case "3":
// TODO
break;
case "4":
// TODO
break;
default:
// TODO
break;
}
}
上述代码能让我们完成任务(1)和任务(2),但是它只能执行一次,选择一个功能。我们需要多次执行,而且考虑到不管什么情况,都会执行一次。那就想到do while
。先看一下do while
的语法:
do {
// 循环体代码块
} while (condition);
while
关键字后面跟着一个循环条件。只要循环条件为 true,循环将继续执行;否则循环终止。为了使我们退出循环的时候方便,这里我们选择定义一个bool
类型的变量loop
。当我们需要退出时,只需要将它置为false
即可。将上述代码修改:
public class SmallChangeSys {
// 1. 先完成显示菜单,并可以选择菜单,给出对应提示
public static void main(String[] args) {
// 定义相关的变量
Scanner sc = new Scanner(System.in);
String key = "";
boolean loop = true;
do {
System.out.println("\n===============零钱通菜单==============");
System.out.println("\t\t\t\t\t1 零钱通明细");
System.out.println("\t\t\t\t\t2 收益入账");
System.out.println("\t\t\t\t\t3 消费");
System.out.println("\t\t\t\t\t4 退出");
System.out.print("请选择(1-4): ");
key = sc.nextLine();
// 使用 switch 分支控制
switch (key){
case "1":
// 零钱通明细
// TODO
break;
case "2":
// 收益入账
// TODO
break;
case "3":
// 消费
// TODO
break;
case "4":
// 退出
// TODO
break;
default:
// TODO
break;
}while (loop)
}
}
这样,整个程序的框架就已经搭建好了。下面使用代码块分别实现各个功能。
2. 零钱通明细
我们需要实现下图功能,那我们就需要一个变量进行显示。实现的方式有三种
- 把收入入账和消费,保存到数组(数组扩容比较麻烦)
- 使用对象
- 使用
String
拼接
此处考虑使用String
进行拼接,所以需要定义一个String
类型的变量:
String detils = "------------------零钱通明细--------------------";
在定义完变量后,我们需要把它放入菜单的选择中(case1
),当我们需要查看明细时,只需要将这个字符串打印出来即可(在后续操作过程中有可能会修改字符串)。
case "1":
System.out.println(detils);
break;
3.收益入账
首先需要一个变量用来存储收益,所以先定义一个存储收益的变量money
:
double money = 0;
我们的代码中已经有一个sc
用于交互,所以money
的值可以直接由我们输入。但是在编写代码过程中我发现如果没有清除缓存的话,代码会直接跳转到switch
中的defalut
语句,所以在输入money
加入了一个清理缓存的语句:
money = sc.nextDouble();
sc.nextLine(); // 清空输入缓冲区
当我们有收益时,我们的余额也会发生改变,所以此处我们添加一个存储余额的变量balacnce
:
double balance = 0;
有了balance
用来存储余额,在实现收益功能的代码块中,自然balance += money
。再看一下打印的信息里面还有一个data
信息,所以需要添加时间相关的信息:
Date date = null; // data 是 java.util.Data类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 可以用于日期格式化的
date = new Date();
因为我们用的时String
进行的拼接,那么现在要将新增的记录拼接到我们的details
中:
// 拼接收益入账信息到details
detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
注意看拼接的过程中是先拼接了一个\n
,所以无论最终我们的details
有多长,它都只是一个变量。
最终收益入账功能实现的代码如下:
case "2":
System.out.print("收益入账金额:");
money = sc.nextDouble();
// 清空输入缓冲区
sc.nextLine();
// money 的值应该校验
// 找出不正确的金额条件,然后给出提示,就直接break
if(money <= 0){
System.out.println("收益入账金额需要大于0");
break;
}
balance += money;
// 获取当前日期
date = new Date();
// 拼接收益入账信息到details
detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
break;
除去上述将的内容,在其中还添加了检验money
值得功能。
其它功能实现方式和上述方式大同小异,此处就不再进行书写。
总结
在项目实现过程中,首先是分析项目的需求,然后根据项目的需求将整个代码的框架搭建出来。在搭建过程中,遵循每个代码块实现一个功能,并且在需要什么变量的时候就定义什么变量(根据实际需求去定义变量)。在听课过程中,韩老师给的两个建议是十分重要的:
- 一段代码完成一个小功能,不要混在一起。
- 找出不正确的条件用来判断,而不是找正确的条件。
项目实现–面向对象思路
先贴代码,分为两个文件
- SmallChangeSysOOP:实现各种功能
- SmallChangeSysAPP:调用
SmallChangeSysOPP代码如下:
package smallchange.oop;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
/**
* @author cdj
* @Version1.0
* 完成零钱通的各个功能
* 将各个功能对应一个方法
*/
public class SmallChangeSysOOP {
// 属性
boolean loop = true;
Scanner sc = new Scanner(System.in);
String key = "";
String detils = "------------------零钱通明细---------------";
double money = 0;
double balance = 0;
Date date = null; // data 是 java.util.Data类型,表示日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 可以用于日期格式化的
String note = null;
// 显示菜单,并可以选择
public void mainMenu() {
do{
System.out.println("\n===================零钱通菜单================");
System.out.println("\t\t\t\t\t1 零钱通明细");
System.out.println("\t\t\t\t\t2 收益入账");
System.out.println("\t\t\t\t\t3 消费");
System.out.println("\t\t\t\t\t4 退 出");
System.out.print("请选择(1-4): ");
key = sc.nextLine();
// 使用 switch 分支控制
switch (key){
case "1":
this.detail();
break;
case "2":
this.income();
break;
case "3":
this.pay();
break;
case "4":
this.exit();
break;
default:
System.out.println("选择有误,请重新选择");
}
}while(loop);
}
// 零钱通明细
public void detail() {
System.out.println(detils);
}
// 完成收益入账
public void income() {
System.out.print("收益入账金额:");
money = sc.nextDouble();
// 清空输入缓冲区
sc.nextLine();
// money 的值应该校验
// 找出不正确的金额条件,然后给出提示,就直接break
if(money <= 0){
System.out.println("收益入账金额需要大于0");
return; // 退出方法,不再执行后面的方法
}
balance += money;
// 获取当前日期
date = new Date();
// 拼接收益入账信息到details
detils += "\n收益入账\t" + money + "\t" + sdf.format(date) + "\t" + balance;
}
// 消费
public void pay() {
System.out.print("收益消费金额:");
money = sc.nextDouble();
sc.nextLine(); // 清空输入缓冲区
// money 的值应该校验 TODO
// 找出金额不正确的情况
if(money <= 0 || money > balance){
System.out.println("你的消费金额应该在 0-" + balance);
return;
}
System.out.print("消费说明: ");
note = sc.next();
sc.nextLine();
balance -= money;
// 拼接消费信息到details
date = new Date(); // 获取到当前时间
detils += "\n" + note + "\t-" + money + "\t" + sdf.format(date) + "\t" + balance;
}
// 退出
public void exit() {
String choice = "";
while (true) { // 要求用户必须输入 y/n,否则就一直循环
System.out.println("你确定要退出吗? y/n");
choice = sc.nextLine();
if ("y".equals(choice) || "n".equals(choice)) {
break;
}
}
// 当用户退出后,再进行判断
if (choice.equals("y")) {
loop = false;
System.out.println("------------------退出了零钱通项目------------------");
}
}
}
SmallChangeSysAPP代码如下:
package smallchange.oop;
/**
* @author cdj
* @Version1.0
* 调用SmallChangeSysOOP 对象
*/
public class SmallChangeSysAPP {
public static void main(String[] args) {
new SmallChangeSysOOP().mainMenu();
}
}
在Structure(使用alt+7打开)界面下可以查看OOP类下面的属性和方法:
将其中的各个功能封装进OOP类下面的方法中,后续我们只用调用它的方法就可以了。对于其它人想用我们的代码,或者说后续添加方法,都是比面向过程更加方便的。