爲方便讀者,本文已添加至索引:html
「魔鏡啊魔鏡,誰是這個世界上最美麗的人?」 每到晚上,女王都會問魔鏡相同的問題(見Decorator模式)。這是她還曾身爲女巫時留下的習慣。儘管要提及這個心裏邪惡的女巫,將會有一大堆故事,但咱們今天要討論的主角,倒是這面神奇的鏡子。關於魔鏡的來歷,誰都不是很清楚。就連這個世界的創造者魔導士(見Builder模式)也對它的存在感到好奇。魔鏡可以迴應主人的訴求,回答主人所提出的問題,並透過鏡子來提示答案相關的信息。咱們能夠經過時の魔導士的研究手札來依稀瞭解下這個神祕的魔法造物。程序員
「這面魔鏡能夠顯現出我所創造的這個世界中任何的物體,這頗有趣。」設計模式
「……可是它彷佛也僅僅是提供了一種受限制的訪問對象的方式,由於我不能經過它直接接觸到對象自己。」函數
「……它也僅在我須要的時候纔會顯示出對應的物體,我相信它並不是從誕生之時就存儲好了世界上全部物體的影像。」學習
「……魔鏡在顯示答案時更像是一種採用了Proxy模式的造物。」優化
是的,他提到了Proxy(代理),一種設計模式。在繼續深刻研究魔鏡以前,咱們先來了解下Proxy的大體內容。ui
爲了更加深刻地瞭解魔鏡,咱們先回顧一個知識點:在Decorator模式筆記中,咱們瞭解到一個全部可見物體的抽象類VisualObject。從鏡子之中,咱們能夠看到某個對象的影像Image:
spa
1 class Image : public VisualObject { 2 public: 3 Image(string name); // load an image. 4 virtual ~Image(); 5 6 virtual void show(); 7 }
然而透過魔鏡,咱們能夠看到任何想看東西的Image。如前文所述,不可能讓魔鏡在一開始就把全部的Image都實例化。(換成咱們程序員的思惟,就是會形成存儲開銷過於巨大),怎麼辦?Proxy模式給出了一種解決策略。讓咱們看看所謂的ImageProxyMagic吧:設計
1 class ImageProxyMagic : public VisualObject { 2 public: 3 ImageProxyMagic(string name); // Just save the name. 4 virtual ~Image(); 5 6 virtual void show(); 7 protected: 8 Image* getImage(); 9 private: 10 string _name; 11 Image* _image; 12 }
誒,有沒有發現它對外的接口和Image相同?是的,這樣一來咱們就能夠像操做Image同樣,操做ImageProxyMagic了。可是具體它又作了什麼?看看代碼吧:代理
1 ImageProxyMagic::ImageProxyMagic(string name) { 2 _name = name; 3 _image = 0; 4 } 5 6 Image* ImageProxyMagic::getImage() { 7 if (!_image) { 8 _image = new Image(_name); 9 } 10 return _image; 11 } 12 13 void ImageProxyMagic::show() { 14 getImage()->show(); 15 }
注意到,構造函數存儲了Image的名字,而將Image的裝載過程延緩到getImage函數當中。於是,只有在某個Image真正須要show出來的時候,它纔會被裝載。ImageProxyMagic將show命令轉發給Image處理。
儘管如此,咱們仍是不瞭解魔鏡爲何會知道問題的答案,咱們僅僅看到的它在展現答案時候的一個可能處理方式。咱們不由想對它提出這樣一個問題:
「魔鏡啊魔鏡,你爲何無所不知?」
使用Proxy模式在訪問對象時引入了必定程度的間接性。根據代理的類型,附加的間接性也有多種用途:
Proxy模式並不老是須要知道實體的類型。若是Proxy類可以徹底經過一個抽象接口處理它的實體,則無須爲每個RealSubject類都生成一個Proxy類;但若是Proxy要實例化RealSubject的話,(好比咱們的例子中)那它必須知道具體的類。
今天的筆記就到這裏了,歡迎你們批評指正!若是以爲能夠的話,好文推薦一下,我會很是感謝的!