我的隱式生活(My Implicit Life)

          繼續搞“對象”,玩OO.

          首頁 新隨筆 聯系 聚合 管理
            11 Posts :: 1 Stories :: 39 Comments :: 0 Trackbacks

          廢話:

          預料中的日志3暫時生產不出來,話說難產就好,別夭折就行,有點掉價哦,呵呵。

           

          因為有些東西還沒有想清楚。那就先搞個四吧,這個東西還是清楚那么一點的。

          一版描述:

          項目需求

          使每個servlet能對用戶訪問權限進行檢查。簡單來說,就是要給每個servlet加個鎖,有鑰匙的用戶才能訪問。

           

          而項目中用戶所謂的訪問權限是基于他擁有的角色。也就是說,servlet對用戶訪問權限的檢查,就是對他所擁有角色的檢查。暫時,每個用戶只能擁有一個角色。

           

          項目的角色很多,但是在web端暫時只有如下的三種:

           

          項目暫時角色

          游客,學生,教師

           

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

           

          servlet加鎖方式

           游客,學生,教師,
          游客或學生,游客或教師,學生或教師,
          游客或學生或教師

           注:上面的“游客”就是“游客角色有權訪問”的意思,依此類推。

           

          這里只有關系“或”(||),如果一個servlet的加鎖方式是“學生或教師”,也就是說擁有學生或教師角色的用戶都可以訪問它。關系“與”(&&)在這里不太可能存在,因為沒有需求說:某個servlet一定只能由“既是學生又是教師的用戶”才能訪問,而且前面也說了,暫時一個用戶“有且只有”一個角色。

           

          So we can get following function


          “加鎖方式數” = 2的“角色數”次方 - 1


          “加鎖方式數”是關于“角色數”的指數函數,也就是說它是關于“角色數”成“指數級”增長的,應該說很快了吧。


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

           

          運用OO的最基本方式,就是封裝對象。既然有為servlet“看門”的責任,那就把這個責任封裝成一個對象,用個俗名:validator

           

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

          o_4-1.JPG

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

           

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


          o_4-2.JPG

           

           

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

          至此,第一個解決方案就出來了。

          思考:

          不足

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

           

          進一步改進的可能

          Student_Or_Teacher_Validator類”的validate方法很大程度上就是“Student_Validator類”的validate方法和“Teacher_Validator類”的validate方法“或操作”出來的結果。

           

          因此,能不能考慮由“Student_Validator類的validate方法”和“Teacher_Validatorvalidate方法”動態的構造一個功能如“Student_Or_Teacher_Validator類的validate方法”。

           

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

           

          結論,需要根據實際情況,動態的改變(裝配)“Validator接口對象”的validate方法。

           

          第一個火花就是“裝飾模式”。它可以讓客戶端動態的組裝對象的方法。真神奇!

          第二版來啦

          o_4.JPG

           

          注:上圖中出現了AndRelationAnd的一系列角色類,可以暫時省略不看,因為前面說了,現在還沒有“與”關系這個需求。只看Or的就可以。

           

          我喜歡叫這個模式為洋蔥模式,一層包一層,最外層對象某方法的邏輯是由內部一層一層對象的同一方法組合出來的。

           

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

           

          如要生成一版中的Student_Or_Teacher_Validator對象,可以用Or_StudentOr_Teacher兩個對象“Or”出來:

           

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

           

          如要生成一版中的Guest_Or_Student_Or_Teacher_Validator對象,可以用Or_StudentOr_TeacherOr _Guest三個對象“Or”出來:

           

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

           

           

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

          對客戶端的影響:

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

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

          優點:

          相對一版最明顯的優點就是類的數目少了很多。

           

          一版不是說“指數級”嗎?這里只是線性的了。假設某一天系統拓展到有10個角色,一版就有210次方那么多個,也就是1024個驗證類。

           

          而二版還是10個角色類,別的都可以在客戶端使用的時候,動態的組裝

           

          更重要的是代碼結構好了,重復邏輯少了。每個邏輯都以最atomic的大小放到最應該的地方。

           

          進而,維護的代價少多了。如某天“教師角色”的驗證邏輯發生了變化,只要改動Or_Teacher一個地方即可。

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

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

          Feedback

          # re: Java Web Application開發日志之四--“make the method become dynamic”,“洋蔥”模式應用 2006-02-19 20:04 InPractice
          我覺得關鍵是不同的Validator都能得到調用。Decoraotr可以實現,用Chain Of Responsibility模式也可以實現。至于這兩者之間的取舍,需要根據更具體的需求才能確定。  回復  更多評論
            

          # re: Java Web Application開發日志之四--“make the method become dynamic”,“洋蔥”模式應用 2006-02-20 18:13 Samuel Cai
          看起來挺有用,但我覺得,倒不如把這些權限都存儲到數據庫中,每個權限對應一列,這樣靈活多了,假設某個servlet要修改權限,照你這種方法,居然要動到代碼。  回復  更多評論
            

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

          # re: Java Web Application開發日志之四--“make the method become dynamic”,“洋蔥”模式應用 2006-03-04 06:02 dylan
          1、這種對servlet的權限認證應該用filter來集中處理
          2、應該使用正則表達式匹配的方式來處理權限,可以放在數據庫或者配置文件中

          建議樓主參考一下acegi  回復  更多評論
            

          # re: Java Web Application開發日志之四--“make the method become dynamic”,“洋蔥”模式應用 2007-05-26 14:21 goodstuff
          lz的具體知識有爭議,但是lz的態度很好,能把復雜的事物講的夠淺顯是一種本領  回復  更多評論
            

          主站蜘蛛池模板: 讷河市| 浦城县| 巴林右旗| 商都县| 抚州市| 防城港市| 名山县| 玛曲县| 凭祥市| 隆回县| 博爱县| 苏尼特右旗| 土默特右旗| 芷江| 谷城县| 财经| 沾化县| 拜城县| 来凤县| 屏山县| 沧州市| 句容市| 六枝特区| 威宁| 临沂市| 正阳县| 两当县| 兰州市| 昌江| 呼玛县| 安图县| 乐业县| 文昌市| 鲁山县| 古田县| 陵川县| 木里| 赤壁市| 杭州市| 曲松县| 新乡县|