2012-11-16 44 views
0

我目前正试图找到一个“确定性”解决方案(意思是:找到一个似乎符合OOP戒律的高效解决方案),以解决我一直遇到的一个反复出现的问题时间:我的代码的不同部分共享数据的问题。在应用程序的模型和视图之间共享数据

请注意,我是而不是在任何地方使用任何MVC框架。我只是将我的数据类引用为模型,将显示类引用为视图(因为它的专有名称与MVC模式无关,所以人们在MVC模式“创建”之前就提供了模型方式, )。

这是我的问题: 每当我做一个使用一些相当扩展的数据(例如游戏)的应用程序时,我会尝试分离逻辑(移动,碰撞等...)并显示在两个类中。但是,后来我偶然发现了这个问题:如何将存储在我的逻辑类中的数据与视图类中相应的显示对象“绑定”,而不会在不同类之间重复数据,引用或其他事物?

让我们一个基本的例子:

  • 我有一个MyLogicClass,抱着“EntityData”对象组成的矢量(每个位置,大小,各种状态,一切以处理我的项目的逻辑)

  • 而且我有一个MyViewClass,为MyLogicClass中的每个EntityData创建并显示Sprites,并在它们在游戏循环中更新后移动它们。

这是要我的脑海里的第一件事将是存储每个数据元素及其对应的视图中,从而让我循环throught我矢量更新项目的逻辑,然后更新相应的意见。但是这迫使我在MyViewClass中持有一个MyLogicClass引用,以确保我可以锁定实体数据,迫使我将两个类(我不想做的事情)耦合起来。另一方面,在我的数据模型(具有ID参数的MyLogicClass的EntityData对象)和我的View类(Sprites持有对其原始实体数据ID的引用)中都存在每个实体具有ID的解决方案, 。但是当我想要定位一个特定的实体,迫使我在我的数据模型中进行循环时,再循环它以在我的View中查找相关的Sprite。这个解决方案允许我在我的数据和我的视图之间有松散的耦合,但是每帧两次循环遍历数百个元素(可能发生!)实际上听起来没有为我优化性能。

我可能会将整个问题给予应有的重视,但我一直在不止一次地磕磕绊绊,而且我还希望能有比我更多的观点。

你们对这个问题有什么建议/解决方案吗?

有没有其他的数据格式/层次结构,我可能不知道这种情况?

回答

0

我想也许你已经想过这个问题了。我有时会这样做。

您的视图类显然有一些到模型的链接,事件是一个很好的方法来做到这一点。这里有一些裸露的骨头给你一个想法。

// Model class 
package 
{ 
    class MyModel extends EventDispatcher 
    { 
     // you can make them public but that would 
     // be against some oop practices. so private it is 
     private var m_position:Vector2D; 

     MyModel(){} 

     // one way of doing getters/getters 
     // example: theModel.SetPosition(something); 
     public function GetPosition():Vector2D { return m_position; } 
     public function SetPosition(value:Vector2D):void 
     { 
      m_position = value; 
      ModelChanged(); 
     } 

     // the other way 
     // sample: theModel.position = something; 
     public function get position():Vector2D {return m_position; } 
     public function set position(value:Vector2D):void 
     { 
      m_position = value; 
      ModelChanged(); 
     } 

     private function ModelChanged():void 
     { 
      dispatchEvent(new Event(Event.CHANGE)); 
     } 
    } 
} 


// now for our view. 
package 
{ 
    class MyView extends Sprite // or whatever 
    { 
     private var model:MyModel; 

     MyView(model:MyModel) 
     { 
      this.model = model; 

      model.addEventListener(Event.CHANGE, handleModelChanged); 

      // fire off an event to set the initial position. 
      handleModelChanged(NULL); 
     } 

     private function handleModelChanged(evt:Event):void 
     { 
      x = model.position.x; 
      y = model.position.y; 
      // etc etc etc. 
     } 
    } 
} 

总之,如果你要在模型文件中的逻辑也是显而易见的,如果没有模型的外面需要改变它没有理由制定者,你不需要制定者。但你确实需要获得者。

这将模型从视图中分离出来,您可以以任何您想要的方式编写任何视图,并且您需要提供的所有内容都是模型更改时的处理程序。只要将您的视图需要的任何数据暴露给getter即可。

您现在只需循环遍历模型,如果更改它将触发一个事件,并且正在侦听的视图将更新。

希望我没有错过任何东西,这解释了你想要的。

编辑:我忘了添加,如果你使用更新函数的话,你不必在所有地方都有“ModelChanged()”。只需更新,并在完成时关闭事件。

+0

感谢您的答案,但并没有解决我的问题。在这里您可以在模型发生变化时发送事件,但您如何定位发生变化的元素?我不想更新我所有的物品,因为只有1个物品发生了变化,所以问题仍然存在...(仍然需要我的Sprites或物品数据相互注册,或者使用ID并在模型中循环两次查看) – elFlashor

+0

它只需要一个循环。你循环模型并运行你想要的任何逻辑,并且“如果”它们由于某种原因而改变,那么它们会发出一条消息,告诉视图更新。如果他们不改变,那么他们不必更新。没有理由在模型和视图上运行循环,只有在需要时才会作出反应。该视图只是同步数据。如果你对同一个模型有10个不同的视图(比如正常游戏区域和小地图),那么他们都会在模型中注册一个更改事件,并且只有在模型更改时才会更新。 – Feltope

+0

该视图不与作为重点的模型进行通信。让它们完全分离,这样你就可以创建任何你想要的下划线模型的“视图”。 – Feltope

1

我所做的是使用事件和事件监听器将它们“链接”在一起。我有我的“模型部分”抛出“显示部分”捕获和渲染/更新的特定事件。

我发现这让我通过编写测试代码来构造一些测试,测试代码可以监听特定的事件并以此方式进行错误检查。我的代码仍然是独立可测的:我可以通过触发来测试我的“模型”,并确保正确的值被引发。同样明智的是,我可以编写一些测试代码来抛出可以被“显示”捕获的预设事件,以查看它是否有任何问题。

然后,一旦所有的工作,我只是重用这些相同的事件侦听器,并链接到'彼此'。

后来我的“控制器”(用户输入)会操纵“模型”部分,这会导致事件被抛出到“显示器”,从而被渲染/更新。

我不知道这是“正确的”,还是不遵循mvc模式,也没有关于这些事情的任何正式知识。我也会对别人更有见地的看法感兴趣。

+0

感谢您的回答:-),但我正在寻找更深入的答案,关于如何处理应用程序的各方之间的信息共享或通信... – elFlashor

相关问题