java面向对象思维程序设计开发以及案例 -电梯运行问题对象分析与程序设计(1)

简介: java面向对象思维程序设计开发以及案例 -电梯运行问题对象分析与程序设计(1)

电梯是我们日常生活中经常看见和使用的运载工具,但其中也隐藏着一个精而小的程序,我们今天模拟一个电梯运行程序来开始我们面向对象之旅


电梯问题-抽取关键需求


1.电梯首先肯定是要可以上下不间断运行

2.可以达到顶层或底层之后向反方向继续运行

3.人员可以按钮然后等待电梯停在本楼层并进入

4.进入的人可以选择自己的目的层数

5.电梯可以在目的层数停止等待一定时间后继续运行


问题需求关键环节流程图


我们进入需求转化环境,我们来梳理一下需求并且转化为一个时序图,便于我们拆分对象以及确定逻辑顺序,流程图如下

1.png

初步领域对象分析,最小可用原则


我们创建对象以及方法要使用最小可用原则,既不需要的就不要加进对象,直到确定需要这个对象或  者属性或者方法再添加,所以可以如下分析

依据时序图,我们初步分为了对象人person与对象电梯elevator

对象电梯可以被启动,然后不断运行,所以我们觉得他应该有一个start方法

我们也许会觉得对象人是外部触发电梯start 方法的对象

电梯应该方法是判断是否到顶部isTop(),是否到底部isBottom(),并且有一个方法是wait() 等待人进入并且选择目标层数selectFloor(int floor)

那么我们的对象建模就结束了,领域建模图如下

1.png

对象建模思考


思考1:电梯运行是否内部维护运行状态,是否需要一个start方法


我个人认为都可以,这里我是按照不需要设计的,我这里把电梯运行和电梯本身认为是两个实体,你 可以用轿厢品牌1 带动电梯,第二天也可以用轿厢2带动电梯,

也就是说电梯是被外部轿厢发动机带动运行的,而电梯本身只负责内部运行逻辑处理

换句话说我的运行创建线程并不是电梯内部维护的,而是适用方,可以用线程池,也可以直接new thread

这样就把更大的自由度留给了电梯合作方:电机轿厢,也符合易扩展多方合作的共赢思维


思考2:是否需要人这个person对象


本程序我们真的需要人这个对象吗,

实际上人在这里的作用无非就是提供电梯需要停止的层数

而实际上这个程序的外部使用者是真正活着的实体人

因此,我们在程序里定义人这个对象是多余的,所以我们可以将对象人person这个类去掉,换成层数floor

重新分析后-最终领域对象图

1.png

面向对象程序设计核心思想原则


1.就是让人从外面看起来就知道你的代码是在干什么,每一个对象都要有意义,并且真实符合世界上实体事物运行规则

2.设计的对象没有绝对的对与错,只要让人觉得你的对象确实合理并且使用起来符合正常人的思维习惯就可以

经过以上分析建模,形成目前的初版代码如下

public class ElevatorTest {
    public static void main(String[] args){
        //18层的电梯
        int floor = 18;
        //电梯初始化
        Elevator elevator = new Elevator(floor);
        //创建一个线程池,初始化两个线程,1:电梯运行线程,2:模拟随机层数人员进入电梯线程
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,2,10L, TimeUnit.SECONDS,new  ArrayBlockingQueue(2));
        //启动电梯
        threadPoolExecutor.execute(elevator);
        //模拟随机楼层人员进电梯与出电梯
        threadPoolExecutor.execute(()->{
                while (true){
                    //模拟随机生成 1~18楼人
                    int enterRandom = new Random().nextInt(18);
                    if(enterRandom ==0){
                        continue;
                    }else {
                        try {
                            //人员进入
                            elevator.enter(enterRandom);
                            Thread.sleep(3000);
                        }catch (InterruptedException e){
                        }
                    }
                }
        });
    }
}
class Elevator implements Runnable {
    boolean start = false;
    int currentFloor ;
    boolean directionTop = true;
    int floor ;
    //保存目标层数map
    Map enterMap = new HashMap(18);
    ReentrantLock lock = new ReentrantLock();
    public Elevator(int floor){
        this.floor = floor;
        this.currentFloor = 1;
        System.out.println("初始化了一个"+floor+"层的电梯,当前电梯在第1层");
    }
    /**
     * 人员进入电梯同时选择好目标层数
     * */
    public void enter(int outFloor){
        lock.lock();
        System.out.println("人员进入,按了"+outFloor+"层");
        enterMap.put(outFloor,null);
        lock.unlock();
    }
    /**
     * 是否是顶层
     * */
    public boolean isTop(){
        return this.currentFloor == floor;
    }
    /**
     * 是否是底层
     * */
    public boolean isBottom(){
        return this.currentFloor == 1;
    }
    @Override
    public void run() {
        System.out.println("电梯启动");
        start = true;
        while (start){
            if(!lock.isLocked()) {
                try {
                    if (directionTop) {
                        currentFloor++;
                        System.out.println("当前在电梯第" + currentFloor + "层");
                        //该层人员出门出门后将该层移除
                        if(enterMap.containsKey(currentFloor)){
                            try {
                                System.out.println(currentFloor+"人员出门");
                                enterMap.remove(currentFloor);
                                System.out.println("剩余楼层"+enterMap.keySet());
                                Thread.sleep(5000);
                            }catch (Exception e){
                            }
                        }
                        if (isTop()) {
                            directionTop = false;
                            System.out.println("到达顶层,开始向下运行");
                        }
                    } else {
                        currentFloor--;
                        System.out.println("当前在电梯第" + currentFloor + "层");
                        //该层人员出门出门后将该层移除
                        if(enterMap.containsKey(currentFloor)){
                            try {
                                System.out.println(currentFloor+"人员出门");
                                enterMap.remove(currentFloor);
                                System.out.println("剩余楼层"+enterMap.keySet());
                                Thread.sleep(5000);
                            }catch (Exception e){
                            }
                        }
                        System.out.println("当前在电梯第" + currentFloor + "层");
                        if (isBottom()) {
                            directionTop = true;
                            System.out.println("到达1层,开始向向运行");
                        }
                    }
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
            }else {
                try {
                    System.out.println("进人中。。");
                    Thread.sleep(5000);
                }catch (Exception e){
                }
            }
        }
    }
}

运行输出结果


初始化了一个18层的电梯,当前电梯在第1层

电梯启动

当前在电梯第2层

人员进入,按了17


当前在电梯第3层

当前在电梯第4层

当前在电梯第5层

人员进入,按了13


当前在电梯第6层

当前在电梯第7层

当前在电梯第8层

人员进入,按了7


当前在电梯第9层

当前在电梯第10层

当前在电梯第11层

人员进入,按了6


当前在电梯第12层

当前在电梯第13层

13人员出门

剩余楼层[6, 7, 17]

人员进入,按了11


人员进入,按了4


当前在电梯第14层

人员进入,按了13


当前在电梯第15层

当前在电梯第16层

当前在电梯第17层

17人员出门

剩余楼层[4, 6, 7, 11, 13]

人员进入,按了7


人员进入,按了1


当前在电梯第18层

到达顶层,开始向下运行

人员进入,按了16


当前在电梯第17层

当前在电梯第17层

当前在电梯第16层

16人员出门

剩余楼层[1, 4, 6, 7, 11, 13]

人员进入,按了4


人员进入,按了3


当前在电梯第16层

当前在电梯第15层

当前在电梯第15层

当前在电梯第14层

当前在电梯第14层

人员进入,按了14


当前在电梯第13层

13人员出门

剩余楼层[1, 3, 4, 6, 7, 11, 14]

人员进入,按了10


当前在电梯第13层

人员进入,按了10


当前在电梯第12层

当前在电梯第12层

当前在电梯第11层

11人员出门

剩余楼层[1, 3, 4, 6, 7, 10, 14]


面向对象到底是节省时间还是浪费时间


其实使用面向对象角度建模并且进行程序开发并不是耗费时间,而是节省时间

因为设计的对象是充血模型,所以后续其他业务使用对应功能只需要对象.方法就可以了,这也是DDD 领域驱动设计的核心思想

而且面向对象设计开发也是利于大家对需求转化的加深,会加速开发效率,比如这个程序我建模可能用了30分钟,但编码只用了15分钟左右


结语


程序是依照我们小设计原则没有任何优化重构编写的,肯定细节上还有容错以及重用上有很多问题

但这就是程序设计,因为他满足了最小化的我们的需求

但是,问题终究是问题,我们还是要解决的,先把当前代码重构,然后我们要把缺失逻辑补充:

比如并没有实现人按电梯上下进入的操作,进入的人并没有实现同时允许多层数选择的操作等

没有使用层数floor对象,而是用map简单表示

下一篇我们将继续优化并完成这个电梯程序


相关文章
|
5天前
|
存储 监控 Java
JAVA线程池有哪些队列? 以及它们的适用场景案例
不同的线程池队列有着各自的特点和适用场景,在实际使用线程池时,需要根据具体的业务需求、系统资源状况以及对任务执行顺序、响应时间等方面的要求,合理选择相应的队列来构建线程池,以实现高效的任务处理。
79 12
|
20天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
6天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
67 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
30天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
116 13
|
1月前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
81 10
|
28天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
62 2
|
1月前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
Java
java中面向过程和面向对象区别?
java中面向过程和面向对象区别?
27 1
|
8天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
48 17