是否有一种设计模式可以向类中注入方法?

3

我有一组相互协作的类(使用javascript编码)。

其中有一个父类和多个子类,由父类实例化。我有许多客户端需要向父或子类添加一个或多个方法。

为了避免每个客户端都继承这些类,因为子类的存在使得继承变得麻烦,我让这些客户端在实例化主类时将函数传递给父类。

主类会动态地创建方法,客户端可以像一直存在一样调用这些方法。

我的问题是:

  1. 这么做明智吗?
  2. 我正在做什么设计模式?

4年前在JavaScript中使用类是很困难的。 - nbro
4个回答

3

策略模式适用于需要在运行时获取“策略”的情况。在这种情况下,策略是符合某种行为的类,即具有像“执行”或其他方法。

装饰者模式也可能适用。它也是一种运行时模式,但在方法级别上增强了它所装饰的类。

因此,如果您动态选择类,则策略模式很好,如果您只在运行时更改方法实现,则装饰者模式很好。

(我在得到ircmaxell的许可后引用了这个答案的装饰器部分)


策略模式是在运行时将对象组合在一起(连接对象)。装饰器模式是在运行时将方法组合在一起(向对象添加方法/功能)。这是相同的概念,但不同的层次。虽然策略模式在这种情况下可能有效(并且可能比当前做法更好),但策略模式是在类级别上工作,而上述描述是在方法级别上工作(因此应该是一个装饰器)。 - ircmaxell
@ircmaxell,我不知道这一点,但你是正确的!我能把它加到我的答案里吗? - hvgotcodes
当然可以!如果您愿意,您可以参考我的答案进行编辑(我将删除我的答案,因为您的覆盖得更好)... - ircmaxell
他在描述策略模式,真的吗?他所描述的是访问者模式。最多只能算装饰器模式... - nbro

2

我必须承认模式并不是我的“强项”,但在JavaScript中你可以做任何你想做的事情。这就是所有框架实现这种“扩展”子“类”的方式(JavaScript 中没有类)。

如果你处于纯 JavaScript 的世界,你需要使用:

foo.prototype.bar = function() {};

所以您可以在任何foo上调用bar,并且bar仅存在于内存中一次 - 也就是说,同一个函数通过每个foo对象在内存中引用。因此,请注意您可能在该范围之外引用的任何变量。
每个库都有自己的插件架构来实现大致相同的目标(它们处理原型中的一些混乱/危险)。

0
正如所说,您正在描述策略模式,您为特定情况执行此操作的方式不是使用原型(从而影响类的所有对象)。

相反,您将提供一个接受函数作为其值的成员。

例如:

function MyClass() {
    this.myFunction = defaultFunction;

    this.defaultFunction = function() {
       // do something by default.
       alert("using default");
    }

    this.doFunction = function() {
       // something that calls myFunction.
       this.myFunction();
    }
}

---8< snip --------

// later on...

t = new MyClass();
t.doFunction(); // output 'using default'
t.myFunction = function(){ 
   // do something specific with this instance, when myFunction is called. 
   alert("customized for this instance.");
}
t.doFunction(); // output 'customized for this instance.'

0

你应该提供一些代码,这样我们才能更好地了解你在谈论什么。

由于你没有提供代码,我只能猜测你没有使用原型。原型是“面向对象”JavaScript的“正确”设计模式。

当你将一个函数/属性/任何东西添加到JavaScript对象的原型中时,所有实例,新的和旧的都会在它们的原型上接收到该函数/属性/任何东西。

在JavaScript中扩展原型非常简单,不应该变得混乱。如果出现混乱,那可能意味着你过于复杂化了它。


我正在使用原型。我没有将这些特定于客户端的方法添加到原型中,因为有大量的客户端,每个客户端都有自己需要添加的一两个方法,并且不需要被其他客户端看到。此外,我希望允许未知的客户端(即使用我的库的人)注入他们自己的函数。 - glenn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接