【问题标题】:Class hierarchy: Is there a cleaner pattern for this?类层次结构:是否有更清晰的模式?
【发布时间】:2015-07-26 18:12:18
【问题描述】:

我在 ES2015 中写这个,但是这个问题也可以带到其他语言。

在我的情况下,我有一个这样的 Chat 类:

// Chat.js
import { socket, config } from "./Util.js";
import User from "./User.js";
class Chat {
    constructor(socket, config) {
        // …
    }
    roomExists(room) {
        // …
    }
    createRoom(room) {
        // …
    }
}
// Make sure to export the same instance to every other module,
// as we only need one chat (resembling a singleton pattern)
export default new Chat(socket, config);

现在,这个类在createRoom() 的某个地方使用了User。问题是User 类需要使用我们导出的Chat 实例:

// User.js
import chat from "./Chat.js";
export default class User {
     join(room) {
         if (chat.roomExists(room)) {
             // …
         }
     }
}

但是现在我们在Chat.jsUser.js 之间有了一个依赖循环。该脚本不会运行。解决此问题的一种方法是永远不要直接导入 Chat.js,而是执行以下操作:

// Chat.js
import { socket, config } from "./Util.js";
import User from "./User.js";
class Chat {
    constructor(socket, config) {
        // Pass `this` as a reference so that we can use
        // this chat instance from within each user
        this.userReference = new User(this);
    }
    roomExists(room) {
    }
    createRoom(room) {
    }
}
// No need to export a singleton anymore, as we pass the
// reference to the chat in the User constructor

但现在,所有其他类都依赖于Chat,并且必须在我们实例化聊天实例后为其提供一个引用。这也不干净,是吗? Chat 现在是单点故障,以后很难交换。

有没有更简洁的管理方式?

【问题讨论】:

  • 为什么join(可能应该是joinRoom以避免与数组方法join混淆)是User而不是Chat的方法? Chat 似乎可以管理房间的方方面面。
  • @JasonCust 因为语义上,Users 应该 join 一个房间,但 Chats 不应该加入任何东西。 Chat 管理 createRoom,因为一些房间是由 Chat(默认房间)创建的。稍后在User 中还将有一个createRoom 方法来启用用户制作的房间。
  • 这个“class singleton”是definitively an antipattern。不要这样做。创建一个对象字面量。
  • @Chiru:您确实应该将用户加入的房间或聊天(房间)或用户在其中创建新房间的聊天作为参数传递给这些方法。不要将 Chats 设为单例。如果您的应用程序只需要一个 Chat,请在您的 App main 中创建一个实例。这正是单例反模式。
  • 我同意,@Bergi,谢谢。我现在使用了对象字面量。

标签: javascript oop design-patterns ecmascript-6


【解决方案1】:

更新

显然 User 不应该有 Chat 。所以,聊天应该是这样的

class Chat{
   //other declarations

  addUser(user,room) {}

  createSpecificRoom(user,name){}

  moveUserToRoom(user,newRoom) {}
}

如果你想从用户对象做事,我们可以使用双重调度。

class User{
  joinChat(chat,room){
      chat.addUser(this,room);
  }
}

var chat=new Chat();
var user= new User();
user.joinChat(chat,room);

但是,IMO 最好的办法是仅使用 Chat 来添加/删除用户。从语义上讲,它的工作是跟踪房间和用户。关于单例,如果您使用支持 DI 的框架,几乎所有服务都是单例,但您不应该关心这一点。只需在您需要的任何地方注入 Chat

【讨论】:

    猜你喜欢
    • 2019-02-17
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-27
    • 2011-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多