I'm not clear from your code, but if you have a member that is logically const, but physically non-const, the usual solution is to make it mutable.
Instead of returning the const Model, you can create one more class which wraps the Notifier object and implements Notifier. (Adapter pattern). Observers can use the newly created class for registering/unregistering.
instead
view->SetModel( model );
you could call
model->getNotifier()->addObserver( view );
view->setModel( model ); // this function will accept const Model*
If you consider the Notifier object not to be part of the Model object which owns it, so that modifying the Notifier doesn't "count" as modifying the Model, then make getNotifier a const method returning a non-const reference:
Notifier& GetNotifier() const //Is const but returns a non-const
{ //reference to allow Observers to
//register themselves.
return m_Notifier;
}
You will then have to either mark m_Notifier as mutable, or else own it by pointer (or smart pointer) or reference rather than by inclusion. Either way, you avoid a const_cast. It is usually preferable to embed objects rather than point/refer to them, but if this is a case where a Notifier isn't considered part of the Model which uses it, then embedding is not essential. Owning it by reference forces you to initialize the reference when Model is constructed, which leads to dependency injection, which is no bad thing. Owning by smart pointer means that, as with embedding, you don't have to do anything about cleanup.
There may be other ways to design things (such as Vinay's addition of another class), but your comment "Is non-const because it needs to return a non-const reference" suggests to me that you can do exactly what you originally wanted, you just don't realise you can.
An alternative approach to my other answer.
Don't have the observer hold a pointer to the model at all. Pass a const *Model
into the update method, which is called by the notifier. This would need to know what model it is notifying for, but that probably isn't difficult given that it's embedded in a model, so it's probably always that one...
If the Observer then needs a non-const Model in SetModel you can still give it one, but more likely is that you'll get rid of SetModel entirely, and just call some_model.AddObserver(some_observer)
instead of some_observer.SetModel(some_model)
.
Similarly but less drastically, you could leave things as they are but declare const *Model m_Model
. Then you can use aModel as a non-const Model in SetModel, but no other method of the observer can modify the Model.
Neither of these changes will work if the Observer is expected to be able to unregister itself without a parameter to use to do so.
I expect Controller to resolve this:
1.Controller knows Model and allows View registration to Model.
class MyController
{
public:
//Controller associated with the Model
MyController(Model* pModel):m_pModel(pModel)
{
}
//Provide the facility to register the view.
//Alternatively, if there is 1:1 relation between controller and View then View poniter can be stored locally inside Controller
void registerObserver(Observer* pObserver)
{
//Register observer
m_pModel->GetNotifier().AddObserver(pObserver);
//set the model in view
pObserver->SetModel(m_pModel);
}
};
2.Change the MyNonModifingView to accept const Model* aModel
class MyNonModifingView : public Observer
{
public:
SetModel(const Model* aModel)
{
m_Model = aModel;
//NO need to register here, My controller does it for me.
// m_Model->GetNotifier().AddObserver(this);
}
void Update() //Part of Observer-Interface, called by Notifiers
{
m_Model->QueryState();
}
};