JavaScript 中的模板方法

发布于 2024-09-26 20:25:30 字数 327 浏览 5 评论 0原文

我想在 javascript 中实现模板方法模式。

我有一个 PropertyDecorator 和一些子类:OpenButtonDecorator、SeeButtonDecorator 等。我想在属性装饰器中具有下一个功能:

var build = function(){
   decorate(); //Abstract in PropertyDecorator, defined in subclasses
   return le.build();
}

如何让这个场景工作?也许我实现了错误的继承:S(也有帮助:))

提前谢谢你。

I want, in javascript, to implement the template method pattern.

I have a PropertyDecorator with some subclasses: OpenButtonDecorator, SeeButtonDecorator and so on. I want to have in Property decorator the next function:

var build = function(){
   decorate(); //Abstract in PropertyDecorator, defined in subclasses
   return le.build();
}

How can I get this scenario working? Maybe I implemented wrong the inheritance :S (help with that too :) )

Thank you in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

尴尬癌患者 2024-10-03 20:25:30

Javascript 是一种动态类型、基于原型的语言。模板方法是一种设计模式,因此与语言无关,但其实现可能因语言而异。

对于 javascript 以及其他动态类型语言(如 ruby​​),抽象类和接口没有多大意义,因为动态链接是通过委托发生的。 (方法调用被传播到继承树中的更高级别,直到原型可以处理请求)。这与鸭子类型结合在一起,这意味着可以在任何实例上调用任何方法,避免了显式契约的需要,在基于类的语言中,显式契约是由在特定类型上可见的那些声明的方法定义的。

因此,为了实现该模式,只需在父类的原型构建方法上调用一个不存在的方法(该方法将是模板),然后在子类上简单地实现该方法:

function PropertyDecorator()
{
   this.build = function()
   {
      var decoration=this.decorate();
      return "The decoration I did: "+decoration;
   };
}

//we set the parent (those prototype that instances of this class will delegate calls to) 
OpenButtonDecorator.prototype = new PropertyDecorator();
function OpenButtonDecorator()
{
   this.decorate = function()
   {
     return "open button";
   };
}


SeeButtonDecorator.prototype = new PropertyDecorator();
function SeeButtonDecorator()
{
   this.decorate = function()
   {
      return "see button";
   };
}



var decorators=Array(new SeeButtonDecorator(),new OpenButtonDecorator());
for (var decorator in decorators){
    document.writeln(decorators[decorator].build());
}

方法调度以这种方式发生:

  • 实例是否调用了该方法?
    • 否 ->将调用委托给父级(它的原型)并重复。
    • 是->在隐式对象(一开始接收调用的对象)的上下文中执行方法体。

因此,当调用 new SeeButtonDecorator().build() 时,它首先会尝试在实例上执行 build 方法。由于它没有在实例中定义,因此方法调用将委托给实例父实例,在本例中,SeeButtonDecorator 原型(这个)也没有获得该方法,因此它将调用委托给其父实例(PropertyDecorator)。 PropertyDecorator,具有 build() 方法。

function PropertyDecorator()
{
   this.build = function()
   {
      var decoration=this.decorate();
      return "The decoration I did: "+decoration;
   };
}

执行时,build 方法的主体将在新的 SeeButtonDecorator() 的上下文中进行评估。实例本身没有 decorate() 方法,因为它是在 SeeButtonDecorator() 函数(其原型)中定义的。好吧,这次调用将被委托给实例原型,最终将得到一个decorate()方法:

function SeeButtonDecorator()
{
   this.decorate = function()
   {
      return "see button";
   };
}

该方法将再次在实例的上下文中执行,并返回字符串,回退到调用堆栈中,直到返回

The decoration I did: see button

Javascript is a dynamic typed, prototype-based language. Template method is a design pattern and hence language independent, but its implementation can vary across languages.

In the case of javascript, and also in other dynamically typed languages, like ruby, abstract classes and interfaces doesn't make much sense, since dynamic linking occurs via delegation. (A method call is propagated to higher levels in the inheritance tree until a prototype can handle the request). This, in conjunction with duck-typing, which means that any method can be potentially called on any instance, avoids the need of an explicit contract, which in class-based languages is defined by those declared methods that are visible on a certain Type.

So in order to implement the pattern, just call an inexistent method on the parent's prototype build method (that method will be the template) and simply implement that method on the sublcasses:

function PropertyDecorator()
{
   this.build = function()
   {
      var decoration=this.decorate();
      return "The decoration I did: "+decoration;
   };
}

//we set the parent (those prototype that instances of this class will delegate calls to) 
OpenButtonDecorator.prototype = new PropertyDecorator();
function OpenButtonDecorator()
{
   this.decorate = function()
   {
     return "open button";
   };
}


SeeButtonDecorator.prototype = new PropertyDecorator();
function SeeButtonDecorator()
{
   this.decorate = function()
   {
      return "see button";
   };
}



var decorators=Array(new SeeButtonDecorator(),new OpenButtonDecorator());
for (var decorator in decorators){
    document.writeln(decorators[decorator].build());
}

A method dispatch occurs this way:

  • Does the instance have the method invoked?
    • No -> Delegate call to the parent (it's prototype) and repeat.
    • Yes-> Execute method body in the context of the implicit object (the one that received the call in the beginning).

So, when calling new SeeButtonDecorator().build(), first, it will try to execute build method on the instance. As it's not defined in the instance, method invocation will be delegated to the instance parent, which in this case SeeButtonDecorator prototype, this one, hasn't got the method neither, so it will delegate the call to it's parent (PropertyDecorator). PropertyDecorator, has the build() method.

function PropertyDecorator()
{
   this.build = function()
   {
      var decoration=this.decorate();
      return "The decoration I did: "+decoration;
   };
}

When executing it, build method's body will be evaluated in the context of the new SeeButtonDecorator(). The instance itself won't have a decorate() method, as it's defined in SeeButtonDecorator() function (its prototype). Well, this time the call will be delegated to the instance prototype, wich will finally got a decorate() method:

function SeeButtonDecorator()
{
   this.decorate = function()
   {
      return "see button";
   };
}

The method will be executed in the context of the instance again, and will return the string, falling back in the call stack until returning

The decoration I did: see button
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文