Intent:
Defines a one-to-many dependency between objects. When the status of an object changes, all objects dependent on it are notified and automatically updated.
Applicable environment:
1) When an abstract model has two aspects, one of which depends on the other. Encapsulate the two in independent objects so that they can be changed and reused independently.
2) When changing an object, you need to change other objects at the same time without knowing how many objects need to be changed.
3) when an object must notify other objects, it cannot assume who the other objects are. In other words, you do not want these objects to be tightly coupled.
Structure:
The object of the observer acts as a member of the subject and then calls the UPDATE function through the observers. In fact, the update () function of the concreteobserver is called, which reflects the polymorphism in C ++: the base class pointer calls the function of the derived class;
Similarly, the reference to concretesubject is saved in concreteobserver, so that the getstate function in concretesubject can be accessed through subject, so that subject and observer can access each other. Note that the subject pointer cannot be defined to direct to the concretesubject object, because the getstate function of concretesubjec cannot be accessed through the base class pointer at this time, because this function is not available in the base class;
At the same time, the subject class saves the observer through the list linked list, and updates all the observer states by using the iterator to traverse the table;
Collaboration relationship:
When any change to the concretesubject that may cause its observer to be inconsistent with its own State, it notifies its various observers.
After receiving a change notification for a specific target, the concreteobserver object can query the information of the target object. The concreteobserver uses this information to make its status consistent with that of the target object;
The observer object of the change request is not updated immediately, but is postponed until it receives a notification from the target.
Notify can be triggered by the target object (subject) or by the user;
Program source code:
Basesubject. h
# Pragma once
# Include "baseobserver. H"
# Include <list>
Using namespace STD;
Class basesubject
{
Public:
Basesubject (void );
Virtual ~ Basesubject (void );
/*
*/
Virtual void attach (baseobserver *);
Virtual void detach (baseobserver *);
Virtual void notify ();
PRIVATE:
List <baseobserver *> * _ observers;
};
Basesubject. cpp File
# Include "stdafx. H"
# Include "basesubject. H"
Basesubject: basesubject (void)
{
}
Basesubject ::~ Basesubject (void)
{
}
Void basesubject: attach (baseobserver * o ){
_ Observers-> push_back (O );
}
/*
*/
Void basesubject: Detach (baseobserver * o ){
List <baseobserver *>: iterator ITER;
For (iter = _ observers-> begin (); iter! = _ Observers-> end (); ITER ++)
{
If (* ITER) = O)
{
_ Observers-> erase (ITER ++ );
} Else
{
ITER ++;
}
}
}
/*
*/
Void basesubject: Policy (){
//
List <baseobserver *>: iterator ITER;
For (iter = _ observers-> begin (); iter! = _ Observers-> end (); ITER ++)
{
(* ITER)-> Update ();
}
}
Derivedsubject. h file
# Pragma once
Class derivedsubject
{
Public:
Derivedsubject (void );
Virtual ~ Derivedsubject (void );
Int getstate ();
Void setstate (int I );
Int subjectstate;
};
Derivedsubject. cpp File
# Include "stdafx. H"
# Include "derivedsubject. H"
Derivedsubject: derivedsubject (void)
{
}
Derivedsubject ::~ Derivedsubject (void)
{
}
Int derivedsubject: getstate ()
{
Return subjectstate;
}
Void derivedsubject: setstate (int I)
{
Subjectstate = I;
}
Baseobserver. h file
# Pragma once
Class baseobserver
{
Public:
Baseobserver (void );
Baseobserver (const baseobserver & pt)
{
Printf ("");
}
Virtual ~ Baseobserver (void );
Virtual void Update () = 0;
};
Baseobserver. cpp File
# Include "stdafx. H"
# Include "baseobserver. H"
Baseobserver: baseobserver (void)
{
}
Baseobserver ::~ Baseobserver (void)
{
}
Derivedobserver. h file
# Pragma once
# Include "baseobserver. H"
# Include "derivedsubject. H"
Class derivedobserver:
Public baseobserver
{
Public:
Derivedobserver (void );
Virtual ~ Derivedobserver (void );
Void Update ();
PRIVATE:
Int observerstate;
Derivedsubject subject;
};
Derivedobserver. cpp File
# Include "stdafx. H"
# Include "derivedobserver. H"
Derivedobserver: derivedobserver (void)
{
}
Derivedobserver ::~ Derivedobserver (void)
{
}
Void derivedobserver: Update ()
{
Observerstate = subject. getstate ();
Printf ("observerstate % d \ n", observerstate );
}
Call the main function:
// Observerpattern. cpp: defines the entry point of the console application.
//
# Include "stdafx. H"
# Include "basesubject. H"
# Include "derivedsubject. H"
# Include "baseobserver. H"
# Include "derivedobserver. H"
Int _ tmain (INT argc, _ tchar * argv [])
{
Basesubject * m_subject = new basesubject ();
Derivedsubject * m_concretesubject = new derivedsubject ();
Baseobserver * m_observer = new derivedobserver ();
M_concretesubject-> setstate (2 );
Printf ("subjectstate % d \ n", m_concretesubject-> subjectstate );
M_subject-> attach (m_observer );
M_subject-> sort y ();
Return 0;
}
Notes in the program:
1) What are the erase failures of vector ordered containers, list ordered containers, and map associated containers?
Note:
After the erase element of the vector sequence container, not only do all iterators pointing to the deleted element become invalid, but also all iterators pointing to the deleted element become invalid. Therefore, erase (ITER ++) cannot be used) method;
Correct usage:
For (iter = C. Begin (); iter! = C. End ();)
{
Iter = C. Erase (ITER); // erase returns the next effective iterator;
}
Associated container map: the erase iterator is invalid only for the iterator whose elements are deleted, but the returned value is void. Therefore, erase (ITER ++) is used to delete the iterator;
For (iter = C. Begin (); iter! = C. End ())
{
C. Erase (ITER ++ );
}
Corresponding map
For (Map <int, string >:: iterator iter = strmap. Begin (); iter! = Strmap. End ())
{
If (some_condition)
{
Strmap. Erase (ITER ++ );
} Else
{
ITER ++;
}
}
List erase only invalidates the current node. The solution is similar to map;
2) in the program, push_back has a memory conflict. I did not check the problem carefully. If any problem is solved, please let me know. Thank you!