Java面向对象和MVC模式设计练习——快递管理系统

一、任务概述

本练习用于熟悉快递管理业务,完成快递管理控制台项目,具体需求如下:

采用二维数组的方式存储快递

  • 管理员
    • 录入快递
      • 柜子位置(系统产生,不能重复)
      • 快递单号(输入)
      • 快递公司(输入)
      • 6位取件码(系统产生,不能重复)
    • 删除快递(根据单号)
    • 修改快递(根据单号)
    • 查询所有快递(遍历)
  • 普通用户
    • 快递取出
      • 输入取件码:显示快递的信息 和 在哪个柜子中,从柜子中移除这个快递

功能实现如下:

存快递:
在这里插入图片描述
删除快递:
在这里插入图片描述
修改快递:
在这里插入图片描述

查询所有快递:
在这里插入图片描述

取件:
在这里插入图片描述

此习题来自 开课吧:《新职课JavaEE软件开发工程师》课程
第三章:面向对象
第6节:异常处理

二、MVC设计模式

1、定义

MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,它把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
在这里插入图片描述
MVC模式中三个组件的详细介绍如下:

  • 模型(Model):用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“Model”有对数据直接访问的权力,例如对数据库的访问。“Model”不依赖“View”和“Controller”,也就是说, Model 不关心它会被如何显示或是如何被操作;
  • 视图(View):能够实现数据有目的的显示(理论上,这不是必需的)。在 View 中一般没有程序上的逻辑。为了实现 View 上的刷新功能,View 需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册;
  • 控制器(Controller):起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变。

2、优点

a、低耦合

通过将视图层和业务层分离,允许更改视图层代码而不必重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变,只需要改动MVC的模型层(及控制器)即可。因为模型与控制器和视图相分离,所以很容易改变应用程序的数据层和业务规则。

由于运用 MVC 的应用程序的三个部件是相互独立,改变其中一个部件并不会影响其它两个,所以依据这种设计思想能构造出良好的松耦合的构件。

b、复用性强

随着技术的不断进步,当前需要使用越来越多的方式来访问应用程序了。MVC模式允许使用各种不同样式的视图来访问同一个服务端的代码,这得益于多个视图(如WEB(HTTP)浏览器或者无线浏览器(WAP))能共享一个模型。

比如,用户可以通过电脑或通过手机来订购某样产品,虽然订购的方式不一样,但处理订购产品的方式(流程)是一样的。由于模型返回的数据没有进行格式化,所以同样的构件能被不同的界面(视图)使用。例如,很多数据可能用 HTML 来表示,但是也有可能用 WAP 来表示,而这些表示的变化所需要的是仅仅是改变视图层的实现方式,而控制层和模型层无需做任何改变。

由于已经将数据和业务规则从表示层分开,所以可以最大化的进行代码重用了。

三、思路梳理

1、MVC架构设计

a、Controller

严格按照MVC模式来设计架构,Controller的作用是流程控制,用来将数据和视图连结。所以Controller中只包含逻辑判断代码,调用Model、View的代码,不包含任何业务运算代码和视图类的代码。

Controller中应当包含快递程序的主入口、判断分支后的各类方法。

b、Model

所有的业务内容,数据存储,数据修改方法等都在Model当中,不与View有任何的耦合关系。此练习只做面向对象练习,所以采用二维数组和快递类对象的方式来储存快递,不使用数据库。

c、View

此练习只做面向对象和MVC设计模式练习,用户交互页面使用打印和Scanner获取。View 中包含所有打印的方法和获取用户输入的方法,不包含任何逻辑和业务代码。

2、流程控制

首先考虑多层分支结构,获取用户输入的信息,分层判断

3、快递信息存储

创建Model类型的10×10的二维数据,来代替10×10的快递柜,可以存放100个快递对象。

快递使用对象的方式来存储,对象中包含快递单号、快递公司和取件码3个属性。

管理员存入快递时创建快递对象,其中快递单号和快递公司由管理员键盘输入并赋值给对象,取件码需要随机生成,同时保证单号和取件码与其他快递不重复。

4、随机生成取件码

采用Random类中的random(int bound)方法来随机生成6位取件码,bound为随机数的边界,当bound为100000时,会生成0~999999之间的随机数,如下:

Random random = new Random();
int code = random.nextInt(1000000);

但因为是int类型的随机数,所以有可能出现随机数不是6位数的情况,例如随机到了278,显然我们想要的是6位的“000278”,同时我们生活中很多常见的取件码都不以0作为开头,所以可以用如下方案生成100000~999999之间的取件码:

int code = random.nextInt(900000)+100000;

在生成取件码之后,我们还需要添加去重功能,同时用户需要通过取件码来查找快递,所以还需要编写一个方法,通过取件码来查询快递。还需要通过快递单号来查询快递的方法,用户管理员增删修改快递。

5、查找快递

a、按快递单号查找

需要编写一个方法,通过快递单号来查询二维数组中对应的快递对象,管理员添加快递输入单号时可以查重,删除修改和遍历快递也需要用此方法。

可以通过双层for循环,遍历二维数组,取出其中的快递对象,调用对象的get()方法,获取它的快递单号,来和我们给方法输入的单号做对比。

b、按取件码查找

与上同理,需要编写通过取件码查询快递的方法,用于用户取件和管理员存快递生成取件码时去重。

6、删除与修改

有了查找快递的方法之后,用户取件、快递员删除和修改快递,都可以先查找到对象,再在model类中对对象进行相应操作即可。主体思路框架有了,接下来开始撸代码。

四、任务拆解与代码

1、创建model、view、controller三个类

a、view

视图类,只包含Scanner对象,和各种打印方法。

import java.util.Scanner;

public class ExpressView {
   
    private final Scanner input = new Scanner(System.in);
    // 后续编写所有的视图打印方法
}

b、model

创建保存快递对象的二维数组,创建对象中的变量信息,String类型的快递单号,快递公司,和int类型的取件码,并为参数生成get和set方法(取件码只有get没有set方法),生成类的构造方法。

另外创建一个int类型的变量size,用来记录快递柜中已存入快递的数量。

public class ExpressModel {
   
    private ExpressModel express[][] = new ExpressModel[10][10];
    private String expressNumber;
    private String expressCompany;
    private int expressCode;
    private int size;

	public ExpressModel() {
   }
	public ExpressModel(String expressNumber, String expressCompany, int expressCode) {
   
        this.expressNumber = expressNumber;
        this.expressCompany = expressCompany;
        this.expressCode = expressCode;
    }

    public String getExpressNumber() {
   
        return expressNumber;
    }

    public void setExpressNumber(String expressNumber) {
   
        this.expressNumber = expressNumber;
    }

    public String getExpressCompany() {
   
        return expressCompany;
    }

    public void setExpressCompany(String expressCompany) {
   
        this.expressCompany = expressCompany;
    }

    public int getSize() {
   
        return size;
    }

    public int getExpressCode() {
   
        return expressCode;
    }
    // 后续编写业务方法
}

c、controller

Controller中需要调度view和model,创建实例对象。包含快递程序的一切流程,创建一个主方法作为快递功能的主入口。

public class ExpressController {
   
    ExpressView view = new ExpressView();
    ExpressModel model = new ExpressModel();

    public void expressMain() {
   }
}

2、视图类所有方法

视图方法可以随着Controller的编写逐个添加,这里为了方便下文阅读理解,提前列出视图类所有方法参阅。为保证程序正常运行,全部采用Scanner类中的nextLine()方法来接受用户输入的数据。

package pers.Enrico.ExpressMVC;

import java.util.Scanner;

public class ExpressView {
   
    private final Scanner input = new Scanner(System.in);

    public void printTitle() {
   
        System.out.println("快递单号\t快递公司\t取件码");
    }

    public void printExpress(ExpressModel express) {
   
        System.out.println(express.getExpressNumber()+"\t"+express.getExpressCompany()+"\t"+express.getExpressCode());
    }

    public void expressInEmpty() {
   
        System.out.println("当前快递柜内无快递。");
    }
    public void welcome() {
   
        System.out.println("\n===欢迎使用新职课快递柜===");
    }

    public void bye() {
   
        System.out.println("===欢迎再次使用新职课快递柜===");
    }

    public String getUser() {
   
        System.out.println("请输入您的身份:1-快递员,2-用户,0-退出");
        return input.nextLine();
    }

    public String getCourierOperation() {
   
        System.out.println("请选择操作:1-存快递 2-删除快递 3-修改快递信息 4-查看所有快递");
        return input.nextLine();
    }

    public String getExpressCode() {
   
        System.out.println("请输入取件码:");
        return input.nextLine();
    }

    public void getExpressOver() {
   
        System.out.println("取件成功!");
    }

    public void getExpressFail() {
   
        System.out.println("查无此取件码对应的快递,请检查取件码。");
    }

    public String getExpressNumber() {
   
        System.out.println("请输入快递单号:(输入0返回上一层)");
        return input.nextLine();
    }

    public String getExpressCompany() {
   
        System.out.println("请输入快递公司:");
        return input.nextLine();
    }

    public void addExpressOver(int code) {
   
        System.out.println("快递已成功存入!取件码为:"+code);
    }

    public void addExpressNumberError() {
   
        System.out.println("该单号的快递已存入,请检查快递单号。");
    }

    public void addExpressFull() {
   
        System.out.println("快递柜已满,无法存入");
    }

    public void updateExpressOver() {
   
        System.out.println("快递信息已修改,新信息如下:");
    }

    public void delExpressOver() {
   
    
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
开发阳光旅行网app中用户下单功能,可实现用户添加订单并完善出行人信息、修改订单,删除订单以及打印行程信息等功能。 具体功能要求如下: (1)显示系统主菜单 包括添加出行订单、查看我的出行订单、修改订单信息、删除出行人、查看行程、退出系统6项功能,其他功能本项目不做要求,当用户选择功能编号后可进入执行相应功能。执行结果如图1所示。 图1 主菜单 (2)添加出行订单 填写出行日期、联系人手机号码、循环录入出行人信息。 出行人信息包括:  出行人类别:成人、儿童(1.2m以下)、老人(65岁以上)  姓名  年龄(如选择类别为老人,输入年龄不足65岁的,显示提示信息“对不起,老人订单年龄需为65岁以上!”)  如果是儿童,需确定是否占床 每成功录入一条出行人信息后,显示出其详细信息,并计算出行金额。定价如下:  成人:2000元/人  儿童:免费,如需占床另加30元  老人:半价,即1000元/人 当一条出行人信息录入完毕后,提示“是否继续添加(Y/N)?”,此处不区分大小写,当输入y或Y时继续录入下一条,否则显示订单信息,包括:  出行日期  联系人手机号码  订单总金额(即所有出行人定单金额之和) 最后显示主菜单。执行效果如图2所示。 图2 添加出行订单 (3)查看我的出行订单信息 查看我的出行订单:查看所录入的订单信息。包括出行日期、联系人手机号码、所有出行人信息,运行效果如图3所示。 图3 查看我的出行订单 (4)修改行程信息 可修改出行日期、联系人手机号码,要求手机号码必须为11位,否则抛出异常信息,提示“手机号码必须为11位”,运行效果如果4所示。 图4 手机号码不是11位 正确修改后,显示修改后的信息,并提示“修改成功!”。如图5所示。 图5 修改订单成功 (5)删除出行人 填写要删除的出行人姓名,执行删除操作,删除成功后给出提示“删除成功!”,如图6所示。如果输入姓名错误,则提示“对不起,定单中不包含此游客信息!”如图7所示。 图6 删除出行人成功 图7 删除出行人失败 (6)查看行程 显示本次旅行行程信息。即读取“旅游行程.txt”文件(素材提供),显示在控制台。运行效果如图8所示。 图8 查看行程 (7)退出系统 退出当前系统,显示“欢迎下次再来。”如图9所示。 三、要求与实现步骤 (一)不使用数据库,使用对象和集合存储数据 (二)定义实体类(成人订单、儿童订单、老人订单),儿童订单、老人订单为成人订单的子类。实体类至少包含但不局限于以上3个。 (三)在各实体类中均需实现各自计算订单价格、显示订单信息的方法,使用方法的重写。 (四)定义工具类,实现查看我的出行订单、添加订单、修改行程信息、删除出行人、查看行程等方法。需使用到对象传参。 (五)使用泛型集合存储所有出行人信息,使用集合的遍历实现查看订单信息、统计订单总金额、删除出行人等功能。 (六)显示信息时,只有儿童出行人需显示是否占座,需使用面向对象多态实现。 (七)修改行程信息时,当手机号码录入错误时需使用throw手动抛出异常。 (八)使用I/O技术实现文件的读取功能,将文本文件“行程信息.txt”中的内容显示到控制台。 (九)定义测试类,完成项目功能菜单以及整体流程,调用相应方法实现具体功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值