2013-07-27 100 views
2

我有一个叫房类,包含所有的球员实体的属性之一的阵列,游戏服务器OOP设计

players = []; 

在客房类是只返回究竟是谁参赛球员的方法全面。

// below method is called by the room's timer 

var getPlayersWhoFinished = function() { 
    playersWhoFinished = []; 
    for (i = 0; i < players.length; i++) { 
     if (players[i].isFinished()) { 
      playersWhoFinished.push(players[i]); 
     }; 
    }; 
    return playersWhoFinished; 
} 

所以我知道我可以只留下上面在客房类作为是的,但我已经有更复杂的映射其他三个功能,在一个已经大类(300条+线)。 我不明白如何封装这些排序方法为其他类,因为它们是如此密切相关的房类,所有的客房参考发送中选取适当的用户。

修改上面的代码并将其插入到Player类中会对我有意义,但唯一可以考虑使用此方法的方法是使用静态方法并将空间对象发送给它。

// players is now a member of the Player class 

Player.getPlayersWhoFinished = function(room, players) { 
    playersWhoFinished = []; 
    for (i = 0; i < players; i++) { 
     if (players[i].getRoom() == room) { 
      playersWhoFinished.push(players[i]); 
     } 
    } 
    return playersWhoFinished; 
} 

无论如何,这对我来说似乎很麻烦和不合适。我一直在努力弄清楚如何让我的Room类尽可能轻松。

+1

它不会真正解决你的问题,但你可以在更短的方式以'filter'重新实现这样的过滤功能:'VAR playersWhoFinished = players.filter(功能(播放器){返回player.isFinished();} );' – icktoofay

+0

尖端,小心与那些未声明的'i'变量,因为它们是隐式的全局变量。 – elclanrs

+1

嗯....他们的方式,我会设计它room.getPlayersWhoFinished()将给所有玩家名单。当房间 –

回答

1

考虑分割成逻辑对象和集合。它类似于什么主干提供(模型,集合)。由于集合逻辑通常是特定于其包含的对象,但也具有一些共享功能(简单迭代,过滤器等),因此您可以创建泛型集合,然后通过继承添加更多方法以适应您的需求它存储的特定对象的需求。

所以,你将有你的房间:

function Room() { 
    // .. 
    this.players = new PlayerCollection(); 
    // .. 
} 

收集我已经添加了一些“奖金”的方法,所以它看起来像:

function Collection() { 
    this.list = [ ]; 
    this.length = 0; 
} 

// adds item 
Collection.prototype.add = function(item) { 
    this.list.push(item); 
    this.length = this.list.length; 
} 

// removes by index 
Collection.prototype.remove = function(index) { 
    this.list.splice(index, 1); 
    this.length = this.list.length; 
} 

// finds one item based on filter function, and triggers callback with item and index 
Collection.prototype.findOne = function(fn, callback) { 
    for(var i = 0, len = this.list.length; i < len; ++i) { 
    var result = fn(this.list[i]); 
    if (result) { 
     return callback(this.list[i], i); 
    } 
    } 
    return callback(null, -1); 
} 

// filters off 
Collection.prototype.filter = function(fn) { 
    return this.list.filter(fn); 
} 

那么就需要定义PlayerCollection,即将有额外的方法只是为了过滤掉已完成的玩家:

function PlayerCollection() { 
    Collection.call(this); 
} 
// some inheritance here 
PlayerCollection.prototype = Object.create(Collection.prototype); 
PlayerCollection.prototype.constructor = PlayerCollection; 

// returns list of finished players 
PlayerCollection.prototype.finished = function() { 
    return Collection.prototype.filter.call(this, function(player) { 
    return player.isFinished(); 
    }); 
} 

您仍然可以重复使用即filter方法,因为它有助于创建一些定制查询。

你的房间逻辑看起来像:

var room = new Room(); 
// add some players to room 
// ... 
var finishedPlayers = room.players.finished(); // what you need 

它看起来清晰和直接的,同时保持所有收集的逻辑从一个房间了,所以你可以简单地重复使用它在你的游戏代码。在一个地方改进 - 可以改善整体。

逻辑划分成这样的摘要,有助于扩大你的代码和独立的依赖关系。
请记住为filter浏览器支持,如果你需要-IE8,然后从here得到垫片。

+0

这正是我所期待的。你向我解释的这个概念将大大简化我的代码。我喜欢能够在任何我想要的地方使用它。 – user2372427

1

getPlayersWhoFinished()方法属于室,这是应该跟踪玩家的对象。您还正在执行中O(n)的复杂每次你需要找到最终的球员,这可以提高时间的搜索。

你可以有一个回调的意思是在每次称为一个玩家完成:

Player.prototype.onFinished = function() { 
    this.getRoom().addFinished(this); 
} 

然后管理室包含了所有的成品玩家的私人阵列:

function Room() { 
    this._finishedPlayers = []; 
} 

Room.prototype.addFinished = function(player) { 
    this._finishedPlayers.push(player); 
} 

Room.prototype.getPlayersWhoFinished = function() { 
    return this._finishedPlayers; 
} 

作为一个边注意,你应该总是用var声明变量,否则你会在全局范围内声明它们(通常是窗口对象)。