<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    子在川上曰

      逝者如斯夫不舍晝夜
    隨筆 - 71, 文章 - 0, 評論 - 915, 引用 - 0
    數(shù)據(jù)加載中……

    一個體現(xiàn)Java接口及工廠模式優(yōu)點的例子

    原2004年初發(fā)于CSDN,后圖片丟失,現(xiàn)補上。陳剛 from www.chengang.com.cn


    ???? 隨著模式概念的普及,了解模式和使用模式的程序員越來越多,很多人在學(xué)習(xí)模式的時候,都會有這樣一種疑惑:“有必要搞得這么復(fù)雜嗎?”。的確,因為教程的例子過于簡單化(這樣方便讀者學(xué)習(xí)),或者是作者選例子的時候并沒有很好體現(xiàn)所講模式的優(yōu)點,很多情況下如果僅就其例子的問題來說,用模式是太復(fù)雜了。因此才導(dǎo)致這樣的誤解:“模式就是把簡單的問題復(fù)雜化嗎?”。當(dāng)然不是,隨著你開發(fā)實踐的不斷豐富,你終會發(fā)現(xiàn)模式強大威力,而且模式也并非貴族化的編程方式,它就是一些經(jīng)過提煉了的解決問題的方法技巧。
    ?
    ????? 通過學(xué)習(xí)模式,程序員開始告別過去準(zhǔn)直線式的代碼方式,模式開擴了我們的視野,強化了我們面向?qū)ο缶幊痰乃季S方式。然而現(xiàn)在又出現(xiàn)了另一個普遍的問題,盲目應(yīng)用模式。模式是問題的解決方案,先有問題才有模式,模式是依附于所要解決的問題的而生的。必須了解模式在很多情況下是以提高代碼的復(fù)雜度為代價來增強靈活性、可復(fù)用性。如果在自已的代碼中使用某一模式僅只提高了代碼的復(fù)雜度,而其它方面收效甚微,或者某部份代碼根本就不存在靈活性及高復(fù)用性的需求,那么我們就沒有必要為使用模式而放棄更直觀簡單的代碼寫法。
    ?
    ????? 一流的高手90%精力關(guān)注問題的解決方案,因為找到了好的解決方案,再寫起代碼會很輕松代碼也簡潔流暢,看這樣的代碼是一種享受和提高;二流的熟手90%精力關(guān)注代碼實現(xiàn),因為問題的解決方案并非最佳,實現(xiàn)的代碼也會比較復(fù)雜;三流菜鳥記流水帳,90%精力在敲鍵盤,常常做了大半才發(fā)現(xiàn)行不通,回過頭來再用90%的時間敲鍵盤,根本不會用到任何模式,寫出來的代碼的只有他自已才能看懂。做出來的軟件也是支離破碎,做一丁點改動都要大費周折,而且你還不知道改動后會產(chǎn)生什么問題,大有住危房里的感覺。
    ?
    ????? 在這里還是舉一個濫用模式的例子吧。我曾參與過一個大集團公司OA系統(tǒng)的第二期開發(fā),開發(fā)沿用原有代碼架構(gòu)并增加新的功能模塊。文檔很少我讀原代碼時就被它程序里的代碼轉(zhuǎn)來轉(zhuǎn)去搞得頭大如斗,最后讀懂了:原代碼架構(gòu)總體采用工廠模式,而且是最復(fù)雜的抽象工廠模式。它把所有模塊類都通過工廠生成還工廠套工廠,并且每一個模塊類都有一個接口,每個接口也只有一個模塊現(xiàn)實類,因為涉及權(quán)限控制還用了代理(proxy)模式。 讀懂代碼后我開始嵌入代碼,發(fā)現(xiàn)每新增一個類,都要到六個Java文件中去增加相應(yīng)代碼,而在類中每增加一個方法,也要到它的接口等四個Java文件中去增加相應(yīng)代碼。天呀!!!記得當(dāng)時我的小姆指常會不聽使喚,就是因為頻繁的使用Ctrl+C 、Ctrl+V,小姆指按著Ctrl鍵給累的。整個項目組苦不堪言,真煩透了。項目結(jié)束后我回顧發(fā)現(xiàn):代理模式用得還對(現(xiàn)在針對權(quán)限這類橫向控制有AOP編程這種新的解決辦法了)但工廠模式在這里根本就是畫蛇添足,不僅沒有解決什么問題,反而增加代碼復(fù)雜度和耦合性,降低了開發(fā)效率連維護難度都提高了。而且那種每個類簡單的加一個接口的方式,更是沒有道理,這讓我很想說周星馳說過的一句話:“球~~~不是這么踢~~~~的,接口~~~不是這么用~~~的”。言歸正傳,我們先來看這樣一個常見問題:某系統(tǒng)需要支持多種類型的數(shù)據(jù)庫。用過Oracle、MSSQL等數(shù)據(jù)庫的人都知道,它們的SQL編寫方式都各有些不同。比如說Oracle的唯一標(biāo)識自動+1字段用的是序列,MSSQL改一下字段屬性就成了,還有各種各自特有的SQL用法。為了支持多數(shù)據(jù)庫,難道我們要開發(fā)多套系統(tǒng)?當(dāng)然NO。請看下面的解決方案。
    ?
    ????? 即然數(shù)據(jù)庫存在多種,我們可以將系統(tǒng)中所有對數(shù)據(jù)庫的操作抽象出來,寫成一個個方法組合到一個類中,有幾種數(shù)據(jù)庫我們就寫幾個這樣的類。具體設(shè)計類圖如下:
    20060910.gif
    ?
    ?
    簡要說明:
    • OracleDataOperate、SqlserverDataOperate、MysqlDataOperate,分別代表Oracle、Sqlserver、Mysql這三種數(shù)據(jù)庫的操作類。繼承自AbstractDataOperate
    • AbstractDataOperate是一個抽象類,包含了那些不同種類數(shù)據(jù)庫都是一樣代碼的操作方法。繼承自DataOperate
    • DataOperate是上面說的數(shù)據(jù)操作類的統(tǒng)一接口,只有兩個方法:取得一條記錄、插入一條記錄。
    • DataOperateFactory是一個工廠方法,統(tǒng)一用它的方法來得到數(shù)據(jù)庫操作類的實例。
    • SampleClass是我們系統(tǒng)的某個功能模塊的類。
    • People是一個實體類,代表一條記錄。三個字段 oid唯一標(biāo)識符、name姓名、date生日。
    ?
    詳細(xì)說明:
    1、所有系統(tǒng)功能模塊類只認(rèn)DataOperat這個接口還不必管具體的實現(xiàn)類是OracleDataOperate還SqlserverDataOperate。DataOperate源代碼如下:
    publicinterface DataOperate {
    ??? //根據(jù)記錄的唯一標(biāo)識取出一條記錄
    ??? People getPeople(String oid);
    ??? //插入一條記錄
    ??? boolean insertPeople(People people);
    }
    ?
    2、AbstractDataOperate、OracleDataOperate、SqlserverDataOperate、MysqlDataOperate都是繼承DataOperate接口的,沒什么好說的,省略。
    ?
    3、DataOperateFactory。我們看看工廠方法怎么寫的。
    publicclass DataOperateFactory {
    ??? publicstaticfinalint ORACLE = 0; //定義三個表示數(shù)據(jù)庫類型的常量
    ??? publicstaticfinalint MYSQL = 1;
    ??? publicstaticfinalint SQLSERVER = 2;
    ?
    ??? privatestatic DataOperate db;
    ??? privatestaticint dataType = MYSQL;
    ??? /**
    ??? ?* 根據(jù)數(shù)據(jù)庫類型(dataType)取得一個數(shù)據(jù)庫操作類的實例,
    ??? ?* 這里對DataOperate使用了單例模式,因為OracelDataOperate等都是無狀態(tài)的工具類,
    ??? ?* 所以整個系統(tǒng)只保留一個實例就行了。
    ??? ?*
    ??? ?* @return 返回的是接口,客戶端不必關(guān)心具體是用那個實現(xiàn)類
    ??? ?*/
    ??? publicstatic DataOperate getInstance() {
    ??????? if (db == null) {
    ??????????? if (dataType == ORACLE) //根據(jù)dateType返回相應(yīng)的實現(xiàn)類
    ??????????????? returnnew OracelDataOperate();
    ??????????? if (dataType == MYSQL)
    ??????????????? returnnew MysqlDataOperate();
    ??????????? if (dataType == SQLSERVER)
    ??????????????? returnnew SqlserverDataOperate();
    ??????? }
    ??????? return db;
    ??? }
    }
    ?
    4、接下來就看看使用端是如何調(diào)用工廠方法和使用數(shù)據(jù)操作類的。
    /**
    ?* 系統(tǒng)某個功能類
    ?*/
    publicclass SampleClass {
    private DataOperate db; //聲明一個數(shù)據(jù)庫操作類,注意這里用的是接口噢
    ??? /**某方法*/
    ??? publicvoid sampleMethod() {
    ??????? db = DataOperateFactory.getInstance();//得到單一實例
    ??????? People p = db.getPeople("123"); //取得一條記錄
    ??????? db.insertPeople(p);//再插回去
    ??? }
    }
    ?
      我們發(fā)現(xiàn)SampleClass中根本沒有出現(xiàn)OracelDataOperate、MysqlDataOperate等的影子,這就是接口的威力。客戶端不必針對OracelDataOperate等寫不同的代碼,它只關(guān)心DataOperate即可,具體要取那個類的邏輯就由DataOperateFactory負(fù)責(zé)了。
    ?
    總結(jié):
    • 從例子中我們可以看到什么是面向接口的編程方式。SampleClass使用數(shù)據(jù)操作類可以不必關(guān)心具體是那個類,只要是符合接口的都行
    • 要實例?只須調(diào)用DataOperateFactory.getInstance()即可,其它的交于DataOperateFactory這個工廠來做吧,使用端什么都不用關(guān)心。
    • 我們要支持新的數(shù)據(jù)庫類型,只須要象OracelDataOperate那樣,再寫一個繼承AbstractDataOperate的類即可,比如SysbaseDataOperate。然后到DataOperateFactory中加入相應(yīng)代碼即可。
    • 如果我們想要可配置性更高,可以用privatestaticint dataType = MYSQL;中的值設(shè)置到一個文本文件中。
      對于開發(fā)支持多種數(shù)據(jù)庫的系統(tǒng),強烈建議使用hibernate,我現(xiàn)在做的系統(tǒng)就是用hibernate的,開發(fā)時用Mysql,到要給客戶時將數(shù)據(jù)庫換了DB2,程序不用做任何改動,真正的無逢移植。不過這樣,本文所提到的方法就沒什么用了.

    posted on 2006-09-10 17:47 陳剛 閱讀(3235) 評論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 在线免费观看一级片| 婷婷精品国产亚洲AV麻豆不片 | 亚洲在成人网在线看| 日本a级片免费看| 中文字幕在线免费观看视频| 亚洲欧洲精品一区二区三区| 国产jizzjizz免费看jizz| 亚洲免费观看视频| 亚洲人成网站在线播放2019| 亚洲综合另类小说色区| 我们的2018在线观看免费高清 | 欧洲人免费视频网站在线| 在线精品亚洲一区二区| 亚洲色欲久久久综合网东京热 | 久久精品国产精品亚洲艾草网| 两性刺激生活片免费视频| WWW国产成人免费观看视频| 亚洲av无码片在线观看| 亚洲一区二区三区香蕉| 色吊丝最新永久免费观看网站| a毛片在线还看免费网站| 亚洲a∨无码精品色午夜| 亚洲综合一区二区精品导航| 亚洲&#228;v永久无码精品天堂久久 | 精品韩国亚洲av无码不卡区| 亚洲综合一区二区精品导航| 亚洲黄片毛片在线观看| 成人午夜免费福利| 日韩人妻无码精品久久免费一| www亚洲精品久久久乳| 亚洲依依成人精品| 久久亚洲国产成人亚| 亚洲国产成人精品女人久久久| 国产精品69白浆在线观看免费| 毛片在线全部免费观看| 牛牛在线精品观看免费正| 亚洲日本VA中文字幕久久道具| 亚洲美女色在线欧洲美女| 亚洲精品国产精品乱码不99 | 亚洲一区二区三区免费观看| 亚洲国产香蕉碰碰人人|