我的隱式生活(My Implicit Life)

          繼續(xù)搞“對(duì)象”,玩OO.

          首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            11 Posts :: 1 Stories :: 39 Comments :: 0 Trackbacks

          廢話:

          預(yù)料中的日志3暫時(shí)生產(chǎn)不出來(lái),話說(shuō)難產(chǎn)就好,別夭折就行,有點(diǎn)掉價(jià)哦,呵呵。

           

          因?yàn)橛行〇|西還沒(méi)有想清楚。那就先搞個(gè)四吧,這個(gè)東西還是清楚那么一點(diǎn)的。

          一版描述:

          項(xiàng)目需求

          使每個(gè)servlet能對(duì)用戶訪問(wèn)權(quán)限進(jìn)行檢查。簡(jiǎn)單來(lái)說(shuō),就是要給每個(gè)servlet加個(gè)鎖,有鑰匙的用戶才能訪問(wèn)。

           

          而項(xiàng)目中用戶所謂的訪問(wèn)權(quán)限是基于他擁有的角色。也就是說(shuō),servlet對(duì)用戶訪問(wèn)權(quán)限的檢查,就是對(duì)他所擁有角色的檢查。暫時(shí),每個(gè)用戶只能擁有一個(gè)角色。

           

          項(xiàng)目的角色很多,但是在web端暫時(shí)只有如下的三種:

           

          項(xiàng)目暫時(shí)角色

          游客,學(xué)生,教師

           

          既然這樣,servlet的加鎖方式就有:

           

          servlet加鎖方式

           游客,學(xué)生,教師,
          游客或?qū)W生,游客或教師,學(xué)生或教師,
          游客或?qū)W生或教師

           注:上面的“游客”就是“游客角色有權(quán)訪問(wèn)”的意思,依此類推。

           

          這里只有關(guān)系“或”(||),如果一個(gè)servlet的加鎖方式是“學(xué)生或教師”,也就是說(shuō)擁有學(xué)生或教師角色的用戶都可以訪問(wèn)它。關(guān)系“與”(&&)在這里不太可能存在,因?yàn)闆](méi)有需求說(shuō):某個(gè)servlet一定只能由“既是學(xué)生又是教師的用戶”才能訪問(wèn),而且前面也說(shuō)了,暫時(shí)一個(gè)用戶“有且只有”一個(gè)角色。

           

          So we can get following function


          “加鎖方式數(shù)” = 2的“角色數(shù)”次方 - 1


          “加鎖方式數(shù)”是關(guān)于“角色數(shù)”的指數(shù)函數(shù),也就是說(shuō)它是關(guān)于“角色數(shù)”成“指數(shù)級(jí)”增長(zhǎng)的,應(yīng)該說(shuō)很快了吧。


          3
          個(gè)角色就有23次方-1個(gè),也就是7個(gè)加鎖方式。

           

          運(yùn)用OO的最基本方式,就是封裝對(duì)象。既然有為servlet“看門”的責(zé)任,那就把這個(gè)責(zé)任封裝成一個(gè)對(duì)象,用個(gè)俗名:validator

           

          接著,運(yùn)用共性和個(gè)性的分析方法,既然有那么多種不同的看門方式(加鎖方式),那就搞一個(gè)接口,然后讓各種“不同”都實(shí)現(xiàn)這個(gè)接口,形成子類。那就有下面的圖:

          o_4-1.JPG

          可以看到,由于有7個(gè)加鎖方式,那就要有7個(gè)子類。每個(gè)子類根據(jù)自己邏輯override接口的validate方法。

           

          這樣,對(duì)于一個(gè)servlet,想讓它上什么樣的鎖,只要讓它拿到對(duì)應(yīng)的子類的引用即可,如下圖中的ClientServlet,我們規(guī)定只能有“學(xué)生或教師”才能訪問(wèn)它。它的部分代碼便是:


          o_4-2.JPG

           

           

          1//new對(duì)應(yīng)的Validator接口的子類。
          2//這里是學(xué)生或教師可訪問(wèn),因此要new Student_Or_Teacher_Validator
          3Validator validator = new Student_Validator();
          4//然后調(diào)用驗(yàn)證方法就可以了
          5boolean ok = validator.validate();

          至此,第一個(gè)解決方案就出來(lái)了。

          思考:

          不足

          validator接口的子類數(shù)目隨“角色數(shù)”成“指數(shù)級(jí)”增長(zhǎng),數(shù)量太多;而且子類中重復(fù)邏輯的代碼很多,如“Student_Or_Teacher_Validator”就重復(fù)了“Student_Validator”和“Teacher_Validator”的邏輯,萬(wàn)一“Student_Validator”的邏輯要改,只要涉及Student的子類都要跟著改,維護(hù)上不方便。

           

          進(jìn)一步改進(jìn)的可能

          Student_Or_Teacher_Validator類”的validate方法很大程度上就是“Student_Validator類”的validate方法和“Teacher_Validator類”的validate方法“或操作”出來(lái)的結(jié)果。

           

          因此,能不能考慮由“Student_Validator類的validate方法”和“Teacher_Validatorvalidate方法”動(dòng)態(tài)的構(gòu)造一個(gè)功能如“Student_Or_Teacher_Validator類的validate方法”。

           

          這樣,“Student_Or_Teacher_Validator”就可以省略了,只剩下一些原子的“角色類”。要實(shí)現(xiàn)Student_Or_Teacher_Validator的驗(yàn)證功能,拿Student_ValidatorTeacher_Validator裝配一下就可以了。

           

          結(jié)論,需要根據(jù)實(shí)際情況,動(dòng)態(tài)的改變(裝配)“Validator接口對(duì)象”的validate方法。

           

          第一個(gè)火花就是“裝飾模式”。它可以讓客戶端動(dòng)態(tài)的組裝對(duì)象的方法。真神奇!

          第二版來(lái)啦

          o_4.JPG

           

          注:上圖中出現(xiàn)了AndRelationAnd的一系列角色類,可以暫時(shí)省略不看,因?yàn)榍懊嬲f(shuō)了,現(xiàn)在還沒(méi)有“與”關(guān)系這個(gè)需求。只看Or的就可以。

           

          我喜歡叫這個(gè)模式為洋蔥模式,一層包一層,最外層對(duì)象某方法的邏輯是由內(nèi)部一層一層對(duì)象的同一方法組合出來(lái)的。

           

          使用了這個(gè)模式,便不用如一版那樣實(shí)現(xiàn)那么多子類,只要實(shí)現(xiàn)幾個(gè)“角色類”即可,這里有3個(gè)(學(xué)生角色:Or_Student、教師角色:Or_Teacher、游客角色:Or_Guest)。所有一版中別的子類都可以由這3個(gè)組裝出來(lái)。

           

          如要生成一版中的Student_Or_Teacher_Validator對(duì)象,可以用Or_StudentOr_Teacher兩個(gè)對(duì)象“Or”出來(lái):

           

          1Validator validator = new Or_Student(new Or_Teacher(OrRelation(req)));

           

          如要生成一版中的Guest_Or_Student_Or_Teacher_Validator對(duì)象,可以用Or_StudentOr_TeacherOr _Guest三個(gè)對(duì)象“Or”出來(lái):

           

          1Validator validator = new Or_Student(new Or_Teacher(new Or_Guest(OrRelation(req))));

           

           

          這種一層包一層的new方式,是不是很像洋蔥?第一次看是很不習(xí)慣,看多了就覺(jué)得習(xí)慣了。

          對(duì)客戶端的影響:

          一版中,客戶端要什么樣的驗(yàn)證類,就直接使用具體類。

          二版中,客戶端要什么樣的驗(yàn)證類,它的工作多了那么一丁點(diǎn),它需要先組裝一下,正如上面的例子。這種組裝的方法很易于理解和使用,不會(huì)給客戶端帶來(lái)任何的不便。如果實(shí)在覺(jué)得客戶端組裝不出來(lái)(傻B客戶端),也可以搞個(gè)工廠給它supply

          優(yōu)點(diǎn):

          相對(duì)一版最明顯的優(yōu)點(diǎn)就是類的數(shù)目少了很多。

           

          一版不是說(shuō)“指數(shù)級(jí)”嗎?這里只是線性的了。假設(shè)某一天系統(tǒng)拓展到有10個(gè)角色,一版就有210次方那么多個(gè),也就是1024個(gè)驗(yàn)證類。

           

          而二版還是10個(gè)角色類,別的都可以在客戶端使用的時(shí)候,動(dòng)態(tài)的組裝

           

          更重要的是代碼結(jié)構(gòu)好了,重復(fù)邏輯少了。每個(gè)邏輯都以最atomic的大小放到最應(yīng)該的地方。

           

          進(jìn)而,維護(hù)的代價(jià)少多了。如某天“教師角色”的驗(yàn)證邏輯發(fā)生了變化,只要改動(dòng)Or_Teacher一個(gè)地方即可。

                           MARCO ZHANG 2006年2月18日23:49:56

          posted on 2006-02-18 23:53 marco 閱讀(1250) 評(píng)論(5)  編輯  收藏 所屬分類: -=Design Pattern=--=Java Techs=--=Project Experience=-

          Feedback

          # re: Java Web Application開(kāi)發(fā)日志之四--“make the method become dynamic”,“洋蔥”模式應(yīng)用 2006-02-19 20:04 InPractice
          我覺(jué)得關(guān)鍵是不同的Validator都能得到調(diào)用。Decoraotr可以實(shí)現(xiàn),用Chain Of Responsibility模式也可以實(shí)現(xiàn)。至于這兩者之間的取舍,需要根據(jù)更具體的需求才能確定。  回復(fù)  更多評(píng)論
            

          # re: Java Web Application開(kāi)發(fā)日志之四--“make the method become dynamic”,“洋蔥”模式應(yīng)用 2006-02-20 18:13 Samuel Cai
          看起來(lái)挺有用,但我覺(jué)得,倒不如把這些權(quán)限都存儲(chǔ)到數(shù)據(jù)庫(kù)中,每個(gè)權(quán)限對(duì)應(yīng)一列,這樣靈活多了,假設(shè)某個(gè)servlet要修改權(quán)限,照你這種方法,居然要?jiǎng)拥酱a。  回復(fù)  更多評(píng)論
            

          # re: Java Web Application開(kāi)發(fā)日志之四--“make the method become dynamic”,“洋蔥”模式應(yīng)用 2006-02-20 20:29 marco
          Samuel Cai朋友,你的“居然”用的好,呵呵。  回復(fù)  更多評(píng)論
            

          # re: Java Web Application開(kāi)發(fā)日志之四--“make the method become dynamic”,“洋蔥”模式應(yīng)用 2006-03-04 06:02 dylan
          1、這種對(duì)servlet的權(quán)限認(rèn)證應(yīng)該用filter來(lái)集中處理
          2、應(yīng)該使用正則表達(dá)式匹配的方式來(lái)處理權(quán)限,可以放在數(shù)據(jù)庫(kù)或者配置文件中

          建議樓主參考一下acegi  回復(fù)  更多評(píng)論
            

          # re: Java Web Application開(kāi)發(fā)日志之四--“make the method become dynamic”,“洋蔥”模式應(yīng)用 2007-05-26 14:21 goodstuff
          lz的具體知識(shí)有爭(zhēng)議,但是lz的態(tài)度很好,能把復(fù)雜的事物講的夠淺顯是一種本領(lǐng)  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 藁城市| 肇源县| 瑞金市| 定陶县| 南木林县| 昭平县| 普兰县| 丹凤县| 盐边县| 广州市| 临清市| 涞源县| 冀州市| 疏附县| 玉林市| 五寨县| 张家界市| 昆山市| 沁水县| 泽库县| 临桂县| 浦东新区| 大名县| 西乌珠穆沁旗| 富锦市| 华宁县| 夏河县| 平潭县| 昌平区| 德令哈市| 班戈县| 融水| 宁晋县| 长宁区| 阳东县| 都江堰市| 齐齐哈尔市| 常山县| 松溪县| 景德镇市| 玉树县|