前言
一个月零零散散的时间学习了java,通过这次“超市管理系统”的练习,希望可以给一同开始学习java的朋友一些参考,更希望大佬们多多指点和批评~
一、确定需求
程序概述:
小型超市商品销售管理系统选择小型超市的四类商品进行管理。
这四类商品是:食品、化妆品、生活用品和饮料(四个类)。
每类商品都包含有商品名和商品利润 (其中包括商品的售价、进价、库存量)。(五个属性)
每类不同的商品还有区别于其他商品的特殊信息(子类特有属性)例如,食品有批发商,化妆品有品牌,饮料有生产厂家。
上述文字可以确定以下几点
程序要实现“增,删,改,查”这四个基本功能 + 显示利润本程序要求对四类商品进行操作,因此分类很明确,只需要创建四个类分别表示四类商品即可本程序中要求商品有(以下属性)商品名、商品利润、售价、进价、库存量(我们当然可以额外加入一个属性:商品id,以实现更加明确的equals比较,后文会提及)。本程序中要求对于不同类的商品还要有自己特有的信息(食品有批发商,化妆品有品牌,饮料有生产厂家)
通过以上内容,我们大概对这个程序有了初步的想法和思路,下面我们深入分析一下需要哪些类以及哪些方法
二、确定类、接口、方法实现
1.确定类
上文提及到:我们需要定义四个类分别表示四类商品,那么我们在写之前是否可以从四个类抽取它们相同的特点(属性)来引入继承的思想呢?
显然是可以的,我们可以定义一个商品类Wares
作为父类,(并且使用多态来切换父类引用的不同指向)Wares
父类包含了四个类商品的共性(具有商品名、售价、进价、库存量、商品编号id这五个属性),而其子类当然就是食品Food
、化妆品Cosmetic
、生活用品DailyUsing
和饮料Drinking
,这样程序中的类就确定下来了
我们可以再深入思考一下:
Wares
可以是普通类、可以是抽象类,我们如何去选择呢?
其实两者在功能实现上都是可以的,但是普通类实现接口的时候,是一定要重写接口中每一个方法的,而抽象类却不需要;况且Wares
是四类商品的父类,我们在对商品进行操作的时候,只需要操作其子类的对象即可,没有必要实例化Wares
对象,因此我们选择将Wares
定义为抽象类。
关于四个子类:食品类
Food
、饮料类Drinking
、化妆品类Cosmetic
、生活用品类DailyUsing
的确定
四个子类只需要继承父类Wares
即可,共性属性自然而然的继承了下来,特性属性在每个类中单独编写即可。
1
2
3
4
5
6
7
8
9
10
11
|
//Wares类中的属性
//商品名字
private String name;
//商品编号
private int id;
//商品进价
private double inPrice;
//商品售价
private double outPrice;
//库存量
private int Count;
|
注:Wares
及其子类的属性我们最好都设为私有属性,再去通过setter
和getter
方法进行存取,养成封装的好习惯~
2.确定接口
商品类
Wares
会包含所以商品类及其子类所共有的静态特征(属性)和对商品的动态操作(方法),属性在类中一一初始化即可,但是方法我们也要在此类中一一写出方法体吗?
我们可以利用接口,把我们程序所需要的方法都一一声明到接口内,不需实现,只需等待父类Wares
去implement
接口,再让其子类中对接口内的方法一一实现(重写)即可
3.确定方法
下面我们来根据程序需求来确定方法(需求:增删改查、显示利润)
我们还可以加入“遍历所有商品”功能,这样还可以在程序调试的时候,判断是否可以真正实现增删改查功能,起到验证作用
因此我们确定下来了有以下几个方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public interface Operations {
/*
添加商品信息
*/
void addWareInfo(ArrayList<Wares> arrayList);
/*
输出商品信息
注意:需要重写toString方法
*/
void printWareInfo(ArrayList<Wares> arrayList);
/*
查询商品信息
注意:需要重写equals方法
*/
void findWareInfo(ArrayList<Wares> arrayList);
/*
计算并显示某个商品的利润
注意:需要重写equals方法
*/
void countWarePrice(ArrayList<Wares> arrayList);
/*
删除商品的信息
注意:需要重写equals方法
*/
void delWareInfo(ArrayList<Wares> arrayList);
/*
修改货物信息
注意:需要重写equals方法
*/
void updateWareInfo(ArrayList<Wares> arrayList);
}
|
三、敲代码前再分析一波~
1.重写equals()吗?
重写
equals()
的目的是用于比较两个不同对象在其本身内容相同时,希望equals方法判定结果是true而非false,这时我们需要重写equals()
本程序我们自定义equals()
判定规则为:当对象的编号和名称同时相同时,判定两个对象为同一个对象
很显然,本程序无论是“增删改查”操作这四个基本功能,还是验证用户是否重复添加同一商品这一功能,都需要两个对象进行equals比较,因此重写equals()
是必须的。
那么是否每一个类都需要重写equals方法呢?
显然,Wares
抽象类是不需要的,因为我们在比较的时候,是比较其子类的对象是否是同一对象,而并非父类对象(况且该父类是抽象类,无法实例化对象,更别谈可以调用其equals()
了)因此我们可以确定:要重写Food
类、Drinking
类、DailyUsing
类、Cosmetic
类中的equals()
要进行重写
1
2
3
4
5
6
7
8
9
10
11
|
/*
重写equals方法
自定义为:当名称相同且商品id相同的时候,视为同一件商品
*/
@Override
public boolean equals(Object o) {
if ( this == o) return true ;
if (o == null || !(o instanceof Wares)) return false ;
Cosmetic cosmetic = (Cosmetic) o;
return super .getName().equals(cosmetic.getName()) && super .getId()==cosmetic.getId();
}
|
2.重写toString吗?
由于需要清晰的显示商品信息,每一次需要输出信息的时候,可以
System.out.print(“…” + 属性1 + “…” + 属性2);
来显示每一条信息。
但是鉴于本程序输出的次数很多,而且System.out.print()
方法在内部调用toString()
。
因此我们可以重写(父类)toString方法,使得每次的输出都有一套固定的输出格式,实现了System.out.print(实例化的对象名);
即可完成格式化输出。
那么是否每一个类都需要重写
toString()
呢?
显然,Wares
抽象类是不需要的,因为我们输出信息的时候,是要输出四个子类对象的信息(父类Wares
是抽象类,无法实例化对象,更别谈可以调用其toString()
了)因此我们可以确定:要重写Food
类、Drinking
类、DailyUsing
类、Cosmetic
类中的toString()
要进行重写
1
2
3
4
5
6
7
8
9
10
11
12
|
/*
重写toString方法
*/
@Override
public String toString() {
return "化妆品 {\t " + super .getId() +
"\t " + super .getName() +
"\t\t" + super .getInPrice() + "元" +
"\t\t" + super .getOutPrice() + "元" +
"\t\t" + super .getCount() + "件" +
"\t}" ;
}
|
3.重写hashCode()吗?
Java中规定:如果两个对象相同,那么它们的
hashCode
值一定要相同;如果两个对象的hashCode
相同,它们对象本身equals
比较并不一定相同。
因此如果改写了equals方法,令两个实际不是一个对象的两个实例在逻辑上相等了,但是hashcode却是不等,这是有矛盾的。
这种矛盾会在hashMap
等集合中造成实际运行结果和预期运行结果的不一致产生。
(个人理解:equals()
返回true表示两个对象相同,在同一个单向链表上比较那么对于同一个单向链表上的结点来说,他们的哈希值都应该是相同的所以hashCode()
的返回值也应该相同)。
就本程序来说没有用到hashMap
这样集合底层的数据结构来存储每一个对象(而是用的arrayList
),因此是否重写hashCode方法对本程序的影响不大,但是鉴于程序的规范性,还是应该遵循以下原则:
如果一个类的equals方法重写了,那么hashCode方法必须重写。并且equals方法返回如果是true,hashCode方法返回的值必须一样。
1
2
3
4
5
6
7
|
/*
重写hashCode方法
*/
@Override
public int hashCode() {
return Objects.hash(brand);
}
|
4.存储结构的确定
类、接口、方法、属性、数据类型以及实现方法都已经确定了,现在需要把实例化的对象以什么样的形式存储到一起呢?
一种是数组、一种是集合
很显然,我们在进行初始化的时候,不知道需要存入多少商品,无法对数组进行预估计容量;数组只能存放单一数据类型的元素,在对其操作的时候(相比较集合中已提供了对集合的很多操作而言)很不方便,而且数组虽然检索效率高,但是插入查找效率很低。
本程序我们选择arrayList
集合进行对象的存储。
注:就本程序而言,个人感觉还是使用
hashMap
(查询更加快捷)或hashSet
(排序更加便捷),且两者都可以自动控制存储的信息无重复的特点。这是本程序需要改进的地方之一
四、总结以及源代码
希望通过这篇文章可以帮助到初学java的你!
如果在文章中的描述或者想法不正确或不恰当,希望路过的大佬们可以多多指正!
链接: https://pan.baidu.com/s/167ee8r1IMW80y3-MKq4aoQ
提取码: i4bk
到此这篇关于java实现简易超市管理系统 附源码下载的文章就介绍到这了,更多相关java实现超市管理系统内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/weixin_45510412/article/details/115030110