K
Krivenok Dmitry
Hello All!
I am trying to implement my own Design Patterns Library.
I have read the following documentation about Observer Pattern:
1) Design Patterns by GoF
Classic description of Observer. Also describes implementation
via ChangeManager (Mediator + Singleton)
2) Pattern hatching by John Vlissides
Describes Observer's implementation via Visitor Design Pattern.
3) Design Patterns Explained by Alan Shalloway and James Trott
Describes Observer's implementation via Adaptor Design Pattern.
4) CUJ's article : "Prying eyes : A Policy-Based Observer I,II" by
Andrei Alexandrescu
Very interesting articles, which describes attempt to implement
a policy-based Observer and several serious problems:
a) Mutual recursion (potential infinite loops, etc...)
b) Active observers problem (iteration problem)
c) Notification order problem
d) GetState()'s return value problem
I am trying to combine best aspects of each approach.
Consider the following pseudo-code example:
class Subject
{
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;
virtual @@@ GetState() = 0; // !!! What type should be
returned???
};
class Observer
{
public:
virtual void Update(Subject*) = 0;
};
class MySubject : public Subject
{
public:
void Attach(Observer*)
{
/// Add pair
}
void Detach(Observer*)
{
/// Delete pair
}
void Notify()
{
/// Call observer->Update(this) for each observer in mapping
}
@@@ GetState()
{
/// Return MySubject-specific data. BUT HOW???
}
private:
// Subject-Observer mapping
// MySubject-specific data
};
class YourSubject : public Subject
{
public:
// Along similar lines
private:
// Subject-Observer mapping
// YourSubject-specific data
};
class MyObserver : public Observer /// This class represents MySubject
and YourSubject
{
public:
void Update(Subject* s)
{
/// Only Subject's interface is available here (not MySubject
or YourSubject)
/// I know one bad solution - type switch via dynamic_cast.
if TypeOf(s) == MySubject
{
/// Update MySubject-specific part of representation
}
else if TypeOf(s) == YourSubject
{
/// Update YourSubject-specific part of representation
}
}
private:
/// MyObserver-specific data (e.g. GUI widgets for subjects
representation)
};
The problem lies in poor Subject's interface.
Subject doesn't know anything about MySubject's private data.
I don't understand why GoF includes GetState method in Subject's
interface.
Type of GetState()'s return value depends up concrete subclass of
Subject, i.e.
class ConcreteSubject : Subject
{
public:
ReturnValue<ConcreteSubject> GetState();
...
};
Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?
Thanks!
P.S.
Sorry for my english
I am trying to implement my own Design Patterns Library.
I have read the following documentation about Observer Pattern:
1) Design Patterns by GoF
Classic description of Observer. Also describes implementation
via ChangeManager (Mediator + Singleton)
2) Pattern hatching by John Vlissides
Describes Observer's implementation via Visitor Design Pattern.
3) Design Patterns Explained by Alan Shalloway and James Trott
Describes Observer's implementation via Adaptor Design Pattern.
4) CUJ's article : "Prying eyes : A Policy-Based Observer I,II" by
Andrei Alexandrescu
Very interesting articles, which describes attempt to implement
a policy-based Observer and several serious problems:
a) Mutual recursion (potential infinite loops, etc...)
b) Active observers problem (iteration problem)
c) Notification order problem
d) GetState()'s return value problem
I am trying to combine best aspects of each approach.
Consider the following pseudo-code example:
class Subject
{
public:
virtual void Attach(Observer*) = 0;
virtual void Detach(Observer*) = 0;
virtual void Notify() = 0;
virtual @@@ GetState() = 0; // !!! What type should be
returned???
};
class Observer
{
public:
virtual void Update(Subject*) = 0;
};
class MySubject : public Subject
{
public:
void Attach(Observer*)
{
/// Add pair
}
void Detach(Observer*)
{
/// Delete pair
}
void Notify()
{
/// Call observer->Update(this) for each observer in mapping
}
@@@ GetState()
{
/// Return MySubject-specific data. BUT HOW???
}
private:
// Subject-Observer mapping
// MySubject-specific data
};
class YourSubject : public Subject
{
public:
// Along similar lines
private:
// Subject-Observer mapping
// YourSubject-specific data
};
class MyObserver : public Observer /// This class represents MySubject
and YourSubject
{
public:
void Update(Subject* s)
{
/// Only Subject's interface is available here (not MySubject
or YourSubject)
/// I know one bad solution - type switch via dynamic_cast.
if TypeOf(s) == MySubject
{
/// Update MySubject-specific part of representation
}
else if TypeOf(s) == YourSubject
{
/// Update YourSubject-specific part of representation
}
}
private:
/// MyObserver-specific data (e.g. GUI widgets for subjects
representation)
};
The problem lies in poor Subject's interface.
Subject doesn't know anything about MySubject's private data.
I don't understand why GoF includes GetState method in Subject's
interface.
Type of GetState()'s return value depends up concrete subclass of
Subject, i.e.
class ConcreteSubject : Subject
{
public:
ReturnValue<ConcreteSubject> GetState();
...
};
Main question:
How to avoid type switching in ConcreteObserver::Update(Subject* s)?
Thanks!
P.S.
Sorry for my english