小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

亂砍設(shè)計(jì)模式之八

 wtf_soft 2006-04-18
BRIDGE模式 —— 所謂伊人,在水一方

junguo

     Bridge模式的中文名稱(chēng)是橋接模式,該模式的目的是將抽象部分和它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立的變化。繼續(xù)以例子來(lái)完成對(duì)該模式的學(xué)習(xí)。

     蒹葭蒼蒼,白露為霜。所謂伊人,在水一方。
     溯洄從之,道阻且長(zhǎng)。溯游從之,宛在水中央。
    
     蒹葭凄凄,白露未晞。所謂伊人,在水之湄。
     溯洄從之,道阻且濟(jì)。溯游從之,宛在水中坻。
    
     蒹葭采采,白露未已。所謂伊人,在水之涘。
     溯洄從之,道阻且右。溯游從之,宛在水中沚。

     這首《蒹葭》取自《詩(shī)經(jīng)》。王國(guó)維在他的《人間詞話》中評(píng)述說(shuō):“《詩(shī)?蒹葭》一篇,最得風(fēng)人深致”。簡(jiǎn)單的場(chǎng)景切換,最直接的感情描寫(xiě),成了千百年來(lái)最能體現(xiàn)詩(shī)人情致的詩(shī)。我感覺(jué)詩(shī)在形式上最重要的是它的語(yǔ)言,簡(jiǎn)單凝練是真正的境界。現(xiàn)今的白話詩(shī),大多被寫(xiě)的晦澀難懂,讀完后佩服詩(shī)人到無(wú)話可說(shuō),寫(xiě)的字都認(rèn)識(shí),但是就不明白放到一塊是什么意思。一直搞不懂為什么要寫(xiě)成那樣?白話文寫(xiě)的詩(shī)歌比古文都難懂很多,有人說(shuō)這是一個(gè)不需要詩(shī)人的時(shí)代,但我想也許是詩(shī)人漂離了時(shí)代,他們也許走到了時(shí)代的前列,但我又覺(jué)得不見(jiàn)得過(guò)多少年后就會(huì)有人愿意花時(shí)間去琢磨晦澀的東西。除了形,就是意了。詩(shī)歌在意上追求境界,應(yīng)該給人遐想的空間。如“有的人死了,他還活著;有的人活者,他已經(jīng)死了”直白到無(wú)任何情趣的詩(shī),也讓人毫無(wú)興趣;但這樣的詩(shī)一度是中國(guó)詩(shī)的主流,而穆旦那樣的優(yōu)秀詩(shī)人則被排擠出了主流,排擠到無(wú)法繼續(xù)寫(xiě)詩(shī)的地步。繼續(xù)說(shuō)《蒹葭》,讀完詩(shī)歌會(huì)感覺(jué)到這樣一個(gè)場(chǎng)景,青山綠水,遠(yuǎn)處隱隱約約一個(gè)少女的身影。近處一個(gè)男子在急切的尋找著船只,眺望著遠(yuǎn)方的路。而他最終沒(méi)找到船,望不到路,焦慮憂(yōu)傷盡顯臉上。也許你會(huì)和我一樣發(fā)現(xiàn),這個(gè)尋路人就是自己。我在想程序是否也有境界,這個(gè)境界又該有什么樣樣的標(biāo)準(zhǔn)呢?
     這樣的詩(shī)歌意境也許可以做成一款游戲。記得上學(xué)的時(shí)候有款游戲《心跳回憶》,類(lèi)似于養(yǎng)成游戲,游戲的內(nèi)容就是玩家通過(guò)不斷的邀請(qǐng)游戲中的美女約會(huì),送禮物給美女等方式來(lái)增加美女對(duì)玩家的好感,好感增加到一定程度,她就會(huì)接受玩家的求婚。很少有人有耐心玩完這款破游戲,但我們同學(xué)中有位仁兄樂(lè)此不疲。考試前幾個(gè)鐘頭還在玩,結(jié)果考后掛了幾科要降級(jí)了。當(dāng)?shù)弥导?jí)的噩耗的時(shí)候,哥們掉了幾顆眼淚,狠狠心又坐到了電腦面前,繼續(xù)他的《心跳回憶》,10多個(gè)小時(shí)過(guò)后,當(dāng)大家還都在夢(mèng)鄉(xiāng)的時(shí)候。他就各個(gè)宿舍游蕩,看到有人醒來(lái)就異常興奮得告訴人家,《心跳回憶》中的女主角他又追到了一個(gè)。降級(jí)的郁悶就這樣被掃空了?,F(xiàn)在,聽(tīng)說(shuō)這位兄弟找到的女朋友很漂亮??吹饺允菃紊淼耐瑢W(xué),也許他該竊笑了:得虧哥們當(dāng)年還練過(guò)。
     我們要實(shí)現(xiàn)的功能沒(méi)有那么復(fù)雜了,此處主要是設(shè)想幫游戲設(shè)計(jì)一個(gè)場(chǎng)景,把青山綠水畫(huà)到屏幕上。由于山可能不只一座,水也可能有多處。我們想把它們封裝成單獨(dú)的類(lèi),由客戶(hù)隨意去組合,組合成不同形狀的圖景。那么我們的類(lèi)圖可以提煉成如下的形式:

     有了類(lèi)圖,我們就可以進(jìn)行開(kāi)發(fā)了。一般來(lái)說(shuō),游戲開(kāi)發(fā)的圖景是寫(xiě)實(shí)性質(zhì)的,類(lèi)似于西方油畫(huà)。但經(jīng)調(diào)查發(fā)現(xiàn),有這么一幫書(shū)呆子,聽(tīng)到“書(shū)中自有顏如玉”的古訓(xùn)后,遍翻古書(shū)尋找美女,后來(lái)發(fā)現(xiàn)不過(guò)癮,想到游戲中尋找自己的夢(mèng)中情人。這批人酷愛(ài)中國(guó)古典文化,重意不重形,喜歡國(guó)畫(huà)上的美女,當(dāng)然山水也應(yīng)該傳統(tǒng)的水墨畫(huà)。為了吸引這批呆子,決定在游戲中提供水墨畫(huà)的場(chǎng)景。這樣我們的類(lèi)也需要進(jìn)行相應(yīng)的變化,它需要支持油畫(huà)和水墨兩種風(fēng)格。想想,我們?cè)撊绾螌?shí)現(xiàn)這一功能呢?最直接想到的就是通過(guò)繼承來(lái)實(shí)現(xiàn),那么我們的類(lèi)圖可能變成這樣。

     圖中我們幫油畫(huà)和水墨都提供了接口,而山水則分別通過(guò)油畫(huà)和水墨來(lái)繼承。這樣明顯的問(wèn)題是,我們需要為山水各提供兩套代碼。有這個(gè)必要嗎?只是造圖風(fēng)格上不同,但過(guò)程是一樣的。接著想,如果我們新添加一個(gè)新場(chǎng)景進(jìn)來(lái),比如說(shuō)天空和陸地,也需要單獨(dú)的類(lèi)來(lái)實(shí)現(xiàn)。那么這時(shí)候我們又要為每個(gè)場(chǎng)景添加兩個(gè)類(lèi)。接著想,后來(lái)發(fā)現(xiàn),有哥們喜歡后印象主義畫(huà)派,還有哥們喜歡抽象主義(寫(xiě)完后,想想了,發(fā)現(xiàn)抽象主義還是比較容易實(shí)現(xiàn)的,畫(huà)個(gè)三角形代表山,畫(huà)兩個(gè)弧線代表水,只要顏色取絢了就是抽象作品了),那么再把這些風(fēng)格都加入到該模式中,會(huì)發(fā)生什么情形呢?完了,已經(jīng)實(shí)現(xiàn)過(guò)的山水類(lèi)都需要重新實(shí)現(xiàn)一次。接著想,客戶(hù)端調(diào)用又會(huì)有什么情形呢?好多類(lèi)啊,該選哪個(gè)呢?當(dāng)然你也可以幫他實(shí)現(xiàn)一個(gè)抽象工廠來(lái)減輕負(fù)擔(dān),但這個(gè)工廠的實(shí)現(xiàn)一樣煩瑣??吹搅诉@么多問(wèn)題,其實(shí)總結(jié)起來(lái)原因就是一個(gè),通過(guò)繼承我們把風(fēng)格和具體的實(shí)物(山,水等)固定到了一起,無(wú)法抽離出來(lái),導(dǎo)致了類(lèi)的膨脹。那么該如何解決這個(gè)問(wèn)題呢?方法就是把這兩樣?xùn)|西給分離出來(lái),讓它們各自實(shí)現(xiàn)各自的代碼。怎么實(shí)現(xiàn)呢?來(lái)看類(lèi)圖:

     我們把不同風(fēng)格給分離了出來(lái)。它們有一個(gè)基類(lèi)Img,主要用來(lái)實(shí)現(xiàn)基本的畫(huà)圖功能,比如畫(huà)線,畫(huà)圈等內(nèi)容(我們這邊只簡(jiǎn)單列出了畫(huà)垂直線和水平線)。而我們的場(chǎng)景也是一個(gè)單獨(dú)的類(lèi),在這些類(lèi)中調(diào)用Img接口提供的基本畫(huà)圖功能來(lái)實(shí)現(xiàn)不同的圖形。抽象出來(lái)后,我們?cè)倩仡^看上面提到的問(wèn)題。假如我們添加一個(gè)具體的實(shí)物進(jìn)來(lái),比如說(shuō)要添加天空進(jìn)來(lái),那么我們只要添加一個(gè)類(lèi)就好了,只要調(diào)用保證它調(diào)用Img接口來(lái)實(shí)現(xiàn)就可以有不同的風(fēng)格了。如果需要添加另一種風(fēng)格進(jìn)來(lái),如后印象主義風(fēng)格,那我們也不需要改變?cè)械念?lèi),只要先添加一個(gè)類(lèi)進(jìn)來(lái)就好了。擴(kuò)展是不是方便了很多?還是來(lái)看看模擬的代碼(簡(jiǎn)陋了些,我只能用文字表達(dá)表達(dá)了),先來(lái)看看風(fēng)格類(lèi)所需要的代碼:
//風(fēng)格接口
class Img
{
public:
//畫(huà)水平線
virtual void DrawHorLine() = 0;
//畫(huà)垂直線
virtual void DrawVerLine() = 0;
protected:
Img(){}
};
//中國(guó)畫(huà)風(fēng)格
class ChineseImg : public Img
{
public:
void DrawHorLine()
{
cout << "水墨畫(huà)水平線" << endl;
}
void DrawVerLine()
{
cout << "水墨畫(huà)垂直線" << endl;
}
};
//油畫(huà)風(fēng)格
class CanvasImg : public Img
{
public:
void DrawHorLine()
{
cout << "油畫(huà)水平線" << endl;
}
void DrawVerLine()
{
cout << "油畫(huà)垂直線" << endl;
}
};

    這邊要實(shí)現(xiàn)的功能其實(shí)就是提供畫(huà)圖的基本方法,比如畫(huà)線或者畫(huà)圓等動(dòng)作(我不太清楚,現(xiàn)在圖形庫(kù)能不能幫我們實(shí)現(xiàn)水墨畫(huà)風(fēng)格的圖形,但我想將來(lái)應(yīng)該可以的)。我們這里的代碼比較簡(jiǎn)單,不做太多的解釋。接著看看實(shí)體類(lèi)的實(shí)現(xiàn)。
//場(chǎng)景抽象類(lèi)
class Scene
{
public:
virtual void DrawBorder() = 0;
Img *GetImg()
{
return m_pImg;
}
virtual ~Scene()
{
delete m_pImg;
}
protected:
Scene()
{
//此處的原因,文章里分析
m_pImg = new CanvasImg();
}
private:
//擁有一個(gè)Img的指針,通過(guò)它來(lái)調(diào)用畫(huà)圖功能
Img *m_pImg;
};
//山的類(lèi)
class Hill : public Scene
{
public:
void DrawBorder()
{
DrawHill();
}
void DrawHill()
{
cout << "三條垂直線就代表山了!" << endl;
Img *pImg = GetImg();
pImg->DrawVerLine();
pImg->DrawVerLine();
pImg->DrawVerLine();
}
};
//水的類(lèi)
class Water : public Scene
{
public:
void DrawBorder()
{
DrawWater();
}
void DrawWater()
{
cout << "三條水平線就代表水了!" << endl;
Img *pImg = GetImg();
pImg->DrawVerLine();
pImg->DrawVerLine();
pImg->DrawVerLine();
}
};

     首先注意到一點(diǎn),就是Scene的構(gòu)造函數(shù)的實(shí)現(xiàn)中有這樣的語(yǔ)句:“m_pImg = new CanvasImg()”,而且Scene類(lèi)中沒(méi)有改邊m_pImg的方法,這樣做的原因是因?yàn)橐话銇?lái)說(shuō)Bridge是對(duì)于整個(gè)程序風(fēng)格的設(shè)置。你配置了什么樣的風(fēng)格,整個(gè)程序運(yùn)行的過(guò)程中風(fēng)格就是什么。因?yàn)橐话銇?lái)說(shuō)Bridge主要是適用于跨平臺(tái)的開(kāi)發(fā),在Linux中與在Windows中,畫(huà)圖的方法肯定不相同,通過(guò)Bridege可以解決這個(gè)問(wèn)題,但在運(yùn)行過(guò)程中肯定不應(yīng)該改變Bridge的類(lèi)型??梢酝ㄟ^(guò)配置文件來(lái)實(shí)現(xiàn),這樣的話,在m_pImg生成的地方通過(guò)讀取配置文件,根據(jù)文件類(lèi)型來(lái)創(chuàng)建m_pImg就好了。當(dāng)然你想在運(yùn)行過(guò)程中改變m_pImg類(lèi)型也可以,看具體情況了。再看看調(diào)用:
int main(int argc, char* argv[])
{
Hill h;
Water w;
h.DrawBorder();
w.DrawBorder();
return 0;
}

    通過(guò)創(chuàng)建的Hill或者Water類(lèi)去畫(huà)圖就可以了。
    我們?cè)賮?lái)看看Bridge的定義:將抽象部分和它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立的變化。其實(shí)這里的抽象用的并不貼切,但想不到太好的詞,人類(lèi)語(yǔ)言的表達(dá)能力是有限的。這里所說(shuō)的抽象,并不是我們所說(shuō)的接口的抽象。在例子里抽象指的就是Img及其子類(lèi)了,用來(lái)畫(huà)圖的對(duì)象。而實(shí)現(xiàn)部分指的就是我們的Hill和Water類(lèi)了。
    Bridge看完了,是不是感覺(jué)有些眼熟呢?你是不是和我一樣遲鈍,想半天,還需要翻看書(shū)才想起來(lái)?回憶一下我們之前談過(guò)的策略模式,看看類(lèi)圖。兩個(gè)模式不僅相似,而且相似的令人發(fā)指,完全是一樣的。但為什么會(huì)被劃成兩個(gè)模式呢?其實(shí)主要是它們要解決的問(wèn)題不相同,策略模式針對(duì)的是類(lèi)中所屬的單個(gè)對(duì)象或者單個(gè)方法,由于這樣的對(duì)象或者方法會(huì)有不同的實(shí)現(xiàn)方法,可能需要運(yùn)行時(shí)刻動(dòng)態(tài)改變。那么我們可以用策略模式來(lái)改變這樣的功能。而B(niǎo)ridge針對(duì)的是整個(gè)類(lèi),根據(jù)不同的Bridge,整個(gè)類(lèi)的風(fēng)格將發(fā)生變化。也可以這樣理解策略模式針對(duì)的是類(lèi)中單個(gè)對(duì)象,這個(gè)對(duì)象可能影響到類(lèi)中少數(shù)的幾個(gè)函數(shù)。而B(niǎo)ridge模式,將影響到類(lèi)中決大多數(shù)的方法。
參考書(shū)目:
1,	設(shè)計(jì)模式——可復(fù)用面向?qū)ο筌浖幕A(chǔ)(Design Patterns ——Elements of Reusable Object-Oriented Software) Erich Gamma 等著 李英軍等譯  機(jī)械工業(yè)出版社
2,	Head First Design Patterns(影印版)Freeman等著 東南大學(xué)出版社
3,	道法自然——面向?qū)ο髮?shí)踐指南    王詠武 王詠剛著  電子工業(yè)出版社
4,      人間詞話手稿本      王國(guó)維 著 吳洋注釋 內(nèi)蒙古出版社

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多