面试题讨论,类设计

2021-04-24 17:35:04 +08:00
 csfreshman

虾皮面经中看到一道题: 如果要实现一个聊天室的逻辑,有 room 和 user 两个类,而 room 设置有一个门,而且有“主人的设定,只有主人才能开门和关门。请问开门和关门的方法,你会放到 room 类还是 user 类中实现 ?为什么?

各位大佬,如果你面试时遇到会怎么回答。 我的想法是: 放在 room 类,room 类中保存房间主人,user 用户如果是主人可以开门或关门,本一菜鸡没看懂这题到底要考察啥?跪求各位大佬指点 讨论。

4077 次点击
所在节点    程序员
31 条回复
RedisMasterNode
2021-04-24 17:42:19 +08:00
哈哈哈 我猜这是 chatbot 团队的面试官

room 类+1
raaaaaar
2021-04-24 17:48:38 +08:00
room,因为门和 room 是一一对应的,是 room 的一种功能。而 room 相关的信息都应该封装在 room 类日,这样才能根据不同的 user 表现出不同的功能,不仅仅是门
raaaaaar
2021-04-24 17:50:10 +08:00
比如说 room 加一个 owner 的属性,当 user 调用 room 时就比较下,根据结果走不同的分支
MoHen9
2021-04-24 18:29:06 +08:00
菜鸡一枚,说说我的看法,我也 get 不到想问什么,可能是对面向对象思想的考察,首先房间有门,门有开关的动作,这是与现实世界的对应,符合基本逻辑,房间有管理员,可以执行开关门的动作,谁是管理员谁就拥有开关门的权限。这样门和房间主人是关联关系,房间主人可以有一个也可以有多个。

如果门或者动作放到 User 上,一个人有多个门时,还得找这些门和对应房间的关系,一个门有多个主人时,啊,什么鬼👻,打出去,乱棍打出去。。。🌚🌚
BeautifulSoap
2021-04-24 18:35:38 +08:00
开门关门的意思是能否允许其他用户进入?
第一直觉是 room 类实现具体怎么开门(因为开门的具体逻辑可能很复杂,交给 user 类的话相当于将 room 类内部详细的结构给暴露了),room 通过对外暴露一个开门关门的接口接受认证信息 or 鉴权,用户直接调用,这样用户只需要持有各个房间的钥匙(认证信息 or 鉴权信息)就行了

如果想搞不同开门方式,或者开门后限制不同人,或复杂的鉴权的话,可能将相关逻辑独立成单独的类比较好。但这个问题只有两个类,倒也不好展开
huijiewei
2021-04-24 19:24:15 +08:00
这个里面需求也不说

要我就按照最复杂的来搞

请个保安
nuistzhou
2021-04-24 19:44:23 +08:00
很简单吧,就是类的设计吧。我也选开关门的 method 放在 room 里,user 可以有个 type 为字典的属性,开关门的 method 验证该用户的这个字典里是否有这个 room 的 key,来鉴权。
charlie21
2021-04-24 19:50:39 +08:00
左手右手一个慢动作 右手左手慢动作重播
先写一个 room interface 这是它需要的
psx2019
2021-04-24 21:48:49 +08:00
```java
public class Room{
String roomId;
String key;
Boolean openStatus;
public Room() {
this.roomId = UUID.randomUUID().toString();
this.key = UUID.randomUUID().toString();
this.openStatus = false;
}

public String getRoomId() {
return roomId;
}

public String getKey() {
return key;
}

public Boolean getOpenStatus() {
return openStatus;
}

public void openOrClose(String key) {
if (this.key.equals(key)) {
this.openStatus = !this.openStatus;
}
}
}

public class User {
String name;
Map<String, String> roomKeys =new HashMap<String, String>();
Map<String, Room> rooms =new HashMap<String, Room>();

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

public String getName() {
return name;
}

public Map<String, String> getRoomKeys() {
return roomKeys;
}

public Map<String, Room> getRooms() {
return rooms;
}
}

```
winnerczwx
2021-04-24 22:11:15 +08:00
同菜鸡

猜测一下面试官想考啥吧

我猜他想考的是 room 的权限设计, room owner 不仅仅可以开关门, 可能后期会加入踢人, 拉人等功能

如果把权限放在 user 里, 感觉就很乱, 一个 user 类 又要存用户信息, 又要存房间权限信息, 这不符合单一职责原则, 而且随着业务需求增加, 维护成本也将提高

所以我支持 room
crclz
2021-04-24 22:30:31 +08:00
开关门的细节显然应该涉及到 Room 更多一些。如果放在 User 类,那么 Room 类就会被迫暴露更多属性,Room 类的<封装性>会被破坏。

当然,如果加入设定“Room 类和 User 类涉及的东西一样多”,那么就应该考虑 DDD 中的 DomainService 设计。
csfreshman
2021-04-24 22:33:51 +08:00
@RedisMasterNode 看面经有个帖子,不清楚是哪个部门,哈哈
csfreshman
2021-04-24 22:37:14 +08:00
@winnerczwx 你这个回答后续踢人 拉人等功能,我觉得是加分项了,后面又扯到单一职责原则,非常巧妙了。
csfreshman
2021-04-24 22:39:24 +08:00
@psx2019 写的没太看明白,这里怎么控制的权限,user 类里只是有个返回 roomKeys 的方法,生成这个的地方在哪?
psx2019
2021-04-25 00:09:07 +08:00
@csfreshman Room 对象生成的时候自动生成的,在构造函数里面,构造生成后可以获取到 key 和 roomId 用来查找和开关门,无论是谁只要持有对的 key 就可以开门,room 本身应该只关注自身状态,也就是当前门是否开启:openStatus,改变状态的动作只有一个 openOrClose(),该动作会判断 key 是否正确来决定是否改变状态,也就是持有 key 的人就是“主人”,最后实现“主人”的这一概念绑定只需要将门的 id 和 key 分别放入 User 类的 roomkeys 和 Rooms 的 Map 容器内即可实现绑定。而主人是谁其实并不是 room 关心的,只需要自己在程序上保证 key 不会别泄露给别的人即可,
mingl0280
2021-04-25 01:45:15 +08:00
肯定 room 啊,怎么可能跟 user 有关联……
Rocketer
2021-04-25 02:00:27 +08:00
按现实中的做法,应该 Room 和 User 都有东西才对。Room 有个锁,而 User 有钥匙。

更确切地说应该是 Door 类里有个锁,这样锁就能通用了,将来踢人等其他操作也可以同样设计。

每次验证权限的时候就 Room.Door.Unlock(User),User 有对应的钥匙就返回 true,否则返回 false,这多方便。还能授权了(把钥匙给其他 User )
running17
2021-04-25 09:12:52 +08:00
资瓷 room 类,毕竟铁打的寺庙,流水的方丈[doge]
index90
2021-04-25 09:37:12 +08:00
room 类+1,tell don't ask
gaobing
2021-04-25 09:38:49 +08:00
单一职责原则。开门,关门是门的功能,不同的门也可能有不同的实现。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/772950

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX