【问题标题】:Is there a design pattern for injecting methods into a class?是否有将方法注入类的设计模式?
【发布时间】:2011-02-01 23:13:04
【问题描述】:

我有一组可以协同工作的类(我正在用 javascript 编码)。

有一个父类和多个由父类实例化的子类。我有许多这些类的客户,每个客户都需要向父类或子类添加一个或多个方法。

我不是让每个客户端都从这些类继承(这可行但由于子类而变得混乱),而是让这些客户端在实例化主类时将函数传递给父类。

主类动态创建方法,客户端可以像一直在那里一样调用方法。

我的问题是:

  1. 这样做明智吗?
  2. 我正在做的事情的设计模式是什么?

【问题讨论】:

  • 4 年前在 Javascript 中使用类是很困难的。

标签: javascript oop design-patterns


【解决方案1】:

strategy pattern 适用于在运行时获得“策略”的情况。可能在这里适用。在这种情况下,策略是一个符合行为的类,即具有类似“执行”之类的方法。

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

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

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

【讨论】:

  • 嗯,策略是关于在运行时堆肥对象(将对象连接在一起)。装饰器是关于在运行时堆肥方法(向对象添加方法/功能)。相同的概念,但不同的层次。虽然 Strategy 在这种情况下可能会起作用(并且可能比正在做的更好),但 Strategy 在类级别起作用,而上述描述在方法级别起作用(因此将是装饰器)......
  • @ircmaxell,我从来不知道,但确实你是对的!我可以将其添加到我的答案中吗?
  • 绝对!如果你愿意,你也可以参考我的回答来编辑它(我要删除我的,因为无论如何你的覆盖得更好)......
  • 他所描述的战略模式,认真的吗?他描述的是访问者模式。顶多是装饰器……
【解决方案2】:

我必须承认模式不是我的“东西”——但你可以在 javascript 中做你想做的事。这就是所有框架如何完成“扩展”子“类”(javascript 中没有类)的那种事情。

如果你在纯javascript世界,你想使用:

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

所以你可以在任何foo 上调用bar,而bar 只在内存中存在一次——即通过每个foo 对象在内存中引用相同的函数。因此,请注意您可能在该范围之外引用的任何变量。

每个库都有自己的插件架构来完成大致相同的目标(并且他们负责原型中的一些混乱/危险)

【讨论】:

    【解决方案3】:

    您应该提供一些代码,以便我们了解究竟您在说什么。

    你没有:我只能猜测你没有使用原型。原型将是“面向对象”JavaScript 的“正确”设计模式。

    当您在 JavaScript 中将函数/属性/任何内容添加到对象的原型时,所有实例,无论新旧都会收到其原型上的函数/属性/任何内容。

    在 JavaScript 中扩展原型非常简单,绝不应该变得混乱。如果是这样,则可能意味着您过于复杂了。

    【讨论】:

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

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

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

    例如

    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.'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2017-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-08
      • 1970-01-01
      相关资源
      最近更新 更多