AS3:从外部列表中在注册表中创建静态变量

时间:2014-04-23 00:32:49

标签: actionscript-3 static-variables

我有一个将使用大量资产的应用程序。为了更好地处理,我选择使用注册表来保存所有资产,以便可以在整个应用程序中访问它们:

package  
{
    public class SpriteRegistry 
    {
        public static var SPRITENAME = "link to image file";    

        public function SpriteRegistry() 
        {

        }

    }

}

我想要做的是创建一个XML文档并列出文件名和链接,以便在应用程序启动时,此注册表创建可从该列表中自由访问的变量,而无需直接对任何内容进行硬编码进入它。

具体来说,我需要知道的是如何获得"公共静态"效果或如何获得我可以动态生成的变量的等效效果。

更多信息:

我正在使用一个函数,它根据名为mouseAttribute的字符串变量将精灵纹理加载到精灵对象中:

loadGraphic(SpriteRegistry[currentAttribute+"Texture"]);

基本上它就像一个绘画程序,但对于视频游戏的关卡编辑器。

问题在于我最终将有100多个精灵需要应用程序才能加载,然后我需要loadGraphic函数仍然能够有效地指向目标精灵。

我使用的库也需要我将源嵌入到类中,然后才能将它拉入sprite对象:

[Embed(source = "/Images/GridTile.png")]
public static var gridTileTexture:Class;

我试图避免使用数组的原因是因为这意味着每次单击编辑器上的单个网格时,我必须搜索100多个对象的数组才能找到一个精灵。那将是突如其来的。

2 个答案:

答案 0 :(得分:1)

这非常简单 - 只需使用静态函数,它将返回XML。因此,您需要以某种方式加载XML文件(您决定在哪里,但您的注册表类应该引用它)。类似的东西:

private static var _xml:XML;

public static function initialize(xml:XML):void {
    _xml = xml;
}

public static function getXML():XML {
    return _xml;
}

所以你会像那样使用它:

SpriteRegistry.initialize(loadedXML); // done only once when you initialize your app
trace(SpriteRegistry.getXML().someValue); // someValue is directly from the XML

它是一种常用的策略,大多数时候你会有类似app初始化程序的东西 - 加载和实例化所有东西,然后将它们传递给一些注册表,这些注册表可以保存它们以便更快地和全局使用。

修改: 在阅读了你的进一步评论之后,我看不出任何重大变化 - 这个决议一切都会好的。 如果您担心需要搜索数组' - 把它作为一个对象!通过这种方式,您可以使用与您指向的完全相同的密钥直接访问正确的密钥:

private static var _registry:Object;

public static function initialize(xml:XML):void {
    // loop through xml and insert items
    _registry[key] = resource;
}

public static function getResource(id):Object {
    return _registry[id];
}

这样你就可以使用它:

SpriteRegistry.getResource(currentAttribute+"Texture");

答案 1 :(得分:1)

我个人认为,你应尽可能避免使用静力学。相反,您应该只创建一个实例,并在需要时通过依赖注入提供它。

如果你采用这种方法,你可以做类似的事情:

public function getSprite(spriteName:String):Class{
    return this[spriteName];
}

public function getSprite(spriteName:String):Class{
    return yourDictionaryOrObject[spriteName];//I'd implement it this way
}

否则你可以选择:

public static function getSprite(spriteName):Class{
    return ThisHonkingBigUnnchangeableClassname[spriteName];
}

所做的是在仅限静态的类中创建一个词典,因为你几乎不可避免地会遇到global mutable state

根据要求进行讨论

为什么要创建实例并传递它,而不是硬编码对特定类的引用?上面的全局可变状态链接涵盖了很多答案,但这里有一些特定于这类问题:

  • 灵活性。假设您构建所有内容的想法是您只有一组资源并行使用,那么您发现需要多个资源 - 例如,您可能需要一个用于色盲用户,或多种语言,或缩略图vs全尺寸的。如果你硬编码为静态,那么你必须进入每个硬编码的地方并进行某种改变以使用不同的设置,而如果你使用DI,你只需提供一个不同的实例加载不同的资源,并完成。

  • 可测试性。这实际上在链接中有所涉及,但我认为它可以解决。如果你想对需要资源的东西进行快速测试,你必须拥有那个静态的“东西”并且你不能改变任何关于它的东西。然后很难知道你实际测试的东西是否正常工作,或者它是否只是根据当前实施的“东西”而起作用。

  • 资源使用:从swf加载到卸载时,所有关于全静态类的内容都存在。实例仅存在于实例化它们直到它们被垃圾收集时。对于包含嵌入资源的资源文件,这尤其重要。

我认为Frameworks的重要一点是要了解它们的工作原理。 ActionScript中使用的主要工作方式相同,即它们有一个中央事件调度程序(事件总线),任何加载到框架的东西都可以通过请求注入它来声明对它的兴趣来获得引用。此外,他们观看了一个事件的阶段,该事件表明添加了某些内容(在RL中它是ADDED_TO_STAGE,而在Mate中它是Flex事件CREATION_COMPLETE)。一旦你理解了这些原则,你就可以用一只非常轻松的手自己应用它们,而不需要随框架附带的所有内容。

<强> TL; DR

我通常会尽量避免回答未提出的问题,但在这种情况下,我认为讨论这个问题的完全不同的方法会有所帮助。从根本上说,解决方案不是注入整个资源实例,而只是注入所需的资源。

我不知道OP的代码是什么样的,但是这个解决方案应该足够通用,它可以将命名BitmapData传递给实现我们的接口的任何东西,它能够调度任何{{{ 1}}我们设置为IEventDispatcher(这可能是为此目的而创建的舞台,特定eventBusDisplayObject

请注意,此代码与我在生产中的代码非常相似;)。

EventDispatcher

请注意,我没有提供界面或自定义事件或界面的示例实现,因为我正在午餐休息时间,但如果有人需要了解代码,请回复,我会填写。