一、 模式定義:
          在不破壞封裝的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣就可以將該對(duì)象恢復(fù)到原先保存前的狀態(tài)。
          二、 模式解說
          在程序運(yùn)行過程中,某些對(duì)象的狀態(tài)處在轉(zhuǎn)換過程中,可能由于某種原因需要保存此時(shí)對(duì)象的狀態(tài),以便程序運(yùn)行到某個(gè)特定階段,需要恢復(fù)到對(duì)象之前處于某個(gè)點(diǎn)時(shí)的狀態(tài)。如果使用一些公有接口讓其它對(duì)象來得到對(duì)象的狀態(tài),便會(huì)暴露對(duì)象的實(shí)現(xiàn)細(xì)節(jié)。
          三、 結(jié)構(gòu)圖
           
          1) 備忘錄(Memento)角色:備忘錄角色存儲(chǔ)“備忘發(fā)起角色”的內(nèi)部狀態(tài)。“備忘發(fā)起角色”根據(jù)需要決定備忘錄角色存儲(chǔ)“備忘發(fā)起角色”的哪些內(nèi)部狀態(tài)。為了防止“備忘發(fā)起角色”以外的其他對(duì)象訪問備忘錄。備忘錄實(shí)際上有兩個(gè)接口,“備忘錄管理者角色”只能看到備忘錄提供的窄接口——對(duì)于備忘錄角色中存放的屬性是不可見的。“備忘發(fā)起角色”則能夠看到一個(gè)寬接口——能夠得到自己放入備忘錄角色中屬性。
          2) 備忘發(fā)起(Originator)角色:“備忘發(fā)起角色”創(chuàng)建一個(gè)備忘錄,用以記錄當(dāng)前時(shí)刻它的內(nèi)部狀態(tài)。在需要時(shí)使用備忘錄恢復(fù)內(nèi)部狀態(tài)。
          3) 備忘錄管理者(Caretaker)角色:負(fù)責(zé)保存好備忘錄。不能對(duì)備忘錄的內(nèi)容進(jìn)行操作或檢查。
          四、一個(gè)例子
          這個(gè)例子是我從網(wǎng)上找到的,我覺得它比較形象,就拿過來直接用了。下面是這個(gè)例子的代碼:
           class WindowsSystem{
           private String state;
           public Memento createMemento(){ //創(chuàng)建系統(tǒng)備份
            return new Memento(state);
           }
           public void restoreMemento(Memento m){ //恢復(fù)系統(tǒng)
            this.state=m.getState();
           }
           public String getState() {
            return state;
           }
           public void setState(String state) {
            this.state = state;
            System.out.println("當(dāng)前系統(tǒng)處于"+this.state);
           }
           
          }
          class Memento{
           private String state;
           
           public Memento(String state) {
            this.state = state;
           }
           public String getState() {
            return state;
           }
           public void setState(String state) {
            this.state = state;
           }
          }
          class User{
           private Memento memento;
           public Memento retrieveMemento() {  //恢復(fù)系統(tǒng)
               return this.memento;
           }
           public void saveMemento(Memento memento){  //保存系統(tǒng)
               this.memento=memento;
           }
          }

          public class Test{

           public static void main(String[] args) {
           
             WindowsSystem Winxp = new WindowsSystem(); //Winxp系統(tǒng)
             User user = new User();   //某一用戶
             Winxp.setState("好的狀態(tài)");   //Winxp處于好的運(yùn)行狀態(tài)
             user.saveMemento(Winxp.createMemento()); //用戶對(duì)系統(tǒng)進(jìn)行備份,Winxp系統(tǒng)要產(chǎn)生備份文件
             Winxp.setState("壞的狀態(tài)");   //Winxp處于不好的運(yùn)行狀態(tài)
             Winxp.restoreMemento(user.retrieveMemento());   //用戶發(fā)恢復(fù)命令,系統(tǒng)進(jìn)行恢復(fù)
             System.out.println("當(dāng)前系統(tǒng)處于"+Winxp.getState());
            }

          }
          在本例中,WindowsSystem是發(fā)起人角色(Orignation),Memento是備忘錄角色(Memento),User是備忘錄管理角色(Caretaker)。Memento提供了兩個(gè)接口(注意這里的接口,并不是java中的接口,它指的是可被外界調(diào)用的方法):一個(gè)是為WindowsSystem 類的寬接口,能夠得到WindowsSystem放入Memento的state屬性,代碼見WindowsSystem的createMemento方法和restoreMemento方法,createMemento方法向Memento放入state屬性,restoreMemento方法獲得放入的state屬性。另一個(gè)是為User類提供的窄接口,只能管理Memento而不能對(duì)它的內(nèi)容進(jìn)行任何操作(見User類)。
          五、 優(yōu)缺點(diǎn)
          1) 保持封裝邊界 使用備忘錄可以避免暴露一些只應(yīng)由原發(fā)器管理卻又必須存儲(chǔ)在原發(fā)器之外的信息。該模式把可能很復(fù)雜的Originator內(nèi)部信息對(duì)其他對(duì)象屏蔽起來,從而保持了封裝邊界。
          2) 它簡(jiǎn)化了原發(fā)器 在其他的保持封裝性的設(shè)計(jì)中,Originator負(fù)責(zé)保持客戶請(qǐng)求過的內(nèi)部狀態(tài)版本。這就把所有存儲(chǔ)管理的重任交給了Originator。讓客戶管理它們請(qǐng)求的狀態(tài)將會(huì)簡(jiǎn)化Originator,并且使得客戶工作結(jié)束時(shí)無需通知原發(fā)器。
          3) 使用備忘錄可能代價(jià)很高 如果原發(fā)器在生成備忘錄時(shí)必須拷貝并存儲(chǔ)大量的信息,或者客戶非常頻繁地創(chuàng)建備忘錄和恢復(fù)原發(fā)器狀態(tài),可能會(huì)導(dǎo)致非常大的開銷。除非封裝和恢復(fù)Originator狀態(tài)的開銷不大,否則該模式可能并不合適。
          4) 維護(hù)備忘錄的潛在代價(jià) 管理器負(fù)責(zé)刪除它所維護(hù)的備忘錄。然而,管理器不知道備忘錄中有多少個(gè)狀態(tài)。因此當(dāng)存儲(chǔ)備忘錄時(shí),一個(gè)本來很小的管理器,可能會(huì)產(chǎn)生大量的存儲(chǔ)開銷。
          六、 適用性
          1)必須保存一個(gè)對(duì)象在某一個(gè)時(shí)刻的(部分)狀態(tài),這樣以后需要時(shí)它才能恢復(fù)到先前的狀態(tài)。
          2)如果一個(gè)用接口來讓其它對(duì)象直接得到這些狀態(tài),將會(huì)暴露對(duì)象的實(shí)現(xiàn)細(xì)節(jié)并破壞對(duì)象的封裝性。
          七、參考
           http://tech.it168.com/n/d/2007-05-20/200705201437328.shtml
          http://www.cnblogs.com/John-zhaohui/archive/2007/08/20/862663.html
          http://www.cppblog.com/converse/archive/2006/08/09/11063.html
          http://java.ccidnet.com/art/3741/20030715/544777_1.html
          http://blog.csdn.net/qutr/archive/2006/08/01/1007600.aspx

          posts - 146, comments - 143, trackbacks - 0, articles - 0

          Copyright © flustar

          主站蜘蛛池模板: 勐海县| 青冈县| 廉江市| 巩义市| 会宁县| 五大连池市| 西丰县| 三河市| 亚东县| 精河县| 武鸣县| 丹东市| 元朗区| 封丘县| 达尔| 徐州市| 山丹县| 房山区| 东莞市| 泊头市| 都昌县| 资中县| 镇远县| 邯郸市| 抚顺县| 安宁市| 鹤庆县| 教育| 板桥市| 丹东市| 安平县| 房产| 平谷区| 澳门| 永和县| 武义县| 遂川县| 青龙| 芦山县| 普陀区| 武山县|