[OOD设计] - 电梯系统设计

news2025/1/18 21:00:03

明确主要需求

首先需要设计电梯系统的基本工作流程,一个简单电梯系统主要就是两个主要功能:

  1. 乘客在电梯外按下按钮时,电梯系统会驱动一个电梯来接人
  2. 乘客在电梯内部按下楼层按钮时,电梯系统会驱动该电梯到达指定楼层 

根据需求来创建必要对象及属性

电梯系统类 - ElevatorSystem

用来管理系统中所有电梯类,并保存电梯调度算法 - (当乘客在外部摁键时,通过算法分配一个电梯去接人)

class ElevatorSystem {

    List<Elevator> elevators;
    Date datetime;

    private static final ElevatorSystem instance = new ElevatorSystem();

    private ElevatorSystem() {
        elevators = new ArrayList<>();
    }

    public static ElevatorSystem getInstance() {
        return instance;
    }

    public void addElevator(Elevator e) {
        elevators.add(e);
    }

    public Elevator assignElevator(Request req) {
        // 选一个IDLE状态的电梯,如果没有则找一个最不忙的电梯
        Elevator res = elevators.get(0);
        for (Elevator tmp: elevators) {
            if (tmp.status == Direction.IDLE) return tmp;
            else if (tmp.checkWorkLoad() < res.checkWorkLoad()) res = tmp;
        }

        return res;
    }
}

电梯类 - Elevator

用于保存电梯的各种属性(当前层,当前状态,最大承重,能到达的最高楼层),以及电梯接送人的顺序逻辑

  • 我们建立两个HashSet 来分别保存乘客向上和向下的请求,使用HashSet的优点是可以过滤掉重复请求,没到达一层时直接查找HashSet来决定停还是不停。
class Elevator {
    int currFloor; // 当前楼层
    Direction status; // 电梯当前方向
    int maxFloor;
    int maxWeight;

    HashSet<Integer> upQueue = new HashSet<>();
    HashSet<Integer> downQueue = new HashSet<>();

    public Elevator(int maxFloor, int maxWeight) {
        this.maxFloor = maxFloor;
        this.maxWeight = maxWeight;
        currFloor = 1;
        status = Direction.IDLE;
    }

    public void handleRequest(Request req) {
        if (req.dir == Direction.DOWN) {
            downQueue.add(req.floor);
        } else {
            upQueue.add(req.floor);
        }
    }

    public int checkWorkLoad() {
        // 查看当前电梯繁忙程度
        return downQueue.size() + upQueue.size();
    }

    public boolean run() {
        try {
            // status refresh
            // when reach 1st floor then switch status to up
            // when reach top floor than switch status to down
            // if status is down but not req in downQ then switch status to UP
            // if status is up but not req in upQ then swith status to Down
            // if no req then switch to IDLE
            if (currFloor==1 && status==Direction.DOWN) {
                status = Direction.UP;
            } else if (currFloor==maxFloor && status==Direction.UP) {
                status = Direction.DOWN;
            } else if (checkWorkLoad()==0) {
                status = Direction.IDLE;
            } else if (upQueue.size()==0) {
                status = Direction.DOWN;
            } else if (downQueue.size()==0) {
                status = Direction.UP;
            }

            // move to next stop
            // if status is down then find next stop and move
            // if status is up then find next stop and move
            if (status == Direction.DOWN) {
                for (int i = currFloor; i>=1; i--) {
                    if (downQueue.contains(i)) {
                        downQueue.remove(i);
                        currFloor = i;
                        return true;
                    }
                }
            } else if (status == Direction.UP) {
                for(int i = currFloor; i<=maxFloor; i++) {
                    if (upQueue.contains(i)) {
                        upQueue.remove(i);
                        currFloor = i;
                        return true;
                    }
                }
            }
        } catch (Exception ex) {
            System.out.println("Alert!!! call the emergency office");
        }
        return false;

    }
}

按键类 (或者请求类) - Request (InternalRequest/ExternalRequest)

这是一个抽象类,并被内部摁键类和外部摁键类继承,用于保存每一个乘客请求的具体信息

enum Direction  {
    UP, DOWN, IDLE
}

abstract class Request {
    int floor;
    Direction dir;
}

class ExternalRequest extends Request {
    int floor;
    Direction dir;

    public ExternalRequest(int f, Direction d) {
        floor = f;
        dir = d;
    }
}

class InternalRequest extends Request {
    int floor;
    Direction dir;

    public InternalRequest(int f, Direction d) {
        floor = f;
        dir = d;
    }
}

(非必要) 乘客类 - Passenger

保存乘客摁键行为的类

  • 按外部按键
  • 按内部按键
class Passenger {
    ElevatorSystem instance = ElevatorSystem.getInstance();
    Elevator assignedElv = null;

    public boolean pressExtButton(int floor, Direction dir) {
        assignedElv = instance.assignElevator(new ExternalRequest(floor, dir));
        return true;
    }

    public boolean pressIntButton(int floor) {
        Direction dir = Direction.IDLE;
        if (floor > assignedElv.currFloor) assignedElv.handleRequest(
                new InternalRequest(floor, Direction.UP));
        else if (floor > assignedElv.currFloor) assignedElv.handleRequest(
                new InternalRequest(floor, Direction.DOWN));
        else return false;
        return true;
    }
}

根据需求来创建相应函数

电梯系统类 - ElevatorSystem

  1. 将外部请求调度给系统中的一架电梯 - assignElevator(Request)

电梯类 - Elevator

  1. 处理按键请求 - handleRequest(Request)
  2. 根据所有请求运行电梯 - runElevator()

(非必要) 乘客类 - Passenger

  • 按外部按键 - pressExtButton()
  • 按内部按键 - pressIntButton()

加分要求

  1. 引入Enum类来定义常量状态
  2. 引入单例设计模式来定义ElevatorSystem类
  3. 增加电梯种类(货运电梯,载人电梯,VIP电梯) 不同电梯有不同策略
  4. 优化电梯调度
    1. 闲置电梯优先
    2. 如果没有闲置,选取请求数最少的电梯
  5. 优化电梯请求处理业务
    1. 如果非高峰期,可以采用FIFO方式处理请求
    2. 如果达到高峰期,可以根据当前电梯状态按照楼层升序处理相同状态的所有请求
  6. 根据电梯工作高峰期来使用不同的请求处理算法,使用Strategy设计模式     

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/532528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

泰克Tektronix AFG31021 任意波函数发生器产品资料

AFG31021是一款高质量、多功能的任意波形发生器&#xff0c;可以生成高精度、高分辨率的波形信号。该产品的主要特点包括&#xff1a; 可以生成任意波形信号&#xff0c;内置多种标准波形&#xff0c;如正弦波、方波、三角波、锯齿波等&#xff0c;也可以通过用户自定义来生成…

支付从业者转型路在何方?

近来&#xff0c;整个支付行业&#xff0c;已经“卷”出了新高度。 营销上电销卷地推&#xff0c;工单卷电销&#xff0c;POS机具则是退押金卷不退押金&#xff0c;无押金卷退押金”&#xff0c;互相“卷”得不亦乐乎。 与此同时&#xff0c;支付圈子里聊的永远是“成本上升”…

微信小程序是怎么做的?

微信小程序是一种轻量级的应用&#xff0c;它可以在微信内部直接使用&#xff0c;无需下载和安装。那么&#xff0c;微信小程序是怎么做的呢&#xff1f; 微信小程序制作的大概步骤 微信小程序制作主要包括以下几个步骤&#xff1a; ①注册小程序账号 ②在小程序制作工具创…

5th-Generation Mobile Communication Technology(一)

目录 一、5G/NR 1、 快速参考&#xff08;Quick Reference&#xff09; 2、5G Success 3、5G Challenges 4、Qualcomm Videos 二、PHY and Protocol 1、Frame Structure 2、Numerology 3、Waveform 4、Frequency Band 5、BWP 6、Synchronization 7、Beam Management 8、CSI Fra…

matmul/mm 函数用法介绍

介绍torch.matmul之前先介绍torch.mm函数, mm和matmul都是torch中矩阵乘法函数&#xff0c;mm只能作用于二维矩阵&#xff0c;matmul可以作用于二维也能作用于高维矩阵 mm函数使用 x torch.rand(4, 9) y torch.rand(9, 8) print(torch.mm(x,y).shape)torch.Size([4, 8]) m…

Linux Shell 实现一键部署VMware Workstation

VMware Workstation 前言 VMware Workstation Pro 是业界标准的桌面 Hypervisor&#xff0c;用于在 Linux 或 Windows PC 上运行虚拟机 download VMware_Workstation VMware_Workstation WindowsVMware_Workstation linux文档downloaddownload参考 Linux 各系统下载使用参…

Scrapy 基本使用

一、Scrapy框架使用 1. 创建scrapy项目&#xff08;不能有汉字&#xff0c;不能数字开头&#xff09; scrapy startproject Baidu 2. 创建爬虫文件 1. cd Baidu 2. scrapy genspider wenda www.baidu.com 注意&#xff1a; parse()是执行了start_url之后要执行的方法&#…

Camunda 外部任务(External Task)如何使用

Camunda的外部任务&#xff08;External Task&#xff09;是一种可分配和可重试的任务&#xff0c;与传统的用户任务不同&#xff0c;它可以在 Camunda 流程引擎之外的应用程序中执行。 外部任务可以用于将复杂的业务逻辑委托给外部系统&#xff0c;例如第三方服务或自定义的应…

Java简便模拟验证码

package staticStu.util;import java.util.Random;public class Login {public static void main(String[] args) {// 开发一个验证码// 1、定义一个变量记录验证码String code"";// 2、定义一个变量记住全部验证码字符String data"abcdefghijklmnopqrstuvwxyzA…

mongodb wireshark显示

mongodb wireshark展示为ssl&#xff0c;只需要禁用tls&#xff0c;然后把当前会话解码为mongo就可以

鸿蒙Hi3861学习十四-Huawei LiteOS-M(AP模式)

一、简介 参看上一章&#xff1a;鸿蒙Hi3861学习十四-Huawei LiteOS-M&#xff08;STA模式&#xff09;_t_guest的博客-CSDN博客 二、API介绍 RegisterWifiEvent 函数功能&#xff1a; 为指定的WIFI事件注册回调函数。当WIFIEVENT中定义的WIFI事件发生时&#xff0c;将调用已注…

MySQL体系架构

一、 MySQL体系架构 MySQL体系架构可分为物理架构和逻辑架构。 1、MySQL物理体系架构 1.1 配置文件 auto.cnf: 配置了MySQL Server的UUIDmy.cnf: MySQL的配置文件 1.2 其他重要文件 -basedirdir_name: MySQL安装的二进制文件目录-datadirdir_name: MySQL的数据目录和-pid-…

使用 Conv1D-LSTM 进行时间序列预测:预测多个未来时间步【优化】

未优化之前的版本见下&#xff0c;作者当时主要是为Mark这个项目&#xff0c;未进行深入分析。 使用 Conv1D-LSTM 进行时间序列预测&#xff1a;预测多个未来时间步 Introduction 通常有许多时间序列预测方法&#xff0c;例如 ARIMA、SARIMA 和 Holtz-winters&#xff0c;但是…

计算机网络基础(子网划分)

文章目录 一、网络设备二、IP地址分类A类地址B类地址C类地址特殊IP地址 三、划分子网根据子网掩码判断主机数根据子网和主机判断子网掩码根据IP和子网掩码判断子网数 四、场景运用 一、网络设备 1.集线器&#xff08;hub&#xff09;&#xff1a;不可以隔离冲突域&#xff0c;…

Redis内存优化——ZSet类型介绍及底层原理详解

系列文章目录 Redis内存优化——String类型介绍及底层原理详解 Redis内存优化——Hash类型介绍及底层原理详解 Redis内存优化——List类型介绍及底层原理详解 Redis内存优化——Set类型介绍及底层原理详解 Redis内存优化——ZSet类型介绍及底层原理详解 文章目录 系列文章目录…

Ingress:k8s集群进出流量的总管

Ingress&#xff1a;k8s集群进出流量的总管 Service 对象&#xff0c;它是 Kubernetes 内置的负载均衡机制&#xff0c;使用静态 IP 地址代理动态变化的 Pod&#xff0c;支持域名访问和服务发现&#xff0c;是微服务架构必需的基础设施。 Service 很有用&#xff0c;但也只能说…

分享一个国内可用的ChatGPT网站,免费无限制,支持AI绘画 - AI 百晓生

背景 ChatGPT作为一种基于人工智能技术的自然语言处理工具&#xff0c;近期的热度直接沸腾&#x1f30b;。 作为一个AI爱好者&#xff0c;翻遍了各大基于ChatGPT的网站&#xff0c;终于找到一个免费&#xff01;免登陆&#xff01;手机电脑通用&#xff01;国内可直接对话的C…

使用apisix代理静态文件

前言 最近公司考虑用apisix作为公司网关并且部署到k8s上&#xff0c;我这边收到一个小任务&#xff1a;使用apisix代理静态文件 通过apisix官网了解到它构建于 NGINX ngx_lua 的技术基础之上&#xff0c;所以按理应该和nginx代理静态资源是一样的。因为是通过docker容器部署…

STM32-内部温度传感器实验

STM32内部是有温度传感器的&#xff0c;以F1为例&#xff0c;它的温度采集范围是-40度到125度&#xff0c;精度为正负2度&#xff0c;采样通道为ADC1_INI6&#xff0c;上电控制位为TSVREFE位。 温度计算方式为&#xff1a;T(摄氏度) (V25 - Vsense) / Avg_Slope 25&#xff…

数据库管理-第七十六期 如何升级19c RAC(20230516)

数据库管理 2023-05-16 第七十六期 如何升级19c RAC1 回头处理2 升级AHF3 升级GI及DB3.1 拷贝所需文件3.2 升级OPatch3.3 升级GI与DB3.4 应用SQL变更 4 升级OJVM4.1 解压补丁4.2执行补丁冲突检查&#xff1a;4.3 升级OJVM4.4 应用SQL变更 5 最终验证总结 第七十六期 如何升级19…