lyl3333489

          2007年7月10日

          騎警

          posted @ 2007-07-20 17:28 AAAAA 閱讀(302) | 評論 (1)編輯 收藏

          觀察者模式

              常聽說這么一句話(大意是這樣):不必可以去套用設計模式,如果按照面向對象的基本原則編程,自然是優雅的設計,即使沒有刻意使用模式,設計也會近乎于模式。開始感覺有一點玄,但在看了《C#設計模式縱橫談》視頻后,覺得有所收獲。下面,就參考視頻的內容,嘗試著寫這么一個過程:根據面向對象的一般原則對設計進行重構,逐漸演化出觀察者模式。
          涉及的面向對象設計原則:單一職責原則、封裝變化、面向接口編程、依賴倒置原則、開閉原則。

          1.發布訂閱模型:



                   
                         
          假如有需求如下:

          銀行需要把帳戶的如匯款、轉賬或取款等操作通知用戶,途徑包括手機短信、 email等。如圖所式。

          自然地,我們可以這樣做:

          public class ATM
           {
               BankAccount bankAccount;
               
               
          public void process()
               {
                    
          //bankAccount...
                   this.sendEmail(userEmail);
                   
          this.sendPhone(phoneNumber);
               }
           
               
          private void sendEmail(String userEmail)
               {
                   
          //
               }

              
          private void sendMobile(String phoneNumber)
               {
                   
          //
               }
           }

          ATM機的 process()方法在處理完業務邏輯后,由email和phone通知用戶。

          2.初步重構

          好像有bad smells,恩,根據單一職責原則。新增Email類和Phone類,并把相關業務邏輯改到BankAccount類完成。于是我們的代碼可以這樣:


          public class ATM
          {
              BankAccount bankAccount;
              
              
              
          public void process()
              {
                    
          //
                    bankAccount.withDraw();
              }
           
           }

          public class BankAccount 
          {
              Email email;
              Mobile mobile;

              
          public void withDraw()
              {
                   
          //
                   email.sendEmail(userEmail);
                   mobile.sendMobile(phoneNumber);
              }
          }

          public class Email
          {
              
          public void sendEmail(String userEmail)
              {
              }
          }

          public class Mobile
          {
              
          public void sendMobile(String phoneNumber)
              {
              }
          }

          下面是代碼的UML圖:




          3.擁抱變化

          這個解決方案有問題嗎?可能沒有問題。它實現了我們的需求:在帳戶有操作變動的時候,通知Email和Mobile去發送信息給用戶。但這樣設計就足夠了嗎?可能足夠了,可能還不夠。
          考慮如下兩種情況:
          1.在很長一段時間里,訂閱方式很穩定,比如系統只通過郵件和手機短信進行信息訂閱,那么這個實現沒有太大問題;
          2.在近一兩年或更短的時間,更多的訂閱方式將會源源不斷地被加進來:比如可以登錄官方網站等等,那這個實現就有問題:再看一下我們的UML圖,類BankAccount依賴于Email和Mobile類!就是說,如果需要添加新的訂閱方式ATM類的process()方法勢必要重新設計!

          于是我們的BankAccount類不得不變成:

          public class  BankAccount
          {
              Email email;
              Mobile mobile;
              Web web;

              
          public void withDraw()
              {
                    
          //
                   email.sendEmail(userEmail);
                   mobile.sendMobile(phoneNumber);
                   web.sendWeb(webSite);
              }
           
           }

          如果還有另一種方式,那么process()方法就又會需要加入:otherSubscribe.send...();等方法,另外如果訂閱類的接口(這里指sendEmail等方法)發生變化,BankAccount的withDraw()方法也必須有相應的變化!這當然是種災難。我們必須改變這種情況。
          先解決遺留問題:第一種情況:訂閱方式相對穩定的情況下呢?不改動會產生災難嗎?
          個人認為:不會。比如某個系統信息只通過手機短信訂閱,那就沒有必要太在意這個問題。考慮周全一點不好嗎,如果將來有類似需求呢?小心過度設計!為了將來可能出現需求而進行的預先設計并不太好。有需求,才有設計。

          現在來看解決之道:

          運用面向對象的思想,抽象出問題所在。BankAccount類依賴于 Email類和Mobile類,而Email和Mobile是具體的類,ATM依賴于具體的類了,而且還不止一個!回憶一下依賴倒置原則:具體應該依賴于抽象,底層模式應該依賴于高層模式那怎么實現依賴倒置原則呢?面向對象編程中有一條總的原則:封裝變化。如何實現封裝變化?需要我們這樣:面向接口編程

          回顧一下:我們在設計中實現類依賴了具體的類,違反了依賴倒置原則。為了遵循依賴倒置原則,我們采用面向接口編程的方法,從而實現了面向對象的一條總的原則:封裝變化。


          看代碼:

          public interface AccountObserver
          {
              
          public void upDate(UserAccount userAccount);
          }

          public class Email implements AccountObserver
          {
              
          public void upDate(UserAccount userAccount)
              {
              }
          }

          public class Mobile
          {
              
          public void upDate(UserAccount userAccount)
              {
              }
          }

          public class BankAccount 
          {
              List 
          <AccountObserver> observer = new ArrayList<AccountObserver>;

              
          public void withDraw()
              {
                   
          //
                   for (AccountObserver ao : observer)
                   {
                      ao.upDate(userAccount)
                    }
              }
              
              
          public void addOberver(AccountObserver accountObserver)
              {
                    observer.add(accountObserver);
               }
          }

          UML圖:



          現在,BankAccount依賴于interface AccountObserver。Email和Mobile實現AccountObserver接口。通過遵循面向接口編程遵循了依賴倒置原則

          4.開閉原則

          終于修改好了,我們解決了訂閱者變化的問題。但如果發布者也傾向于變化呢?這就牽涉到面向對象里的另一個原則:開閉原則即:對擴展開放,對修改關閉。具體怎么做呢?通過抽象類,從抽象類繼承具體類。
          看最終的代碼(只寫幾個關鍵的方法,全貌可看最后的UML圖):

          訂閱:

          public interface AccountObserver
          {
              
          public void upDate(UserAccount userAccount);
          }

          public class Email implements AccountObserver
          {
              
          public void upDate(UserAccount userAccount)
              {
              }
          }

          public class Mobile implements AccountObserver
          {
              
          public void upDate(UserAccount userAccount)
              {
              }
          }


          發布:



          public abstract class Subject
          {
               List 
          <AccountObserver> observer = new ArrayList<AccountObserver>;

              
          protected void withDraw()
              {
                   
          //
                   notify();
                   
              }
              
              
          protected void notify(UserAccount userAccount)
              {
                   
          for (AccountObserver ao : observer)
                   {
                      ao.upDate(userAccount)
                    }
               }
              
              
          protected void addOberver(AccountObserver accountObserver)
              {
                    observer.add(accountObserver);
               }

                
          protected void deleteOberver(AccountObserver accountObserver)
              {
                    observer.remove(accountObserver);
               }

          }

          public class BankAccount extends Subject
          {
              
          public void withDraw()
              {
                   
          //
                   for (AccountObserver ao : observer)
                   {
                      ao.upDate(userAccount)
                    }
              }
              
          }



          看UML圖:




          5.觀察者模式概況




          這就是觀察者模式了,對比一下官方的UML圖,是不是一目了然了呢?
          稍作說明(這里的依賴都是指廣義的依賴):
          1.被觀察者ConcreteSubject繼承自Subject抽象類;
          2.Subject抽象類依賴于觀察者Observer抽象接口;
          3.觀察者ConcreteObserver實現Observer 接口;
          4.觀察者ConcreteObserver間接依賴于ConcreteSubject類。
          如果要增加具體的觀察者,只要再實現Obsever接口即可,而被觀察方不需要做任何修改。而如果需要修改被觀察者,只要從Subject抽象類繼承即可。

          posted @ 2007-07-10 10:36 AAAAA 閱讀(325) | 評論 (0)編輯 收藏

          收集的網址

          http://www.linuxfans.org   
          http://www.otasuke.ne.jp/modules/xwords/index.php   
          http://jp.hjenglish.com/papers.aspx   
          www.21cnhr.gov.cn   
          http://www.ytv.co.jp/conan/   
          http://www13.tianya.cn/new/Publicforum/Content.asp?idWriter=3915484&Key=228823315&strItem=no04&idArticle=483393&flag=1   
          http://piano.stedu.net/   
          http://www.nhk.or.jp/           <<NHK>>           http://www.nhk.or.jp/r-news/   
          http://www.intel.com/software/cn/mcwebcast/#slide=1    intel class   
          http://www.yangmi.net/ky/Print.asp?ArticleID=13801   !!!   
          http://bbs.i18.cn/index.asp     中國零售網   
          http://www.fortunespace.net/forum/    中國財富論壇   
          http://www.yesky.com/SoftChannel/72357786515668992/20040129/1764106.shtml  求和   
          http://www.yesky.com/SoftChannel/72348968914255872/20050126/1905902.shtml Excel ?用   
          http://www.yesky.com/soft/office/excel-news/his/his_4.shtml  Excel   
          http://www.4399.net/flash/1602_2.htm?800 golden   
          http://edu.itbulo.com/200511/58025.htm        ITbulo   
          http://202.103.49.240/jsjzs/excel/excelyy.htm    Excel 排序   
          http://192.168.1.23/use_wf/Dep_App     WF  WF  WF  WF   
          http://www.yodian.com   有點   
          http://www.dlsp.com.cn   DLSP   
          http://64.233.179.104/search?q=cache:QqZYnKlqqEwJ:members.at.infoseek.co.jp/skillup/yougo/yougo6.htm+EOB%E3%80%80Electronic&hl=ja&gl=jp&ct=clnk&cd=1&lr=lang_ja   
          http://www.codesky.net   CODE   
              
          http://www1.tianya.cn/new/TechForum/Content.asp?idWriter=3915484&Key=840161655&idItem=81&idArticle=251915   
          http://www.chinacs.net/archives/8/2004/12/12/3188.html       C#   
          http://music.whnews.cn/playgame/flashshow.php?flashid=895      SC   
          http://www.tianya.cn/new/TechForum/Content.asp?idWriter=3915484&Key=481775086&idItem=81&idArticle=562447   
          http://192.168.1.211/TRIAL/upload/jinji/study/access/    ACCESS   
          http://www.wswire.com/      huaerjie dianxun   
          http://infoseek.amikai.com/amitext/indexUTF8.jsp   
          http://www.51windows.net/pages/ado/?url=/pages/ado/mdmthaddnew.htm      ADO    ADO 
          http://www.51windows.net/
            
          http://www.codechina.net/resource/sort.php/621/4       Access VBA  Code   
          http://jakarta.apche.org        struts   
          http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/csref/html/vcoricsharptutorials.asp       MSDN c#   
          http://www.daliancity.com.cn/job/index.php     DLZX 
          http://www.cjsdu.com/   DuiRiLunTan


          http://www.mutouyu.com/translation/ 木頭魚翻訳

          http://www6.tianya.cn/new/techforum/Content.asp?idWriter=3915484&Key=700727019&idItem=81&idArticle=574220

          http://localhost:8080/solves4/pages/CM/AAA/CMAAA001R.jsp

          http://www.tianya.cn/new/techforum/Content.asp?idWriter=3915484&Key=292720848&idItem=81&idArticle=568508

          http://www1.tianya.cn/new/techforum/Content.asp?idWriter=3915484&Key=189209006&idItem=81&idArticle=573983

          http://www2.tianya.cn/new/techforum/Content.asp?idWriter=3915484&Key=677920263&idItem=81&idArticle=573828
           hua xian chuang guan

          http://www.4399.net/flash/4362_4.htm?1024
           pao tai TD

          http://www.excite.co.jp/world/chinese/
           onlineTranslate

          http://www.4399.net/flash/457_1.htm?800
           qiJi

          http://www.javaeye.com/
           
          http://www.andykhan.com/jexcelapi/
           JXL(JAVA Excel API)

          http://www.uml.org.cn/sjms/200703274.asp
           設計モード

          http://www.okajax.com/
           Ajax 中國

          http://www.nicenic.com/domain/
           域名


          域名最長的網站
          http://www.llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch.co.uk/
          http://www.111111111111111111111111111111111111111111111111111111111111.com/
          http://3.141592653589793238462643383279502884197169399375105820974944592.com/
          http://www.thelongestdomainnameintheworldandthensomeandthensomemoreandmore.com/

          幾個不錯的JAVA學習網站
          http://www.csdn.net(社區、文檔、bolg、知識庫)
          http://www.hibernate.org.cn
          http://www.aygfsteel.com
          http://www.jdon.com
          http://www.javafan.net
          http://www.open-open.com
          http://dev2dev.bea.com.cn/
          http://www.javaresearch.org/
          http://www.codechina.net/resource/
          http://gceclub.sun.com.cn
          http://www.javaeye.com
          http://WWW.chinaitlab.com  中國IT試験室

          您的Blog地址是:http://www.aygfsteel.com/lyl3333489/

           

          posted @ 2007-07-10 09:05 AAAAA 閱讀(256) | 評論 (0)編輯 收藏

          <2007年7月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          導航

          統計

          常用鏈接

          留言簿(1)

          隨筆檔案

          相冊

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 三明市| 临洮县| 延安市| 偏关县| 莱芜市| 杭锦后旗| 抚远县| 福泉市| 漳平市| 麻城市| 包头市| 云阳县| 靖边县| 青海省| 固原市| 缙云县| 广宗县| 曲沃县| 西乌珠穆沁旗| 曲水县| 高州市| 仪征市| 手游| 内乡县| 安丘市| 清水河县| 磴口县| 会同县| 六安市| 谢通门县| 静安区| 西宁市| 方山县| 彭州市| 大厂| 渑池县| 亚东县| 三江| 栾城县| 玉山县| 明溪县|