【Java作业】模拟停车场

分类专栏:
Java作业

文章标签:
Java基础
原创

前言

此文为记录一次Java课的小作业所写,适合停留在Java基础的新手练习。

一、实验内容

随着家庭购买汽车的增加,停车场车位紧张的问题越来越突出。请根据题目要求完成简单的车位管理程序。 1.停车场有若干停车位(为说明问题,假定为n个,可扩),每个位置可以存放不同种类的的汽车,包括卡车Truck,客车Carriage和小轿车Car,但同一时刻一个位置只能存放0或1辆汽车。 2.管理系统模拟实际车辆停车的情况:新来车辆时如果有空位,按顺序为该车分配停车位;车辆开走时,按停车场的收费标准交纳相应停车费(假定停车场能获取车辆对象的类别);统计各类车辆的数量。 3.定义描述停车场的类Park,其中有n个位置用于存放各类车辆。 4.定义基类Automobile:①驾驶员;②车牌号(字符串)、车辆类别(分为Car、Truck、Carriage);③String getMobileMessage()车辆相关信息;④parking()泊车、start()开车、pause()暂停等。 5.定义派生类Truck,Carriage和Car,这些车辆除了拥有车牌号(字符串)、车辆已使用年数(整数)之外, Truck还拥有载重量(浮点数,单位吨)属性,Carriage还拥有乘坐人数(整数,单位人)属性, Car还拥有排气量(浮点数,单位L)属性。 6.每辆车上只有一驾驶员,驾驶员按停车场的收费要求支付费用;按现实停车场的场景来模拟需有的动作(方法):在出口前停车、付费、开车、泊车等。 7.收费标准:其中Truck收费2元/小时,Carriage收费1.5元/小时,Car收费1元/小时。 8.测试上述所要求的各种功能,即根据菜单命令为新来车辆分配停车位、开走车辆(输入车位编号)时付费、显示停车场中各类车辆的数量。

二、程序设计

1.UML图

在这里插入图片描述

2.设计思路

①车类设计

无论是Car,Truck还是Carrige,都是继承基类AutoMoblie,它抽象了各种车的公共部分,同时Car,Truck和Carrige都有自己独有的属性,同时基类中有私有属性Type,用来标识车是什么类型的车,同时覆写了getMobileMessage方法(用来返回具体的字符串)

在这里插入图片描述

②人与车的关系

车有私有属性people,即AutoMoblie聚合了People类,主要用来模拟人坐进车中这么一个操作;同时People类也依赖于AutoMoblie类,主要体现在调用people方法时,也会相应的调用车的方法。

③停车场类实现方式

停车场内部维护了两个ArrayList数组,一个用来存储车位信息,一个用来存储各车位计时

在这里插入图片描述

④停车场自动安排车位和扩容机制

每当车辆进入时,程序会自动检查automobiles,如果有空车位则进入,并且times数组开始计时,否则则对数组进行扩容已达到停车场扩容的效果。

在这里插入图片描述

⑤停车场实时情况展示(display方法)

Park类中有个display方法,用于展示当前停车场的具体情况

在这里插入图片描述

具体效果如下:

在这里插入图片描述

在这里插入图片描述

⑥获取总车位信息

Park类中有个获取真实容量的方法,因为Park类中使用ArrayList来存储数据,但是其中真实数组elementData是私有的并不对外提供操作的方法,这时我们获取其真实的容量大小就得通过反射来进行,具体操作如下

在这里插入图片描述

⑦类型和收费标准的抽象(Type类和Charging)

为了达到开闭原则,提升系统的延展性,我把类型和收费标准抽象出来单独成类,未来要是要修改类型和收费标准,可以直接替换这两个类,当然更好的操作是再设计接口,未来如果要改,直接实现该接口就行,但是为了方便起见,我这里没有设计相应接口(主要是觉得太麻烦了)。 具体操作如下:

在这里插入图片描述

在这里插入图片描述

⑧测试类中自定义类MyRandom

为了更好模拟停车场实际情况,特意设计类一个随机类,用于返回随机车牌号等。

在这里插入图片描述

⑨测试类模拟停车场

为了使测试更清楚,这里把一秒当做一小时来计算

在这里插入图片描述

在这里插入图片描述

三、代码详情

1.基类Automobile

package com.dreamchaser.park;

public class Automobile {
    /**
     * 驾驶员
     */
    private People people;
    /**
     * 车牌号
     */
    private String number;
    /**
     * 车辆已使用年年数
     */
    private Integer year;
    /**
     * 车辆类别
     */
    private Type type;

    public People getPeople() {
        return people;
    }

    public void setPeople(People people) {
        this.people = people;
    }

    public Integer getYear() {
        return year;
    }

    public void setYear(Integer year) {
        this.year = year;
    }

    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    public Automobile(People people, String number, Integer year) {
        this.people = people;
        this.number = number;
        this.year = year;
    }


    public String getMobileMessage(){
        return "驾驶员:"+people+" ;车牌号:"+number+" ;车辆类别:"+type;
    }

    public void parking(int i){
        System.out.println(people+"把车开到"+i+"号车位泊车!");
    }
    public void start(){
        System.out.println("车已启动!");
    }

    public void pause(String s){
        System.out.println(people+"把车暂时停在了"+s);
    }

}



2.派生类Car

package com.dreamchaser.park;

public class Car extends Automobile{
    /**
     * 排气量
     */
    private float  displacement;

    public Car(People people, String number, Integer year, float displacement) {
        super(people, number, year);
        this.displacement = displacement;
        this.setType(Type.CAR);
    }

    @Override
    public String getMobileMessage() {
        return super.getMobileMessage()+" ;排气量:"+displacement+"L";
    }
}

3.派生类Carriage

package com.dreamchaser.park;

public class Carriage extends Automobile{
    private Integer peopleNumber;

    public Carriage(People people, String number, Integer year, Integer peopleNumber) {
        super(people, number, year);
        this.peopleNumber = peopleNumber;
        this.setType(Type.CARRIAGE);
    }
    @Override
    public String getMobileMessage() {
        return super.getMobileMessage()+" ;乘坐人数:"+peopleNumber+"人";
    }
}

4.派生类Truck

package com.dreamchaser.park;

public class Truck extends Automobile{
    private float capacity;

    public Truck(People people, String number, Integer year, float capacity) {
        super(people, number, year);
        this.capacity = capacity;
        this.setType(Type.TRUCK);
    }

    @Override
    public String getMobileMessage() {
        return super.getMobileMessage()+" ;载重量:"+capacity+"吨";
    }

}

5.People类

package com.dreamchaser.park;

public class People {
    /**
     * 驾驶员名字
     */
    private String name;

    public People(String name) {
        this.name = name;
    }

    /**
     * 在出口前停车
     */
    public void stop(Automobile automobile){
        automobile.pause("出口");
    }

    /**
     * 付费
     * @param d
     */
    public void pay(double d){
        System.out.println("付费"+d+"元!");
    }

    /**
     * 开车
     */
    public void drive(Automobile automobile){
        automobile.start();
    }

    /**
     * 泊车
     * @param i
     */
    public void park(Automobile automobile,int i){
        automobile.parking(i);
    }

    @Override
    public String toString() {
        return name;
    }

    public void into(Automobile automobile,Park park){
        stop(automobile);
        System.out.println("车辆信息:"+automobile.getMobileMessage());
        drive(automobile);
        park(automobile,park.park(automobile));
        System.out.println("---------------------------------------");
    }
    public void out(Automobile automobile,Park park){
        drive(automobile);
        stop(automobile);
        System.out.println("车辆信息:"+automobile.getMobileMessage());
        pay(park.out(automobile));
        drive(automobile);
        System.out.println("---------------------------------------");
    }
}


6.Park类

package com.dreamchaser.park;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class Park {
    /**
     *初始停车场车位为10
     */
    private List<Automobile> automobiles=new ArrayList<>(10);
    /**
     * 存储时间
     */
    private List<Long> times=new ArrayList<>();
    int capacity=getArrayListCapacity((ArrayList<?>) automobiles);

    public int park(Automobile automobile){
        Date date=new Date();
        int i=0;

        for (;i<automobiles.size();i++){
            Automobile a=automobiles.get(i);
            if (a==null){
                automobiles.set(i,automobile);
                times.set(i,date.getTime());
                return i;
            }
        }
        //车位不够则扩容
        automobiles.add(automobile);
        times.add(date.getTime());
        //比较容量,如果size大于容量,说明容量已被扩充,需更新并通知
        if (automobiles.size()>capacity){
            System.out.println("---------------------------");
            capacity=getArrayListCapacity((ArrayList<?>) automobiles);
            System.out.println("车位扩容!当前停车场车位总数为"+capacity);
            System.out.println("---------------------------");
        }
        return i;
    }
    public double out(Automobile automobile){
        Date date=new Date();
        long t=0;
        for (int i=0;i<automobiles.size();i++){
            if (automobiles.get(i)==automobile){
                automobiles.set(i,null);
                t=date.getTime()-times.get(i);
                times.set(i,null);
                System.out.println(i+"号车位的车已驶离!");
                break;
            }
        }

        //这里为了演示清楚,一秒当一小时
        return t/1000*Charging.getCharging(automobile.getType());
    }

    /**
     * 通过反射获取list中的数组,然后通过数组返回其容量大小
     * @param arrayList
     * @return
     */
    public static int getArrayListCapacity(ArrayList<?> arrayList) {
        Class<ArrayList> arrayListClass = ArrayList.class;
        try {
            //获取 elementData 字段
            Field field = arrayListClass.getDeclaredField("elementData");
            //开始访问权限
            field.setAccessible(true);
            //把示例传入get,获取实例字段elementData的值
            Object[] objects = (Object[])field.get(arrayList);
            //返回当前ArrayList实例的容量值
            return objects.length;
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
    }

    public void display(){
        System.out.println("当前停车场情况:");
        System.out.println("\t\t\t\t金昊霖的停车场\t\t\t\t");
        System.out.println("------------------------------------------------------");
        //外置变量记录循环的次数
        int a=0;
        for (Automobile automobile:automobiles){
            if (a%5==0){
                System.out.println();
                System.out.print("|\t");
            }
            if (automobile==null){
                System.out.print("空\t|\t");
            }else{
                System.out.print(a+"\t|\t");
            }
            a++;
        }
        System.out.println();
        System.out.println("------------------------------------------------------");
    }
}


7.启动测试类Main

package com.dreamchaser.park;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Main {
    public static void main(String[] args) {
        Park park=new Park();
        List<People> peoples=new ArrayList<>(20);
        for (int i=0;i<20;i++){
            peoples.add(new People("第"+i+"个志愿者"));

        }
        List<Automobile> automobiles=new ArrayList<>(20);
        for (int i=0;i<20;i++){
            Type type=MyRandom.getType();
            if (type==Type.CAR){
                automobiles.add(new Car(peoples.get(i), MyRandom.getLicense(),MyRandom.getInteger(),MyRandom.getInteger()));
            }else if (type==Type.CARRIAGE){
                automobiles.add(new Carriage(peoples.get(i), MyRandom.getLicense(),MyRandom.getInteger(),MyRandom.getInteger()));
            }else if (type==Type.TRUCK){
                automobiles.add(new Truck(peoples.get(i), MyRandom.getLicense(),MyRandom.getInteger(),MyRandom.getFloat()));
            }

        }


        try {
            //前十辆驶入停车场
            for (int i=0;i<10;i++){
                peoples.get(i).into(automobiles.get(i),park);
            }
            //显示停车场当前情况
            park.display();
            //1个小时后
            Thread.sleep(1000);
            //前五辆驶出停车场
            for (int i=0;i<5;i++){
                peoples.get(i).out(automobiles.get(i),park);
            }
            //显示停车场当前情况
            park.display();
            //后十辆驶入停车场
            for (int i=10;i<20;i++){
                peoples.get(i).into(automobiles.get(i),park);
            }
            //显示停车场当前情况
            park.display();
            //2个小时后
            Thread.sleep(2000);
            //后十辆驶出停车场
            for (int i=10;i<20;i++){
                peoples.get(i).out(automobiles.get(i),park);
            }
            //显示停车场当前情况
            park.display();
            //1个小时后
            Thread.sleep(1000);
            //剩下五辆驶出停车场
            for (int i=5;i<10;i++){
                peoples.get(i).out(automobiles.get(i),park);
            }
            //显示停车场当前情况
            park.display();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class MyRandom{
    static Random random=new Random();
    public static String getLicense(){
        return "浙"+(char) (Math.random ()*26+'A')+(int)(Math.random ()*10)+(int)(Math.random ()*10)+(int)(Math.random ()*10)+(int)(Math.random ()*10);
    }
    public static Type getType(){
        int i= (int)(Math.random()* Type.values().length);
        return Type.values()[i];
    }
    public static Integer getInteger(){
        return random.nextInt(100);
    }
    public static float getFloat(){
        return random.nextFloat();

    }
}


8.Charging类

package com.dreamchaser.park;

public class Charging {
    public static double getCharging(Type type){
        if (type==Type.CAR){
            return 1;
        }else if (type==Type.CARRIAGE){
            return 1.5;
        }else{
            return 2;
        }
    }
}


9.Type类

package com.dreamchaser.park;

public enum Type {
    TRUCK,CAR,CARRIAGE
}

四、运行结果(测试结果)

注:此处为了更好的模拟效果,程序将一秒当做一小时来计算

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

总结

此作业涉及继承、覆写、反射、线程、设计模式等Java基础知识点,适合当做初学Java的新手练习。

  • 作者:金昊霖
  • 发表时间:2020-7-04
  • 版权声明:自由转载-非商用-非衍生-保留署名(创意共享3.0许可证)
  • 评论

    留言