亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++設計模式之訪問者模式

2020-01-26 15:15:43
字體:
來源:轉載
供稿:網友

前言

這是23+1(簡單工廠模式)之中的最后一個了――訪問者模式。訪問者模式也是一個比較麻煩的設計模式。我也沒有實戰經驗,對于訪問者模式的理解完全來自GOF的《設計模式:可復用面向對象軟件的基礎》,而這篇文章就是根據對這本書的理解而寫出來的。在讀《設計模式:可復用面向對象軟件的基礎》的時候,讓我想起自己做過的一個項目,該項目雖然沒有使用訪問者模式,但是,今天理解了該模式,如果使用該模式對之前做過的項目進行重構,將是一個不錯的想法。

訪問者模式

在GOF的《設計模式:可復用面向對象軟件的基礎》一書中對訪問者模式是這樣說的:表示一個作用于某對象結構中的各元素的操作。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。訪問者模式把數據結構和作用于結構上的操作之間的耦合解脫開,使得操作集合可以相對自由地演化。該模式的目的是要把處理從數據結構分離出來。訪問者模式讓增加新的操作很容易,因為增加新的操作就意味著增加一個新的訪問者。訪問者模式將有關的行為集中到一個訪問者對象中。現在再來說說我之前經歷過的那個項目。

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

UML類圖

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

使用場合

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

代碼實現

復制代碼 代碼如下:

#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)
{
     // 現在根據傳進來的pElementA,可以對ConcreteElementA中的element進行操作
}
 
void ConcreteVisitor1::VisitConcreteElementB(ConcreteElementB *pElementB)
{
     // 現在根據傳進來的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設置visitor,進行對應的操作
     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;
}

總結

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

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人网中文字幕| 热re99久久精品国产66热| 成人精品久久一区二区三区| 国产精品福利在线| 亚洲一区国产精品| 青青久久av北条麻妃黑人| 久久久久久久av| 疯狂做受xxxx高潮欧美日本| 欧美肥老妇视频| 亚洲91精品在线观看| 日韩a**站在线观看| 国产精品久久久久久久久久小说| 久久久在线免费观看| 一二美女精品欧洲| 成人欧美在线视频| 一区二区三区亚洲| 欧美精品久久一区二区| 亚洲一区二区精品| 欧洲亚洲免费在线| 日韩av色综合| 国产精品久久99久久| 日韩免费观看网站| 国产成人综合亚洲| 国产亚洲欧美一区| 日韩免费观看网站| 亚洲欧美激情另类校园| 91精品免费看| 亚洲欧美日韩精品| 亚洲精品在线视频| 国产精品毛片a∨一区二区三区|国| 国内伊人久久久久久网站视频| 国产亚洲精品久久久久久777| 亚洲第一网站免费视频| 亚洲天堂免费观看| 中文字幕亚洲图片| 这里只有精品丝袜| 欧美自拍大量在线观看| 久久亚洲精品中文字幕冲田杏梨| 国产精品高精视频免费| 午夜精品久久久久久久久久久久| 2021国产精品视频| 欧美午夜久久久| 久久综合电影一区| 在线播放国产一区二区三区| 成人免费网站在线| 久久精品色欧美aⅴ一区二区| 日本国产一区二区三区| 亚洲精品99999| 国产精品三级久久久久久电影| 亚洲欧美福利视频| 91av福利视频| 91av视频在线播放| 欧美性videos高清精品| 欧美在线日韩在线| 欧美日韩国产色视频| 国产视频精品va久久久久久| 欧美自拍视频在线| 国产精品jizz在线观看麻豆| 欧美精品久久久久久久久久| 萌白酱国产一区二区| 日韩在线国产精品| 国产一区二区黄| 久久五月天色综合| 国产成人涩涩涩视频在线观看| 久久久久久久97| 国产不卡av在线免费观看| 欧美激情视频播放| 国产日韩专区在线| 日韩在线观看免费全集电视剧网站| 日韩中文视频免费在线观看| 国产va免费精品高清在线观看| 岛国视频午夜一区免费在线观看| 欧美午夜性色大片在线观看| 国产xxx69麻豆国语对白| 97视频网站入口| 亚洲第一精品夜夜躁人人爽| 欧美精品18videosex性欧美| 狠狠色狠狠色综合日日五| xx视频.9999.com| 亚洲男女性事视频| 岛国精品视频在线播放| 国产日韩欧美中文在线播放| 亚洲毛片一区二区| 欧美日韩福利电影| 欧美日韩aaaa| 91精品国产自产在线观看永久| 青青在线视频一区二区三区| 欧美疯狂xxxx大交乱88av| 久久久久久国产精品三级玉女聊斋| 成人妇女免费播放久久久| 久久久免费在线观看| 国产91精品青草社区| 日韩精品黄色网| 日韩精品在线免费播放| 亚洲欧美一区二区精品久久久| 日韩视频欧美视频| 久久久精品欧美| 成人国内精品久久久久一区| 国模精品一区二区三区色天香| 欧美激情视频在线免费观看 欧美视频免费一| 国产拍精品一二三| 96精品久久久久中文字幕| 亚洲男子天堂网| 日韩成人激情影院| 国产精自产拍久久久久久蜜| 欧美成人精品不卡视频在线观看| 亚洲摸下面视频| 大量国产精品视频| 国产91精品黑色丝袜高跟鞋| 欧美午夜激情小视频| 中文字幕日韩av电影| 亚洲第一男人天堂| 久久综合88中文色鬼| 亚洲一区二区久久| 日韩麻豆第一页| 久久久久久久香蕉网| 日韩电影免费在线观看| 欧美激情二区三区| 狠狠久久五月精品中文字幕| 中文字幕在线视频日韩| 97在线视频免费看| 精品久久久久久| 亚洲国产一区二区三区四区| 搡老女人一区二区三区视频tv| 日韩免费电影在线观看| 国产欧美日韩中文| 欧美激情一区二区三区高清视频| 日韩在线视频国产| 91久久久久久久久| 欧美在线欧美在线| 国产一区二区三区视频在线观看| 亚洲va欧美va国产综合久久| 4p变态网欧美系列| 国产一区二区日韩| 4388成人网| 亚洲成人久久电影| 4438全国亚洲精品在线观看视频| 亚洲国产日韩欧美在线图片| 亚洲的天堂在线中文字幕| 精品一区二区三区四区在线| 欧美大尺度电影在线观看| 国产精品美女www| 欧美日韩国产丝袜美女| 国产精品成人一区二区| 琪琪第一精品导航| 亚洲国产一区二区三区四区| 一区二区三区国产在线观看| 欧美一级黑人aaaaaaa做受| 夜夜躁日日躁狠狠久久88av| 一区二区欧美日韩视频| 国产精品黄视频| 日韩在线观看av| 欧美激情aaaa| 国产不卡av在线免费观看| 亚洲视频在线观看视频| 日韩最新免费不卡| 精品中文字幕在线观看| 97欧美精品一区二区三区| 欧美人与物videos| 欧美极品美女视频网站在线观看免费| 亚洲欧美国产精品va在线观看| 日韩a**中文字幕| 精品国内自产拍在线观看| 午夜精品国产精品大乳美女|