from cliff
Multiplicity
You might go with multiple instances of the same VideoPlayerMediator. The idiom of using a constant for the Mediator name won't work though, and you'll have to dynamically give the Mediator a name. Dynamically-named Mediators can best take their name by appending 'Mediator' to their View Component's instance name. The Rather than having a constant NAME, the Mediator would have a private name variable, which it sets at construction time based upon its View Component's id. Then in getMediatorName, we return this property. (Multiplicity in Mediators will be covered in the upcoming courseware).
Uber-component/Mediator
Make the tile component that holds the multiple video components be a custom component that passes events from its children to its Mediator. The Mediator for the tile component knows about how to deal with the video components it contains.
The first one is probably the best option since it would be more reusable.
-=Cliff>
Showing posts with label puremvc. Show all posts
Showing posts with label puremvc. Show all posts
Thursday, August 2, 2007
puremvc proxyFactory to manage many proxies
from cliff
Good point, Carl.
Most times, your Proxies will only have one instance created, though we won't go to the trouble to make them Singletons. So having a NAME constant to register and retrieve the Proxy with makes sense most of the time.
But lets imagine you have a particle system, where a Proxy is responsible for holding a single particle and you have thousands of particles. The ParticleProxy holds the physics implementation; the math for affecting the particle state. Its Data Object is a ParticleVO that holds the properties for a single particle.
You probably have a ParticleFactoryProxy that dynamically creates and registers these ParticleProxies, giving them unique names and properties at creation time.
The only thing that changes since we have multiple instances registered is the fact that we can't predetermine the name assign it to a constant and refer to with a singular idiom.
The ParticleFactoryProxy will only have a single instance created, so to retrieve it:
Quote
var facade:ApplicationFacade = ApplicationFacade.getInstance();
var pfProxy:ParticleFactoryProxy = facade.retrieveProxy(ParticleFactoryProxy.NAME) as ParticleFactoryProxy;
However since we have more than one instance of ParticleProxy, we'll have to have a different way of getting the name of the one we want. We'll probably have the ParticleFactoryProxy keep a list of all the names of the particles it has generated. Then to access them, perhaps from a command, we might do something like this:
Quote
var particleNames:Array = pfProxy.getParticleNames();
for (var k:int = 0; k< particleNames.length; k++) {
var particleProxy:ParticleProxy = facade.retrieveProxy(particleNames[k]) as ParticleProxy;
particleProxy.updateVector();
}
Good point, Carl.
Most times, your Proxies will only have one instance created, though we won't go to the trouble to make them Singletons. So having a NAME constant to register and retrieve the Proxy with makes sense most of the time.
But lets imagine you have a particle system, where a Proxy is responsible for holding a single particle and you have thousands of particles. The ParticleProxy holds the physics implementation; the math for affecting the particle state. Its Data Object is a ParticleVO that holds the properties for a single particle.
You probably have a ParticleFactoryProxy that dynamically creates and registers these ParticleProxies, giving them unique names and properties at creation time.
The only thing that changes since we have multiple instances registered is the fact that we can't predetermine the name assign it to a constant and refer to with a singular idiom.
The ParticleFactoryProxy will only have a single instance created, so to retrieve it:
Quote
var facade:ApplicationFacade = ApplicationFacade.getInstance();
var pfProxy:ParticleFactoryProxy = facade.retrieveProxy(ParticleFactoryProxy.NAME) as ParticleFactoryProxy;
However since we have more than one instance of ParticleProxy, we'll have to have a different way of getting the name of the one we want. We'll probably have the ParticleFactoryProxy keep a list of all the names of the particles it has generated. Then to access them, perhaps from a command, we might do something like this:
Quote
var particleNames:Array = pfProxy.getParticleNames();
for (var k:int = 0; k< particleNames.length; k++) {
var particleProxy:ParticleProxy = facade.retrieveProxy(particleNames[k]) as ParticleProxy;
particleProxy.updateVector();
}
puremvc Model Locator pattern in PureMVC
from cliff
In the sense that the Model/ModelLocator is like a Christmas tree and we adorn it with all our cheery holiday data objects, yes the PureMVC Model is similar to the ModelLocator.
However it differs quite a bit in terms of how we actually access to the data.
In Cairngorm, typically you:
* Define the ModelLocator class as a Singleton.
* Add properties to it.
* Fetch the ModelLocator Singleton at various places in the View by calling its getInstance method.
* Bind to its properties.
Binding is something else that is very Flex/Flash-centric that was verboten to rely upon for the PureMVC implementation. In an environment that doesn't have the Flex and Flash classes, events and binding can't be counted upon being there there for you. At least not with the Flash/Flex implementations. (Think Mozilla Tamarin, or even J2ME, or maybe curl).
In PureMVC, you:
* Define proxies to hold the data
* Register them with the Model, typically via the Facade
* Retrieve the Proxies elsewhere with Commands or Mediators
* Set the data on the View Components with Mediators
Of course there's nothing to stop you from fetching the Proxies inside your View Components, and binding to their data. But that makes the View Components less portable since they now have this inherent PureMVC stuff in them.
Look at the Architecture 101 demos. All custom components have no knowledge of the PureMVC system or where their data comes from at all. This means you could carry them away and make a Cairngorm demo around them without having to remove any PureMVC framework stuff at all. Instead they expose an API to that their Mediators use to communicate with them, using public properties and Events. Internally they use binding all they wish to move data around and change their behavior based on the current data in the controls.
This is the path to reusability in View Components.
In the sense that the Model/ModelLocator is like a Christmas tree and we adorn it with all our cheery holiday data objects, yes the PureMVC Model is similar to the ModelLocator.
However it differs quite a bit in terms of how we actually access to the data.
In Cairngorm, typically you:
* Define the ModelLocator class as a Singleton.
* Add properties to it.
* Fetch the ModelLocator Singleton at various places in the View by calling its getInstance method.
* Bind to its properties.
Binding is something else that is very Flex/Flash-centric that was verboten to rely upon for the PureMVC implementation. In an environment that doesn't have the Flex and Flash classes, events and binding can't be counted upon being there there for you. At least not with the Flash/Flex implementations. (Think Mozilla Tamarin, or even J2ME, or maybe curl).
In PureMVC, you:
* Define proxies to hold the data
* Register them with the Model, typically via the Facade
* Retrieve the Proxies elsewhere with Commands or Mediators
* Set the data on the View Components with Mediators
Of course there's nothing to stop you from fetching the Proxies inside your View Components, and binding to their data. But that makes the View Components less portable since they now have this inherent PureMVC stuff in them.
Look at the Architecture 101 demos. All custom components have no knowledge of the PureMVC system or where their data comes from at all. This means you could carry them away and make a Cairngorm demo around them without having to remove any PureMVC framework stuff at all. Instead they expose an API to that their Mediators use to communicate with them, using public properties and Events. Internally they use binding all they wish to move data around and change their behavior based on the current data in the controls.
This is the path to reusability in View Components.
puremvc Mediator notification handling
from Cliff
Mediators should play a fairly simple and mechanical role in the architecture:
* Receive Event information from their View Components, gather information from the View Component and/or custom Event and send it off in a Notification.
* Receive Notifications, extract the data mostly from the Notification, and update the View Component.
Similar to a switchboard operator. Who are you calling, sir? Ok, I'll route you through.
Although you can do most anything in a Mediator, limiting it to this role and pushing more complicated stuff, (the sort of stuff you might actually want to reuse) into a Command is a better idea. This keeps the Mediator simple and lightweight, doing only the minimum work necessary to adapt the View Component to the system.
For guidance about the Mediator's role, examine the three Mediators of the Architecture 101 demo, and how they adhere to this simple ambition. Note that a more complicated activity such as deleting a User (and their associated Roles) are done in a Command.
Because they are special case adapters for custom View Components, it is not expected that Mediators will be the most reusable aspect of a system. Due to the relatively simple role Mediators play, I sought the simplest way of 'plugging' them into the system.
But of course this doesn't change the way you feel about the particular implementation. This is why I did my best to make PureMVC a system where you could take or leave as much as you want. If you're down with the out of box way of doing things, great. If not, there are plenty of ways to customize it to your like.
So as to how you might override this Mediator Notification behavior:
When the the View class's registerMediator method is called, it interrogates the Mediator for a list of Notification interests, by calling its listNotificationInterests method. The View maps each Notification name returned to an Observer object that points the Mediator instance and a predetermined callback method - handleNotification.
Examine the View.registerMediator method to see how this happens.
Inside View.registerMediator, when an Observer object is created, it is registered with the View's Observer Map through a call to the public method registerObserver. We typically don't create Observers, they're usually used internally by the Core actors to map Commands and Mediators to Notifications.
Consequently, the Facade does not have a registerObserver method, and it is not required by IFacade, which exposes the Core actor methods that are expected to be in typical use, and not actually the full IView, IModel and IController interfaces.
Your first step is to simply not return anything from listNotificationInterests in your Mediator. This way the View simply registers the Mediator in its Mediator Map and goes on about its business.
Then you want to add a registerObserver method to your concrete ApplicationFacade. This method should in turn call registerObserver on the View. It is not governed by an interface, so its signature can be different from that of the View. This means it can save the Mediator the work of constructing the Observer object, as sendNotification does for INotifiers.
Have your registerObserver method accept the Notification name, a reference to the Mediator instance, and a reference to the callback function. Then it would construct an appropriate Observer instance and call view.registerObserver. (the Facade has a local protected reference to the View Singleton called 'view')
Next, in your Mediator constructor, for each Notification you want to be notified of, do this:
facade.registerObserver( ApplicationFacade.SOME_NOTIFICATION_NAME, this, handleSomeNotification );
That should get you where you're wanting to go.
If I get a chance I'll work this into the courseware. I'm coming up on the section about Mediators, and clarifying this subject with hands on examples would probably be good. This is one of those areas, where the out of box way is simple and will cover most cases, but if you want a different flavor of behavior, you can get to it quickly.
Mediators should play a fairly simple and mechanical role in the architecture:
* Receive Event information from their View Components, gather information from the View Component and/or custom Event and send it off in a Notification.
* Receive Notifications, extract the data mostly from the Notification, and update the View Component.
Similar to a switchboard operator. Who are you calling, sir? Ok, I'll route you through.
Although you can do most anything in a Mediator, limiting it to this role and pushing more complicated stuff, (the sort of stuff you might actually want to reuse) into a Command is a better idea. This keeps the Mediator simple and lightweight, doing only the minimum work necessary to adapt the View Component to the system.
For guidance about the Mediator's role, examine the three Mediators of the Architecture 101 demo, and how they adhere to this simple ambition. Note that a more complicated activity such as deleting a User (and their associated Roles) are done in a Command.
Because they are special case adapters for custom View Components, it is not expected that Mediators will be the most reusable aspect of a system. Due to the relatively simple role Mediators play, I sought the simplest way of 'plugging' them into the system.
But of course this doesn't change the way you feel about the particular implementation. This is why I did my best to make PureMVC a system where you could take or leave as much as you want. If you're down with the out of box way of doing things, great. If not, there are plenty of ways to customize it to your like.
So as to how you might override this Mediator Notification behavior:
When the the View class's registerMediator method is called, it interrogates the Mediator for a list of Notification interests, by calling its listNotificationInterests method. The View maps each Notification name returned to an Observer object that points the Mediator instance and a predetermined callback method - handleNotification.
Examine the View.registerMediator method to see how this happens.
Inside View.registerMediator, when an Observer object is created, it is registered with the View's Observer Map through a call to the public method registerObserver. We typically don't create Observers, they're usually used internally by the Core actors to map Commands and Mediators to Notifications.
Consequently, the Facade does not have a registerObserver method, and it is not required by IFacade, which exposes the Core actor methods that are expected to be in typical use, and not actually the full IView, IModel and IController interfaces.
Your first step is to simply not return anything from listNotificationInterests in your Mediator. This way the View simply registers the Mediator in its Mediator Map and goes on about its business.
Then you want to add a registerObserver method to your concrete ApplicationFacade. This method should in turn call registerObserver on the View. It is not governed by an interface, so its signature can be different from that of the View. This means it can save the Mediator the work of constructing the Observer object, as sendNotification does for INotifiers.
Have your registerObserver method accept the Notification name, a reference to the Mediator instance, and a reference to the callback function. Then it would construct an appropriate Observer instance and call view.registerObserver. (the Facade has a local protected reference to the View Singleton called 'view')
Next, in your Mediator constructor, for each Notification you want to be notified of, do this:
facade.registerObserver( ApplicationFacade.SOME_NOTIFICATION_NAME, this, handleSomeNotification );
That should get you where you're wanting to go.
If I get a chance I'll work this into the courseware. I'm coming up on the section about Mediators, and clarifying this subject with hands on examples would probably be good. This is one of those areas, where the out of box way is simple and will cover most cases, but if you want a different flavor of behavior, you can get to it quickly.
pureMVC Coarse-grained interface concept
in doc:
it's said :
Mediator and Proxies should expose coarse-grained interface to
commands( and each other ), that hides the implementation of
their stewarded View component or Data model
Fine-grained PO一般来说管理着持久数据与表列的一对一映射. Coarse-grained PO通过多个Fine-grained PO 来管理持久数据. 这样, 属于Coarse-grained中的Fine-grained PO, 其生命期受制于Coarse-grained PO, 超过了Coarse-grained PO生命期的Fine-grained PO是没有意义的, 因为它们是做为一个整体出现的. 另外, 客户只能通过Coarse-grained PO来间接的访问其中的Fine-grained PO.
因为Coarse-grained是做为一个整体出现的, 所以Lazy initialization是不可能的, 对Coarse-grained来说, 要么一起装入, 要么什么也不装入, 一起装入也就造成了较长的响应时间, 另外, Coarse-grained也会影响我们写程序时运用inheritance 和 polymorphism(这一点, 希望能得到其它朋友的见解)
EJB就其本身只能做成一种Coarse-grained PO(Sun网站上也不得不这样说), 而Hibernate PO 则可以做成Fine-grained 和Coarse-grained, 显然选择的余地多.
Fine-grained和Coarse-grained 一般是指远程方法调用的接口的颗粒大小.
比如, 我有一个远程对象, 他有很多属性和对应的getter和setter方法,
如果我们远程调用对象每个属性的getter和setter方法, 就会产生很多远程方法调用. 这就是Fine-grained interface, 会造成性能问题
所以我们可以用一个setdata或getdata的方法把一些属性的访问封装起来, 只用一个远程方法传输一个data transfer object来对该对象进行赋值和访问, 这就是Coarse-grained interface
it's said :
Mediator and Proxies should expose coarse-grained interface to
commands( and each other ), that hides the implementation of
their stewarded View component or Data model
Fine-grained PO一般来说管理着持久数据与表列的一对一映射. Coarse-grained PO通过多个Fine-grained PO 来管理持久数据. 这样, 属于Coarse-grained中的Fine-grained PO, 其生命期受制于Coarse-grained PO, 超过了Coarse-grained PO生命期的Fine-grained PO是没有意义的, 因为它们是做为一个整体出现的. 另外, 客户只能通过Coarse-grained PO来间接的访问其中的Fine-grained PO.
因为Coarse-grained是做为一个整体出现的, 所以Lazy initialization是不可能的, 对Coarse-grained来说, 要么一起装入, 要么什么也不装入, 一起装入也就造成了较长的响应时间, 另外, Coarse-grained也会影响我们写程序时运用inheritance 和 polymorphism(这一点, 希望能得到其它朋友的见解)
EJB就其本身只能做成一种Coarse-grained PO(Sun网站上也不得不这样说), 而Hibernate PO 则可以做成Fine-grained 和Coarse-grained, 显然选择的余地多.
Fine-grained和Coarse-grained 一般是指远程方法调用的接口的颗粒大小.
比如, 我有一个远程对象, 他有很多属性和对应的getter和setter方法,
如果我们远程调用对象每个属性的getter和setter方法, 就会产生很多远程方法调用. 这就是Fine-grained interface, 会造成性能问题
所以我们可以用一个setdata或getdata的方法把一些属性的访问封装起来, 只用一个远程方法传输一个data transfer object来对该对象进行赋值和访问, 这就是Coarse-grained interface
Subscribe to:
Posts (Atom)