Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: Mediator role  (Read 10706 times)
newtriks
Courseware Beta
Full Member
***
Posts: 23


 - newtriks
View Profile WWW Email
« on: October 13, 2007, 12:24:51 »

Hi all,

Just a quick easy one for ya'll, do you think its acceptable to have a mediator which is not assigned to a view component.  For example, a mediator to monitor the status of a remote connection? cheers simon
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: October 13, 2007, 01:50:27 »

The Mediators are more concerned with adapting the View to the rest of the PureMVC system, and so would not really be the right setup.

Without a View Component, the Mediator could only be sent Notifications from elsewhere in the application and as a result either fire off further notifications or manipulate the Model, which is a responsibility muddle.

Really, a Proxy is the right place for it. In the same way a Mediator would place event listeners on its View Component, the Proxy owns and listens to the HTTPService or whatever the remote connection component is as its data object. Proxies don't just have to hold data, they can control access to any object such as a service or socket connection.

In the CodePeek demo, have a look at the CodePeekSearchProxy which handles the service to talk with Google Code.

-=Cliff>
Logged
newtriks
Courseware Beta
Full Member
***
Posts: 23


 - newtriks
View Profile WWW Email
« Reply #2 on: October 13, 2007, 01:53:05 »

Cheers Cliff, I have resolved without the mediator and is cool!

Looks like it was a good presentation at MAX :) nervous on stage or super cool?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: October 13, 2007, 07:11:46 »

Heh, right. A bit of both really. It was a lot of fun. I suggest trying it sometime. Tricky format. ;)

-=Cliff>
Logged
immerzeel
Courseware Beta
Jr. Member
***
Posts: 14


View Profile Email
« Reply #4 on: October 17, 2007, 03:03:03 »

About mediators without a view. I have got one and it was kind of difficult for me to see where the code should be. First I decided to make it a Proxy, but it has to send and receive Notifications, which doesn't apply to the model (AFIAK).

This is an implementation of SWFAddress, which allows deeplinking in the SWF. It changes the URL, which allows bookmarking. On view changes I send a Nofication from my ApplicationMediator, which this class receives and changes the URL.
When someone lands on the site with an URL, this class sends a similar Notification to change the view in the ApplicationMediator. The internalUpdate switch prevents the application from looping.

I tried to implement it in the ApplicationMediator, but that got too messy and bloated for my taste.

My questions are:
Should it be a Proxy? if so, what to do about the Notification handling?
Should it stay a Mediator? The BrowserMediator gets fed a null object in the ViewPrepCommand, which smells a bit funny.
Should it be a stand-alone class? My problem then is where do I put it, this was the simplest solution I could think of.
Are the (public) constants and 'switch' statements bad practice? I do prefer 'switch' over 'for', it is easier to read.

:
package com.ip.nowhere.view {
import org.puremvc.patterns.mediator.Mediator;
import org.puremvc.interfaces.IMediator;
import org.puremvc.interfaces.INotification;

import com.ip.nowhere.ApplicationFacade;

/**
*/
public class BrowserMediator extends Mediator implements IMediator {
/**
* Canonical name of <code>BrowserMediator</code>.
*/
public static const NAME : String = "BrowserMediator";

public static const EVENTS : String = "/events";
public static const WORKSHOPS : String = "/workshops";
public static const SEARCH : String = "/search";
public static const NEWS : String = "/news";
public static const AGENDA : String = "/agenda";
public static const PICS : String = "/pics";
public static const FILM : String = "/film";
public static const SPEAK : String = "/speak";
public static const READ : String = "/read";
public static const ART : String = "/art";
public static const SHOW : String = "/show";

/**
* View is internally updated.
* If true, <code>handleSWFAddressChange</code> won't send the
* notfications.
*/
private var internalUpdate : Boolean = false;

/**
* Constructor.
*
* @param viewComponent
*/
public function BrowserMediator(viewComponent : Object) {
super(viewComponent);

SWFAddress.onChange = handleSWFAddressChange;
}

/**
* Get <code>BrowserMediator</code> name.
*
* @return Name of <code>BrowserMediator</code>.
*/
override public function getMediatorName() : String {
return BrowserMediator.NAME;
}

/**
* List all notifications.
*
* @return Array List of Notification names.
*/
override public function listNotificationInterests() : Array {
return [ApplicationFacade.STARTUP,
ApplicationFacade.VIEW_EVENTS,
ApplicationFacade.VIEW_WORKSHOPS,
ApplicationFacade.VIEW_SEARCH,
ApplicationFacade.VIEW_NEWS,
ApplicationFacade.VIEW_AGENDA,
ApplicationFacade.VIEW_PICS,
ApplicationFacade.VIEW_FILM,
ApplicationFacade.VIEW_SPEAK,
ApplicationFacade.VIEW_READ,
ApplicationFacade.VIEW_ART,
ApplicationFacade.VIEW_SHOW];
}

/**
* Handle all Notifications.
*
* @param note Notification.
*/
override public function handleNotification(note : INotification) : void {

internalUpdate = true;

switch(note.getName()) {
case ApplicationFacade.STARTUP:
case ApplicationFacade.VIEW_EVENTS:
SWFAddress.setValue(EVENTS);
break;

case ApplicationFacade.VIEW_WORKSHOPS:
SWFAddress.setValue(WORKSHOPS);
break;

case ApplicationFacade.VIEW_SEARCH:
SWFAddress.setValue(SEARCH);
break;

case ApplicationFacade.VIEW_NEWS:
SWFAddress.setValue(NEWS);
break;

case ApplicationFacade.VIEW_AGENDA:
SWFAddress.setValue(AGENDA);
break;

case ApplicationFacade.VIEW_PICS:
SWFAddress.setValue(PICS);
break;

case ApplicationFacade.VIEW_FILM:
SWFAddress.setValue(FILM);
break;

case ApplicationFacade.VIEW_SPEAK:
SWFAddress.setValue(SPEAK);
break;

case ApplicationFacade.VIEW_READ:
SWFAddress.setValue(READ);
break;

case ApplicationFacade.VIEW_ART:
SWFAddress.setValue(ART);
break;

case ApplicationFacade.VIEW_SHOW:
SWFAddress.setValue(SHOW);
break;

default:
}
}

/**
* Handles the <code>onChange</code> event of <code>SWFAddress</code>.
*/
private function handleSWFAddressChange() : void {
if (!internalUpdate) {
switch(SWFAddress.getValue()) {
case EVENTS:
sendNotification(ApplicationFacade.VIEW_EVENTS);
break;

case WORKSHOPS:
sendNotification(ApplicationFacade.VIEW_WORKSHOPS);
break;

case SEARCH:
sendNotification(ApplicationFacade.VIEW_SEARCH);
break;

case NEWS:
sendNotification(ApplicationFacade.VIEW_NEWS);
break;

case AGENDA:
sendNotification(ApplicationFacade.VIEW_AGENDA);
break;

case PICS:
sendNotification(ApplicationFacade.VIEW_PICS);
break;

case FILM:
sendNotification(ApplicationFacade.VIEW_FILM);
break;

case SPEAK:
sendNotification(ApplicationFacade.VIEW_SPEAK);
break;

case READ:
sendNotification(ApplicationFacade.VIEW_READ);
break;

case ART:
sendNotification(ApplicationFacade.VIEW_ART);
break;

case SHOW:
sendNotification(ApplicationFacade.VIEW_SHOW);
break;

default:
}
}

SWFAddress.setTitle(ApplicationProxy.getTitle() + SWFAddress.getValue());

internalUpdate = false;
}
}
}

Next is the ApplicationMediator class. The registerChild method registers the views that act like screens. The selectedChild method makes the selected view visible and hides the others (this is my semi-implementation of Flex's ViewStack, as this is an AS3/Flash application). As you can see both classes seem similar and don't feel DRY. It works, but I am open to refactoring and complying to best practices .

Later,

Pascal

:
package com.ip.nowhere.view {
import flash.display.MovieClip;

import org.puremvc.interfaces.IMediator;
import org.puremvc.interfaces.INotification;
import org.puremvc.patterns.mediator.Mediator;

import com.ip.nowhere.model.ApplicationProxy;
import com.ip.nowhere.ApplicationFacade;

/**
*/
public class ApplicationMediator extends Mediator implements IMediator {
/**
* Canonical name of <code>ApplicationMediator</code>.
*/
public static const NAME : String = "ApplicationMediator";

private var applicationProxy : ApplicationProxy;

/**
* Constructor.
*
* @param viewComponent
*/
public function ApplicationMediator(viewComponent : Object) {
super(viewComponent);

applicationProxy = facade.retrieveProxy(ApplicationProxy.NAME) as ApplicationProxy;

applicationProxy.registerChild(ApplicationFacade.VIEW_EVENTS, application.eventsView);
applicationProxy.registerChild(ApplicationFacade.VIEW_WORKSHOPS, application.workshopsView);
applicationProxy.registerChild(ApplicationFacade.VIEW_SEARCH, application.searchView);
applicationProxy.registerChild(ApplicationFacade.VIEW_NEWS, application.newsView);
applicationProxy.registerChild(ApplicationFacade.VIEW_AGENDA, application.agendaView);
applicationProxy.registerChild(ApplicationFacade.VIEW_PICS, application.picsView);
applicationProxy.registerChild(ApplicationFacade.VIEW_FILM, application.filmView);
applicationProxy.registerChild(ApplicationFacade.VIEW_SPEAK, application.speakView);
applicationProxy.registerChild(ApplicationFacade.VIEW_READ, application.readView);
applicationProxy.registerChild(ApplicationFacade.VIEW_ART, application.artView);
applicationProxy.registerChild(ApplicationFacade.VIEW_SHOW, application.showView);
}

/**
* Get <code>ApplicationMediator</code> name.
*
* @return Name of <code>ApplicationMediator</code>.
*/
override public function getMediatorName() : String {
return ApplicationMediator.NAME;
}

/**
* List all notifications.
*
* @return Array List of Notification names.
*/
override public function listNotificationInterests() : Array {
return [ApplicationFacade.STARTUP,
ApplicationFacade.VIEW_EVENTS,
ApplicationFacade.VIEW_WORKSHOPS,
ApplicationFacade.VIEW_SEARCH,
ApplicationFacade.VIEW_NEWS,
ApplicationFacade.VIEW_AGENDA,
ApplicationFacade.VIEW_PICS,
ApplicationFacade.VIEW_FILM,
ApplicationFacade.VIEW_SPEAK,
ApplicationFacade.VIEW_READ,
ApplicationFacade.VIEW_ART,
ApplicationFacade.VIEW_SHOW];
}

/**
* Handle all Notifications.
*
* @param note Notification.
*/
override public function handleNotification(note : INotification) : void {
switch(note.getName()) {
case ApplicationFacade.STARTUP:
case ApplicationFacade.VIEW_EVENTS:
applicationProxy.selectedChild = ApplicationFacade.VIEW_EVENTS;
break;

case ApplicationFacade.VIEW_WORKSHOPS:
applicationProxy.selectedChild = ApplicationFacade.VIEW_WORKSHOPS;
break;

case ApplicationFacade.VIEW_SEARCH:
applicationProxy.selectedChild = ApplicationFacade.VIEW_SEARCH;
break;

case ApplicationFacade.VIEW_NEWS:
applicationProxy.selectedChild = ApplicationFacade.VIEW_NEWS;
break;

case ApplicationFacade.VIEW_AGENDA:
applicationProxy.selectedChild = ApplicationFacade.VIEW_AGENDA;
break;

case ApplicationFacade.VIEW_PICS:
applicationProxy.selectedChild = ApplicationFacade.VIEW_PICS;
break;

case ApplicationFacade.VIEW_FILM:
applicationProxy.selectedChild = ApplicationFacade.VIEW_FILM;
break;

case ApplicationFacade.VIEW_SPEAK:
applicationProxy.selectedChild = ApplicationFacade.VIEW_SPEAK;
break;

case ApplicationFacade.VIEW_READ:
applicationProxy.selectedChild = ApplicationFacade.VIEW_READ;
break;

case ApplicationFacade.VIEW_ART:
applicationProxy.selectedChild = ApplicationFacade.VIEW_ART;
break;

case ApplicationFacade.VIEW_SHOW:
applicationProxy.selectedChild = ApplicationFacade.VIEW_SHOW;
break;

default:
}
}

/**
* Cast the <code>viewComponent</code> to its actual type.
*
* @return viewComponent
*/
protected function get application() : MovieClip {
return viewComponent as MovieClip;
}
}
}
Logged
Pages: [1]
Print