3

我有一个与 Flash、actionscript 3 相关的 OOP 问题。这是一个个人项目,我正在寻找这个问题的设计模式或解决方法,我的目标是学习新事物。

我创建了一个名为 Chain 的类。我创建了这个 util-class 来简化延迟函数调用。您可以通过添加以毫秒为单位的延迟来创建一系列函数。这条链可以多次执行,甚至可以以相反的顺序执行。此类具有返回自身的函数。这使得拥有像这样的 jQuery 风格的语法成为可能:

var chain:Chain = new Chain(); 
chain.wait(100).add(myFunction1,300).wait(300).add(myFunction2,100);
// etc..

对于这个例子,我留下了很多函数只是为了演示这个问题。Chain 类主要用于添加功能和启动/停止链。

public class Chain 
{  
 function wait(delay:int = 0):Chain
 {
   // do stuff
   return this;
 }

 public function add(func:Function, delay:Number = 0):Chain
 {
      list.push( new ChainItem(func, delay) );
      return this;
 }
}

现在,我还有一个名为 ChainTween 的类。我正在尝试拆分事物以使 Chain 具有一些核心功能,并让 ChainTween 做一些动画技巧。我有创建一个基于 Chain 类的小补间引擎的想法。目前它扩展了Chain。它使用了 Chain 类中的许多受保护变量,并覆盖了 Chain 的一些核心函数,以在 Chain 进程中添加补间函数。

public class ChainTween extends Chain
{  
 function animate(properties:Object = null, duration:Number = 0, easing:Function = null):ChainTween
 {
   // do stuff
   return this;
 }
}

现在这就是问题所在:我想保留链接语法,但是 wait() 返回一个 Chain 实例并且 Chain 没有动画函数。

var chain:ChainTween = new ChainTween();
chain.wait(100).animate({x:200}, 100).wait(250);

我试图覆盖 ChainTween 类中的 wait() 和 add() 函数,但这会导致不兼容的覆盖。

我可以将chain.wait(100) 转换为ChainTween,但是当我链接很多它们时,这非常难看并且没有用。现在我不想将任何 ChainTween 函数添加到 Chain(也没有虚拟函数),并且我想保持所有函数的完成,因此返回 Object 也不是一个选项。我尝试使用接口,但这会产生同样的问题,因为接口的功能应该在实现它的类中实现。

现在我考虑在 ChainTween 中创建一个 Chain 的实例,但这不允许我覆盖函数,然后我应该将许多属性设为 public 而不是 protected,这也不是首选。

这可能吗?有人对此有很好的解决方案吗?

4

6 回答 6

2

这个问题很常见。您使用的设计模式称为Fluent Interface,如果您在 Google 上搜索“Fluent Interface Inheritance”,您会发现很多问题和很少的答案。

在 C#、Java 和 C++ 中解决此问题的常用方法是使用模板。但是,我不知道如何在 AS3 中实现相同的功能,我发现这个主题可能会对您有所帮助。

于 2010-12-17T15:02:30.697 回答
1

如果您希望函数通过代码完成列出,它必须在那里。这排除了任何运行时发现方法。我会在 Chain 中添加如下内容:

public function animate(args:Object, time:int):Chain {
    throw new Error("Animate is supported only on ChainTween");
}

在 ChainTween 中被覆盖。不要认为这是一个很大的延伸。

于 2010-12-17T10:28:00.030 回答
1

遵循 Chain 类的结构,应该可以(并且在某种程度上合乎逻辑)使用 add 方法调用 animate 方法......不了解 Chain 类的更多信息,很难更准确,但理论上它会似乎有可能......这需要向 add 方法添加一个新参数。

var chain:ChainTween = new ChainTween();
var params:Object = {x:200};
chain.wait(100).add(animate, 300 , params).wait(300);

alxx 有一点,似乎必须以某种方式给出一些东西,与 Javascript 不同,AS3 是一种强类型语言,这正是您的限制的原因。如果您需要实现诸如旋转、淡出等特定的方法,您可能没有很多可用的解决方案。这些方法将返回一个 ChainTween、一个 Chain 或一个 Object,并且您将同时关闭 Object 和 * ...

不知何故,我仍然认为使用 add() (或您可能为此目的创建的任何其他方法)添加 rotate、fadeOut 或 animate 方法更符合 Chain 的设计。

于 2010-12-17T13:33:12.193 回答
0

您可以尝试返回 * 而不是 Chain 但这会删除代码提示。

于 2010-12-17T10:56:43.707 回答
0

如果我是你,我会创建一个IChain只描述核心功能的界面(addwait

于 2010-12-17T11:29:54.347 回答
0

我会选择已经建议的界面想法。Wait 会返回类似 'IChainTween' 的东西,它只包含配置 ChainTween 的方法以及返回原始链的类似 'then' 的函数。

package
{
    public interface IChainTween
    {
        function doSomething():IChainTween;
        ...
        function then():IChain;
    }
}

package
{
    public class ChainTween implements IChainTween
    {
        private originalChain:IChain;
        public function ChainTween(IChain chain)
        {
            originalChain = chain;
        }
        ...
        public function doSomething():IChainTween
        {
            return this;
        }
        public function then():IChain
        {
            return originalChain;
        }
    }
}
于 2010-12-17T16:48:21.857 回答