java - 使用 Java Runnable 进行糟糕的类设计
问题描述
您能否解释一下为什么在以下程序中以这种方式实现 Runnable 接口是一个糟糕的设计决策?直观地说,如果我必须自己编写这个,我会让 Hotel 成为它自己的类,并在一个实现 Runnable 的新类中为 run() 编写规范。但是,我无法真正解释为什么下面的代码是一个糟糕的设计决定。
该课程模拟了一家酒店,里面有排队的人和房间列表。有几个“工作台”在不同的线程上运行,每个工作台负责从队列中移除人员并将他们签入可用的房间。为简单起见,不包括退房。方法的实现并不重要(相信它是线程安全的),这个问题是关于将 run() 放入 Hotel 类的设计决策。
public class Hotel implements Runnable {
private final static int NR_ROOMS = 10;
private final Person [] rooms = new Person [ NR_ROOMS ];
private final List < Person > queue = new ArrayList < >();
private final Lock queueLock = new ReentrantLock ();
private boolean occupied (int i) {
return ( rooms [i] != null);
}
private int checkIn ( Person p) {
// add Person to a free room
}
private void enter ( Person p) {
// add a person to the waiting queue
}
// every desk employee should run as a separate thread
@Override
public void run () {
// remove guests from the queue and check them in
}
}
解决方案
OO 编程的重点是创建对业务逻辑建模的类;由于您的问题涉及酒店、房间、人员等,因此可以期望在您的问题域中存在代表这些“名词”的类。然后这些类上的方法表示对对象执行的操作。
我run()
对 Hotel 类的方法的直接问题是根本不清楚酒店“运行”的含义。我想在某些情况下这可能是有道理的;例如,如果你有一个模拟,并且有关于酒店随着时间推移应该发生的事情的规则。不自然的部分是酒店通常是发生事情的地方,而不是做事情的地方。
就此而言,在我看来,酒店实例有一个 列表rooms
,每个列表都是 类型Person
。您可以通过这种方式使简单的逻辑工作,但是 OO 设计的原则之一是使现有程序的扩展变得容易,因为您已经对问题域的真实世界对象进行了建模,因此用它们做更多的事情将是自然比你没有更容易。在这种情况下,在我看来,如果 Hotel 有一个 Room 对象列表,那么每个 Room 对象可以包含一定数量的 Person 对象,则可以更好地匹配已知问题空间。那么一个房间里的人数就更灵活了,不同房间的人数可能不同,等等。
我完全赞成从一个简单的系统开始,但既然你问的是 OO 设计,我想我会借此机会指出这些关于这个的事情。
推荐阅读
- concourse - Concourse CI 中的资源类型:如果 Check 总是只返回最新版本会怎样?
- azure - 将模型部署到 Kubernetes
- django - docker 容器上的 Django 在生产服务器中返回 localhost 作为域
- python - Python 将原始 GMT 转换为其他时区,例如 SGT
- html - 极高的元素故障
- mysql - 加载数据本地 INFILE 错误 2068 (HY000)
- here-api - 这里 Map Api 使用 Retrofit 获取调用
- apache-spark - Spark SQL - 默认情况下未启用配置单元
- regex - 使用正则表达式提取以特定目标 URL 开头的链接的锚文本
- objective-c - 如何修改此 SRT 文件解析器?