Here we will give an implementation example of the observer design pattern in Symbian C++. We will implement it in Symbian S60 2nd Edition, although the developer SDK version is not important that here because we will not be doing any extensive of any SDK API.
The original Observer pattern need not to be described here because that is available over the net or reference books.
Symbian Application depends on the view based architecture. That is , we can use Symbian view and Container classes together to present some Model on the application. So, we will use Symbian View (CAknView) and Container (CCoeControl) classes for the view part of the Observer pattern implementation. Actually, sample application implementing the Observer Pattern needs two Views + containers , one of which will be the opening or Default view, and the other will present the changing data (Which is actually the view used in the Observer pattern).
Along with demonstrating the implementation of the Observer pattern , here we have used multiple views in my application. In my next blog I will show how to do that.Otherwise, carefully looking at the current example will also do.
For implementing the observer pattern , we will need Model which holds the transient or changing data. For simulating the changing data, we will use Active objects. In other cases, it can be a class with asynchronous functions. Its a simple class which extends the CActive class and holds a list of Observers (Described later) which observers on the change of Data. It also contains functions for attaching and detaching observers and also for notifying the observer upon change in Data.

The Class which acts as the model is called "CUserData" (just for the record)..
For now, it is enough to show only the model class decleration. Now we turn to Observers. One things should be kept in mind here, this is not optimal example of implementation of Observer Pattern, (i.e. Programming to interface, not implementation etc).
For creating Observers , we first create an Observer interface through which the actual observers will be attached , detached or notified by the model.

Now, the observer interface is ready. Now we declare the Observer (The View + Container classes) which implements this MObserver interface.
The View Part: This is the main part.. This will keep connection with the Model.
Now , we need a controller. Here, the AppUI will act as a controller. It has reference to the view and the Model. It controls the change in view too. Here is the snapshot of our AppUI class...
Now, we see how it works...
1. Create the Observer View and Subject (CUserData) from inside the AppUI.
void CObserverTestAppUi::ConstructL()
{
BaseConstructL();
iAppContainer = new (ELeave) CObserverTestContainer;
//we create the Observer
iUserStatusView = new (ELeave) CUserStatusView(*this,KNoView);
iUserStatusView->ConstructL();
AddViewL(iUserStatusView);
//We create another View which is the default view
iOpeningView = new (ELeave) COpeningView(*this,KNoView);
iOpeningView->ConstructL();
AddViewL(iOpeningView);
//we create the Subject
iGpsData = new (ELeave) CUserData();
iGpsData->ConstructL();
iAppContainer->SetMopParent( this );
iAppContainer->ConstructL( ClientRect() );
SetDefaultViewL(*iOpeningView);
AddToStackL( iAppContainer );
}
2. In the CUserStatusView class , there is not much to show, we just have an Update Function which is called from the Subject;s Notify() function.
void CUserStatusView::Update(CUserData* theChangedSubject)
{
iContainer->SetSize(theChangedSubject->GetRectSize());
iContainer->SetAngle(theChangedSubject->DirectionAngle());
}
It is evident what this function does.... :-)
3. There is not also much to show the UserStatusContainer , inside its draw function , the data from CUserData is taken and shown in appropriate format to the screen.
4. The Subject (CUserData) class has some importatnt functions which are notable.
void CUserData::Attach(MObserver* anObserver)
{
iObservers.Append(anObserver);//attaches the observer to this
}
void CUserData::Detach(MObserver* anObserver)
{
}
void CUserData::Notify()
{
//notifies all the observers...
TInt numObservers = iObservers.Count();
for(TInt index =0; index <>Update(this);//this is the views Update function stated at step 2
}
5. And the above Notify() function is called from the Active Objects RunL() function..
void CUserData::RunL()
{
...................
Notify();
if (iState == EUninitialized) {
// Do something the first time RunL() is called
iState = EInitialized;
} else if (iState != EError) {
// Do something
}
iTimer.After(iStatus, 1000000); // Set for 1 sec later
SetActive(); // Tell scheduler a request is active
}
6. Now the most important thing... controlliing the view from AppUI...
void CObserverTestAppUi::HandleCommandL(TInt aCommand)
{
switch ( aCommand )
{
case EAknSoftkeyBack:
case EEikCmdExit:
{
Exit();
break;
}
case EObserverTestCmdAppTest:
{
iGpsData->Attach(iUserStatusView);
iGpsData->StartL(1000000);
ActivateViewL(TVwsViewId(KUidObserverTest,KUserStatusViewId));
break;
}
case EViewChangeCmd:
{
iGpsData->Detach(iUserStatusView);
iGpsData->Cancel();
ActivateViewL(TVwsViewId(KUidObserverTest,KOpeningViewId));
break;
}
default:
break;
}
}
This is the implementation details of the Observer pattern in Symbian C++ platform. Because of the Symbian OS architecture, the implementation is so Easy. There , is not much to customize, the great Symbian has it all made up from before....
The original Observer pattern need not to be described here because that is available over the net or reference books.
Symbian Application depends on the view based architecture. That is , we can use Symbian view and Container classes together to present some Model on the application. So, we will use Symbian View (CAknView) and Container (CCoeControl) classes for the view part of the Observer pattern implementation. Actually, sample application implementing the Observer Pattern needs two Views + containers , one of which will be the opening or Default view, and the other will present the changing data (Which is actually the view used in the Observer pattern).
Along with demonstrating the implementation of the Observer pattern , here we have used multiple views in my application. In my next blog I will show how to do that.Otherwise, carefully looking at the current example will also do.
For implementing the observer pattern , we will need Model which holds the transient or changing data. For simulating the changing data, we will use Active objects. In other cases, it can be a class with asynchronous functions. Its a simple class which extends the CActive class and holds a list of Observers (Described later) which observers on the change of Data. It also contains functions for attaching and detaching observers and also for notifying the observer upon change in Data.

The Class which acts as the model is called "CUserData" (just for the record)..
For now, it is enough to show only the model class decleration. Now we turn to Observers. One things should be kept in mind here, this is not optimal example of implementation of Observer Pattern, (i.e. Programming to interface, not implementation etc).
For creating Observers , we first create an Observer interface through which the actual observers will be attached , detached or notified by the model.

Now, the observer interface is ready. Now we declare the Observer (The View + Container classes) which implements this MObserver interface.
The View Part: This is the main part.. This will keep connection with the Model.
Now , we need a controller. Here, the AppUI will act as a controller. It has reference to the view and the Model. It controls the change in view too. Here is the snapshot of our AppUI class...
Now, we see how it works...1. Create the Observer View and Subject (CUserData) from inside the AppUI.
void CObserverTestAppUi::ConstructL()
{
BaseConstructL();
iAppContainer = new (ELeave) CObserverTestContainer;
//we create the Observer
iUserStatusView = new (ELeave) CUserStatusView(*this,KNoView);
iUserStatusView->ConstructL();
AddViewL(iUserStatusView);
//We create another View which is the default view
iOpeningView = new (ELeave) COpeningView(*this,KNoView);
iOpeningView->ConstructL();
AddViewL(iOpeningView);
//we create the Subject
iGpsData = new (ELeave) CUserData();
iGpsData->ConstructL();
iAppContainer->SetMopParent( this );
iAppContainer->ConstructL( ClientRect() );
SetDefaultViewL(*iOpeningView);
AddToStackL( iAppContainer );
}
2. In the CUserStatusView class , there is not much to show, we just have an Update Function which is called from the Subject;s Notify() function.
void CUserStatusView::Update(CUserData* theChangedSubject)
{
iContainer->SetSize(theChangedSubject->GetRectSize());
iContainer->SetAngle(theChangedSubject->DirectionAngle());
}
It is evident what this function does.... :-)
3. There is not also much to show the UserStatusContainer , inside its draw function , the data from CUserData is taken and shown in appropriate format to the screen.
4. The Subject (CUserData) class has some importatnt functions which are notable.
void CUserData::Attach(MObserver* anObserver)
{
iObservers.Append(anObserver);//attaches the observer to this
}
void CUserData::Detach(MObserver* anObserver)
{
}
void CUserData::Notify()
{
//notifies all the observers...
TInt numObservers = iObservers.Count();
for(TInt index =0; index <>Update(this);//this is the views Update function stated at step 2
}
5. And the above Notify() function is called from the Active Objects RunL() function..
void CUserData::RunL()
{
...................
Notify();
if (iState == EUninitialized) {
// Do something the first time RunL() is called
iState = EInitialized;
} else if (iState != EError) {
// Do something
}
iTimer.After(iStatus, 1000000); // Set for 1 sec later
SetActive(); // Tell scheduler a request is active
}
6. Now the most important thing... controlliing the view from AppUI...
void CObserverTestAppUi::HandleCommandL(TInt aCommand)
{
switch ( aCommand )
{
case EAknSoftkeyBack:
case EEikCmdExit:
{
Exit();
break;
}
case EObserverTestCmdAppTest:
{
iGpsData->Attach(iUserStatusView);
iGpsData->StartL(1000000);
ActivateViewL(TVwsViewId(KUidObserverTest,KUserStatusViewId));
break;
}
case EViewChangeCmd:
{
iGpsData->Detach(iUserStatusView);
iGpsData->Cancel();
ActivateViewL(TVwsViewId(KUidObserverTest,KOpeningViewId));
break;
}
default:
break;
}
}
This is the implementation details of the Observer pattern in Symbian C++ platform. Because of the Symbian OS architecture, the implementation is so Easy. There , is not much to customize, the great Symbian has it all made up from before....

5 comments:
1. I don't understand, does it have any difference from simple observer pattern.
2. Another thing is you mention about view based architecture, does come it from MVC? then it is inherently follow the observer pattern.
Yes , both of the points are valid. But my goal was not to re-describe the observer pattern, there are thousands of references about observer pattern over the web. My idea is to just show how to implement it in the Symbian C++ platform.(look at the title)There is no difference between this one and a stripped down simple observer pattern.This is just a solution to the "unknown Unknown" problem - a symbian developer who does not know what to know. I have tried to tell him what he needs to know. Thats it...
Great article! This is _the_ implementation of the observer pattern on Symbian C++!
Can you tell me why your Detach() method is implemented empty?
Btw. Visit my blog on makomdev.blogspot.com ;-)
If you are looking wow power leveling, buy warcraft gold as well as WOW Power Leveling and World Of wow levelingWhen you need someone to listen,FFXI Gil, I'll be there. When you need a hug, cheap FFXI Gil,I'll be there. When you need someone to hold your hand, I'll be there. When you need someone to wipe your tears, guess what? I'll be there. William Shakespeare
Post a Comment