【问题标题】:Refactoring objects with the same prototype properties重构具有相同原型属性的对象
【发布时间】:2016-09-19 01:08:47
【问题描述】:

假设我们有一个超类Character 和两个子类Player 和Enemy。

var Character = function(x, y){
    this.x = x || 0;
    this.y = y || 0;
};
var Enemy = function() {
    // randomInt returns an integer value in between 0 and 505 (canvas width)
    var x = randomInt(0, 505);
    var y = this.getNewRow();
    Character.call(this, x, y);
};
var Player = function(x, y, hearts) {
    Character.call(this, x, y);
    this.hearts = hearts;
};

Player 和 Enemy 都将具有原型属性,例如 width、height、leftMargin 和 topMargin。

Enemy.prototype.width = 96; 
Enemy.prototype.height = 65; 
Enemy.prototype.leftMargin = 2; 
Enemy.prototype.topMargin = 78; 

Player.prototype.width = 66; 
Player.prototype.height = 75;
Player.prototype.leftMargin = 18;
Player.prototype.topMargin = 64; 

由于 Player 和 Enemy 两个子类都有这 4 个属性(尽管值不同),我觉得这应该以某种方式重构,但是如何重构呢?由于这些类的每个实例都将具有相同的属性值,因此我确实想利用原型链并将它们保存在原型对象中(除非您可以向我解释为什么我不应该这样做)。

【问题讨论】:

  • 如果Player 和Enemy 共有这些属性,为什么不将它们添加到Character 类中?
  • 到目前为止,没有超类也没有子类,它们没有关系......
  • @Barmar,因为如果您只是将它们添加到 Character 类中,那么每个 player 和 enemy 实例都会将这些属性保存为本地值(这会占用内存)和我们不会利用原型链的力量
  • 您是说这些值对于所有Enemies 都相同吗?因此,您需要一种方法来表明 Character 的每个子类都具有这些类范围的属性,但它们是特定于子类的。
  • 一个简单的选项是function setSize(obj, w, h, l, t) { obj.prototype.width = w; /*etc*/ },然后是setSize(Enemy, 96, 65, 2, 78); setSize(Player, 66, 75, 18, 64);。

标签: javascript design-patterns prototype-chain prototype-pattern


【解决方案1】:

我不会做出这样的区分并完全依赖继承。 我更喜欢组合而不是继承,所以当发生变化时我不会被锁定在我的继承框中。在这种情况下还要考虑过早的过度工程,您是否真的期望通过将这些属性存储在对象本身中来解决性能问题? 我的设计是你有一个字符,它具有 x、y、hearts、width、height、leftMargin、topMargin、type 属性。因此,通过这种方式,您可以获得非常灵活的一致数据,可以满足您未来的需求:

  • 敌人可以通过改变类型来交朋友
  • 敌人在某个时间点也可以有心,为什么不应该?
  • 所有字符都可以通过改变宽度/高度来扩大/缩小
  • 所有字符都可以通过改变边距来改变位置。

基本上,您将拥有一个通用的数据结构来进行操作,而无需费力地维护您的层次模型。 希望这会对你有所帮助。

【讨论】:

  • 很好的建议和观点,我会研究作文(我从来没有听说过这个)。我之所以“过度设计”这个,是因为它是一个学习项目,而且我对设计模式非常感兴趣。
【解决方案2】:

这里没有可以应用的特殊设计模式。将这些属性放在各自的原型上很好,您甚至可能想在Character.prototype 上设置一些默认值。由于它们是实例的属性,应该由类的所有对象共享,因此原型正是放置它们的正确位置。

如果您想在分配时避免重复,只需将其放入函数中即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-02
    • 2018-02-17
    • 2014-01-05
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    相关资源
    最近更新 更多