欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++設(shè)計模式之訪問者模式

 更新時間:2014年10月09日 09:47:51   作者:果凍想  
這篇文章主要介紹了C++設(shè)計模式之訪問者模式,本文講解了什么是訪問者模式、訪問者模式的UML類圖、訪問者模式的實現(xiàn)代碼等內(nèi)容,需要的朋友可以參考下

前言

這是23+1(簡單工廠模式)之中的最后一個了——訪問者模式。訪問者模式也是一個比較麻煩的設(shè)計模式。我也沒有實戰(zhàn)經(jīng)驗,對于訪問者模式的理解完全來自GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》,而這篇文章就是根據(jù)對這本書的理解而寫出來的。在讀《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》的時候,讓我想起自己做過的一個項目,該項目雖然沒有使用訪問者模式,但是,今天理解了該模式,如果使用該模式對之前做過的項目進行重構(gòu),將是一個不錯的想法。

訪問者模式

在GOF的《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書中對訪問者模式是這樣說的:表示一個作用于某對象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。訪問者模式把數(shù)據(jù)結(jié)構(gòu)和作用于結(jié)構(gòu)上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。該模式的目的是要把處理從數(shù)據(jù)結(jié)構(gòu)分離出來。訪問者模式讓增加新的操作很容易,因為增加新的操作就意味著增加一個新的訪問者。訪問者模式將有關(guān)的行為集中到一個訪問者對象中?,F(xiàn)在再來說說我之前經(jīng)歷過的那個項目。

是基于Windows Shell開發(fā)的一個項目,在一個容器中存儲了很多的Shell Items,同時定義了對Items的操作,由于項目一直都在進行后期擴展,對Items的操作在后期都需要進行擴展的;而現(xiàn)在的做法是,定義一個操作類,該操作類中定義了一個集合,該集合存放Items,在該操作類中擴展對應(yīng)的操作方法?,F(xiàn)在想想如果使用訪問者模式也是可以的,由于Items集合是固定的,當(dāng)需要擴展集合的操作時,只需要添加對應(yīng)的訪問者即可。

UML類圖

Visitor(訪問者):為該對象結(jié)構(gòu)中ConcreteElement的每一個類聲明一個Visit操作。該操作的名字和特征標(biāo)識了發(fā)送Visit請求給該訪問者的那個類。這使得訪問者可以確定正被訪問元素的具體的類。這樣訪問者就可以通過該元素的特定接口直接訪問它。
ConcreteVisitor(具體訪問者):實現(xiàn)每個由Visitor聲明的操作。每個操作實現(xiàn)本算法的一部分,而該算法片段乃是對應(yīng)于結(jié)構(gòu)中對象的類。ConcreteVisitor為該算法提供了上下文并存儲它的局部狀態(tài)。這一狀態(tài)常常在遍歷該結(jié)構(gòu)的過程中累積結(jié)果。
Element(元素):定義一個Accept操作,它以一個訪問者為參數(shù)。
ConcreteElement(具體元素):實現(xiàn)Accept操作,該操作以一個訪問者為參數(shù)。
ObjectStructure(對象結(jié)構(gòu)):能夠枚舉它的元素,同時提供一個高層的接口以允許該訪問者訪問它的元素。

使用場合

1.一個對象結(jié)構(gòu)包含很多類對象,它們有不同的接口,而你想對這些對象實施一些依賴于其具體類的操作;
2.需要對一個對象結(jié)構(gòu)中的對象進行很多不同的并且不相關(guān)的操作,而你想避免讓這些操作“污染”這些對象的類。Visitor使得你可以將相關(guān)的操作集中起來定義在一個類中;
3.當(dāng)該對象結(jié)構(gòu)被很多應(yīng)用共享時,用Visitor模式讓每個應(yīng)用僅包含需要用到的操作;
4.定義對象結(jié)構(gòu)的類很少改變,但經(jīng)常需要在此結(jié)構(gòu)上定義新的操作。改變對象結(jié)構(gòu)類需要重定義對所有訪問者的接口,這可能需要很大的代價。如果對象結(jié)構(gòu)類經(jīng)常改變,那么可能還是在這些類中定義這些操作較好。

代碼實現(xiàn)

復(fù)制代碼 代碼如下:

#include <iostream>
#include <vector>
using namespace std;
 
class ConcreteElementA;
class ConcreteElementB;
 
class Visitor
{
public:
     virtual void VisitConcreteElementA(ConcreteElementA *pElementA) = 0;
     virtual void VisitConcreteElementB(ConcreteElementB *pElementB) = 0;
};
 
class ConcreteVisitor1 : public Visitor
{
public:
     void VisitConcreteElementA(ConcreteElementA *pElementA);
     void VisitConcreteElementB(ConcreteElementB *pElementB);
};
 
void ConcreteVisitor1::VisitConcreteElementA(ConcreteElementA *pElementA)
{
     // 現(xiàn)在根據(jù)傳進來的pElementA,可以對ConcreteElementA中的element進行操作
}
 
void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
{
     // 現(xiàn)在根據(jù)傳進來的pElementB,可以對ConcreteElementB中的element進行操作
}
 
class ConcreteVisitor2 : public Visitor
{
public:
     void VisitConcreteElementA(ConcreteElementA *pElementA);
     void VisitConcreteElementB(ConcreteElementB *pElementB);
};
 
void ConcreteVisitor2::VisitConcreteElementA(ConcreteElementA *pElementA)
{
     // ...
}
 
void ConcreteVisitor2::VisitConcreteElementB(ConcreteElementB *pElementB)
{
     // ...
}
 
// Element object
class Element
{
public:
     virtual void Accept(Visitor *pVisitor) = 0;
};
 
class ConcreteElementA : public Element
{
public:
     void Accept(Visitor *pVisitor);
};
 
void ConcreteElementA::Accept(Visitor *pVisitor)
{
     pVisitor->VisitConcreteElementA(this);
}
 
class ConcreteElementB : public Element
{
public:
     void Accept(Visitor *pVisitor);
};
 
void ConcreteElementB::Accept(Visitor *pVisitor)
{
     pVisitor->VisitConcreteElementB(this);
}
 
// ObjectStructure類,能枚舉它的元素,可以提供一個高層的接口以允許訪問者訪問它的元素
class ObjectStructure
{
public:
     void Attach(Element *pElement);
     void Detach(Element *pElement);
     void Accept(Visitor *pVisitor);
 
private:
     vector<Element *> elements;
};
 
void ObjectStructure::Attach(Element *pElement)
{
     elements.push_back(pElement);
}
 
void ObjectStructure::Detach(Element *pElement)
{
     vector<Element *>::iterator it = find(elements.begin(), elements.end(), pElement);
     if (it != elements.end())
     {
          elements.erase(it);
     }
}
 
void ObjectStructure::Accept(Visitor *pVisitor)
{
     // 為每一個element設(shè)置visitor,進行對應(yīng)的操作
     for (vector<Element *>::const_iterator it = elements.begin(); it != elements.end(); ++it)
     {
          (*it)->Accept(pVisitor);
     }
}
 
int main()
{
     ObjectStructure *pObject = new ObjectStructure;
 
     ConcreteElementA *pElementA = new ConcreteElementA;
     ConcreteElementB *pElementB = new ConcreteElementB;
 
     pObject->Attach(pElementA);
     pObject->Attach(pElementB);
 
     ConcreteVisitor1 *pVisitor1 = new ConcreteVisitor1;
     ConcreteVisitor2 *pVisitor2 = new ConcreteVisitor2;
 
     pObject->Accept(pVisitor1);
     pObject->Accept(pVisitor2);
 
     if (pVisitor2) delete pVisitor2;
     if (pVisitor1) delete pVisitor1;
     if (pElementB) delete pElementB;
     if (pElementA) delete pElementA;
     if (pObject) delete pObject;
 
     return 0;
}

總結(jié)

訪問者模式的基本思想如下:首先擁有一個由許多對象構(gòu)成的對象結(jié)構(gòu),就是上面代碼中的ObjectStructure,這些對象的類都擁有一個Accept方法用來接受訪問者對象;訪問者是一個接口,它擁有一個Visit方法,這個方法對訪問到的對象結(jié)構(gòu)中不同類型的元素做出不同的操作;在對象結(jié)構(gòu)的一次訪問過程中,我們遍歷整個對象結(jié)構(gòu),對每一個元素都實施Accept方法,在每一個元素的Accept方法中回調(diào)訪問者的Visit方法,從而使訪問者得以處理對象結(jié)構(gòu)的每一個元素。我們就可以針對對象結(jié)構(gòu)設(shè)計不同的訪問者類來完成不同的操作。

設(shè)計模式中經(jīng)常說的一句話是:發(fā)現(xiàn)變化并封裝之。是否采用訪問者模式,就要看“變化”是什么。訪問者模式中,“變化”是具體訪問者,其次是對象結(jié)構(gòu);但是,如果具體元素也會發(fā)生改變,就萬萬不能使用訪問者模式,因為這樣“牽一發(fā)而動全身”,后期的維護性就太差了。

相關(guān)文章

  • 詳解C語言常用的一些轉(zhuǎn)換工具函數(shù)

    詳解C語言常用的一些轉(zhuǎn)換工具函數(shù)

    這篇文章主要介紹了C語言常用的一些轉(zhuǎn)換工具函數(shù),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-11-11
  • QT 中文亂碼解決匯總(QString與string、char*互轉(zhuǎn)亂碼)

    QT 中文亂碼解決匯總(QString與string、char*互轉(zhuǎn)亂碼)

    在QT中使用中文時,經(jīng)常會碰到論碼問題,本文主要介紹了QT 中文亂碼解決匯總(QString與string、char*互轉(zhuǎn)亂碼),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • C語言函數(shù)超詳細(xì)講解上篇

    C語言函數(shù)超詳細(xì)講解上篇

    函數(shù)是一組一起執(zhí)行一個任務(wù)的語句。每個?C?程序都至少有一個函數(shù),即主函數(shù)?main()?,所有簡單的程序都可以定義其他額外的函數(shù),函數(shù)我們分兩篇來講解,接下來開始第一篇
    2022-04-04
  • C++演講比賽管理系統(tǒng)實現(xiàn)流程實例

    C++演講比賽管理系統(tǒng)實現(xiàn)流程實例

    這篇文章主要介紹了C++演講比賽管理系統(tǒng)實現(xiàn)流程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • 模擬鼠標(biāo)事件的實現(xiàn)思路及代碼

    模擬鼠標(biāo)事件的實現(xiàn)思路及代碼

    這篇文章主要介紹了模擬鼠標(biāo)事件的實現(xiàn)思路及代碼,有需要的朋友可以參考一下
    2013-12-12
  • C語言中的分支循環(huán)其嵌套語句

    C語言中的分支循環(huán)其嵌套語句

    這篇文章主要介紹了C語言中的分支循環(huán)其嵌套語句,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • c++幾種基本的插入排序(圖文)

    c++幾種基本的插入排序(圖文)

    這篇文章主要介紹了c++幾種基本的插入排序(圖文),需要的朋友可以參考下
    2014-11-11
  • 淺談頭文件algorithm中的常用函數(shù)

    淺談頭文件algorithm中的常用函數(shù)

    下面小編就為大家?guī)硪黄獪\談頭文件algorithm中的常用函數(shù)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • C語言大小端字節(jié)序存儲模式深入解讀

    C語言大小端字節(jié)序存儲模式深入解讀

    我們知道,當(dāng)編譯器執(zhí)行 “創(chuàng)建變量” 這一代碼時,會在內(nèi)存中開辟空間相應(yīng)的空間來存儲變量值。而對于整型變量而言,變量值又是以二進制補碼的形式存放的
    2022-09-09
  • C++中默認(rèn)無參構(gòu)造函數(shù)的工作機制淺析

    C++中默認(rèn)無參構(gòu)造函數(shù)的工作機制淺析

    構(gòu)造函數(shù)主要作用在于創(chuàng)建對象時為對象的成員屬性賦值,構(gòu)造函數(shù)由編譯器自動調(diào)用,無須手動調(diào)用;析構(gòu)函數(shù)主要作用在于對象銷毀前系統(tǒng)自動調(diào)用,執(zhí)行一些清理工作
    2023-02-02

最新評論