类层次结构:这有更清晰的模式吗?

时间:2015-07-26 18:12:19

标签: javascript oop design-patterns ecmascript-6

我在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);

现在,这个类在User中的某个地方使用了createRoom()。问题是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现在是单点故障,以后很难交换。

有更简洁的方法来管理吗?

1 个答案:

答案 0 :(得分: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