设计模式C++描述----04.观察者(Observer)模式 (四)

2014-11-24 12:03:53 · 作者: · 浏览: 2
知改变状态(调用Observer的Update操作)。
2. 运行示例程序,可以看到当原始数据 Subject 处于状态 “old” 时候,依赖于它的两个观察者都显示 “old”,当原始数据状态改变为 “new” 的时候,依赖于它的两个观察者也都改变为“new”。
3. 可以看到 Observer 与 Subject 互为耦合,但是这种耦合的双方都依赖于抽象,而不依赖于具体。

三. MFC中的观察者模式

MFC 的 View/Document 结构的实现中也采用了观察者模式。

Document 为模式中的通知者,管理应用程序中的数据,View为模式中的观察者,以给定的方显示所关联的 Document中的数据。CDocument类中定义了一个指针列表,用于保存对应的 CView 对象,并定义了一个函数用于对链表中的所有CView的对象进行更新。

结构如下:

\


原代码如下:


[cpp] //afxwin.h
class CDocument : public CCmdTarget
{
public:

// Operations
void AddView(CView* pView); //注册操作
void RemoveView(CView* pView); //注销操作


// Update Views (simple update - DAG only) //通知操作
void UpdateAllViews(CView* pSender, LPARAM lHint = 0L,
CObject* pHint = NULL);

protected:

CPtrList m_viewList; // list of views
}


//DocCore.cpp
void CDocument::AddView(CView* pView)
{
ASSERT_VALID(pView);
ASSERT(pView->m_pDocument == NULL); // must not be already attached
ASSERT(m_viewList.Find(pView, NULL) == NULL); // must not be in list

m_viewList.AddTail(pView); //加入链表中
ASSERT(pView->m_pDocument == NULL); // must be un-attached
pView->m_pDocument = this;

OnChangedViewList(); // must be the last thing done to the document
}

void CDocument::RemoveView(CView* pView)
{
ASSERT_VALID(pView);
ASSERT(pView->m_pDocument == this); // must be attached to us

m_viewList.RemoveAt(m_viewList.Find(pView)); //从链表中删除
pView->m_pDocument = NULL;

OnChangedViewList(); // must be the last thing done to the document
}

void CDocument::UpdateAllViews(CView* pSender, LPARAM lHint, CObject* pHint)
// walk through all views
{
ASSERT(pSender == NULL || !m_viewList.IsEmpty());
// must have views if sent by one of them

POSITION pos = GetFirstViewPosition(); //遍历所有观察者
while (pos != NULL)
{
CView* pView = GetNextView(pos);
ASSERT_VALID(pView);
if (pView != pSender)
pView->OnUpdate(pSender, lHint, pHint);
}
}
//afxwin.h
class CDocument : public CCmdTarget
{
public:

// Operations
void AddView(CView* pView); //注册操作
void RemoveView(CView* pView); //注销操作


// Update Views (simple update - DAG only) //通知操作
void UpdateAllViews(CView* pSender, LPARAM lHint = 0L,
CObject* pHint = NULL);

protected:

CPtrList m_viewList; // list of views
}


//DocCore.cpp
void CDocument::AddView(CView* pView)
{
ASSERT_VALID(pView);
ASSERT(pView->m_pDocument == NULL); // must not be already attached
ASSERT(m_viewList.Find(pView, NULL) == NULL); // must not be in list

m_viewList.AddTail(pView); //加入链表中
ASSERT(pView->m_pDocument == NULL); // must be un-attached
pView->m_pDocument = this;

OnChangedViewList(); // must be the last thing done to the document
}

void CDocument::RemoveView(CView* pView)
{
ASSERT_VALID(pView);
ASSERT(pView->m_pDocument == this); // must be attached to us

m_viewList.RemoveAt(m_viewList.Find(pView)); //从链表中删除
pView->m_pDocument = NULL;

OnChangedViewList(); // must be the last thing done to the document
}

void CDocument::UpdateAllViews(CView* pSender, LPARAM lHint, CObject* pHint)
// walk through all views
{
ASSERT(pSender == NULL || !m_viewList.IsEmpty());
// must have views if sent by one of them

POSITION pos = GetFirstViewPosition();