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

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

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

    人在江湖

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      82 Posts :: 10 Stories :: 169 Comments :: 0 Trackbacks

    備忘錄(Memento Pattern)模式
    備忘錄模式又叫做快照模式(Snapshot Pattern)或Token模式,是對(duì)象的行為模式。
    備忘錄對(duì)象是一個(gè)用來存儲(chǔ)另外一個(gè)對(duì)象內(nèi)部狀態(tài)的快照的對(duì)象。備忘錄模式的用意是在不破壞封裝的條件下,將一個(gè)對(duì)象的狀態(tài)捕捉住,并外部化
    存儲(chǔ)起來,從而可以在將來合適的時(shí)候把這個(gè)對(duì)象還原到存儲(chǔ)起來的狀態(tài)。備忘錄模式常常與命令模式和迭代子模式一同使用。
    常見的軟件系統(tǒng)往往不止存儲(chǔ)一個(gè)狀態(tài),而是需要存儲(chǔ)多個(gè)狀態(tài)。這些狀態(tài)常常是一個(gè)對(duì)象歷史發(fā)展的不同階段的快照,存儲(chǔ)這些快照的備忘錄對(duì)象
    叫做此對(duì)象的歷史,某一個(gè)快照所處的位置叫做檢查點(diǎn)。
    備忘錄角色:
    備忘錄角色有如下的責(zé)任。
    1、將發(fā)起人(Originator)對(duì)象的內(nèi)部狀態(tài)存儲(chǔ)起來,備忘錄可以根據(jù)發(fā)起人對(duì)象的判斷來決定存儲(chǔ)多少
         發(fā)起人(Originator)對(duì)象的內(nèi)部狀態(tài)。
    2、備忘錄可以保護(hù)其內(nèi)容不被發(fā)起人對(duì)象之外的任何對(duì)象所讀取。備忘錄有兩個(gè)等效的接口:
    1、窄接口:負(fù)責(zé)人(Caretaker)對(duì)象(和其他除發(fā)起人對(duì)象之外的任何對(duì)象)看到的是備忘錄的窄
       接(narrow interface),這個(gè)窄接口只允許它把備忘錄對(duì)象傳給其他的對(duì)象;
    2、寬接口:與負(fù)責(zé)人對(duì)象看到的窄接口相反的是,發(fā)起人對(duì)象可以看到一個(gè)寬接口(wide interface),
       這個(gè)寬接口允許它讀取所有的數(shù)據(jù),以便根據(jù)數(shù)據(jù)恢復(fù)這個(gè)發(fā)起人對(duì)象的內(nèi)部狀態(tài)。853P
    發(fā)起人角色:
    發(fā)起人角色有如下責(zé)任:
    1、創(chuàng)建一個(gè)含有當(dāng)前的內(nèi)部狀態(tài)的備忘錄對(duì)象。
    2、使用備忘錄對(duì)象存儲(chǔ)其內(nèi)部狀態(tài)。
    負(fù)責(zé)人角色:
    負(fù)責(zé)人角色有如下的責(zé)任:
    1、負(fù)責(zé)保存?zhèn)渫泴?duì)象
    2、不檢查備忘錄對(duì)象的內(nèi)容。

    Java代碼

       1: 寬接口和白箱:
       2:         發(fā)起人角色
       3:         public class Originator{
       4:             private String state;
       5:             
       6:             //工廠方法,返還一個(gè)新的備忘錄對(duì)象
       7:             public Memento createMemento(){
       8:                 return new Memento(state);
       9:             }
      10:             
      11:             //將發(fā)起人恢復(fù)到備忘錄對(duì)象所記載的狀態(tài)
      12:             public void restoreMemento(Memento memento){
      13:                 this.state = memento.getState();
      14:             }
      15:             
      16:             //狀態(tài)的取值方法
      17:             public String getState(){
      18:                 return this.state;
      19:             }
      20:             
      21:             //狀態(tài)的賦值方法
      22:             public void setState(String state){
      23:                 this.state = state;
      24:                 System.out.println("Current state = " + this.state);
      25:             }
      26:         }
      27:         
      28:         備忘錄模式要求備忘錄對(duì)象提供兩個(gè)不同的接口:一個(gè)寬接口提供給發(fā)起人對(duì)象,另一個(gè)窄接口提供給所有其他的對(duì)象,包括負(fù)責(zé)人對(duì)象。
      29:         寬接口允許發(fā)起人讀取到所有的數(shù)據(jù);窄接口只允許它把備忘錄對(duì)象傳給其他的對(duì)象而看不到內(nèi)部的數(shù)據(jù)。
      30:         //備忘錄角色
      31:         public class Memento{
      32:             private String state;
      33:             
      34:             public Memento(String state){
      35:                 this.state = state;
      36:             }
      37:             
      38:             public String getState(){
      39:                 return this.state;
      40:             }
      41:             
      42:             public void setState(String state){
      43:                 this.state = state;
      44:             }
      45:         }
      46:         
      47:         負(fù)責(zé)人角色負(fù)責(zé)保存?zhèn)渫泴?duì)象,但是從不修改(甚至不查看)備忘錄對(duì)象的內(nèi)容(一個(gè)更好的實(shí)現(xiàn)是負(fù)責(zé)人對(duì)象根本無法從備忘錄
      48:         對(duì)象中讀取個(gè)修改其內(nèi)容)
      49:         
      50:         //負(fù)責(zé)人角色
      51:         public class Caretaker{
      52:             private Memento memento;
      53:             
      54:             //備忘錄的取值方法
      55:             public Memento retrieveMemento(){
      56:                 return this.memento;
      57:             }
      58:             
      59:             //備忘錄的賦值方法
      60:             public void saveMemento(Memento memento){
      61:                 this.memento = memento;
      62:             }
      63:         }
      64:         
      65:         //客戶端
      66:         public class Client{
      67:             private static Originator o = new Originator();
      68:             private static Caretaker c= new Caretaker();
      69:             private static void main(String[] args){
      70:                 //該負(fù)責(zé)人對(duì)象的狀態(tài)
      71:                 o.setState("On");
      72:                 //創(chuàng)建備忘錄對(duì)象,并將發(fā)起人對(duì)象的狀態(tài)存儲(chǔ)起來
      73:                 c.saveMemento(o.createMemento());
      74:                 //修改發(fā)起人對(duì)象的狀態(tài)
      75:                 o.setState("Off");
      76:                 //恢復(fù)發(fā)起人對(duì)象的狀態(tài)
      77:                 o.restoreMemento(c.retrieveMemento());
      78:             }
      79:         }
      80:         首先將發(fā)起人對(duì)象的狀態(tài)設(shè)置成“On”(或者任何有效狀態(tài)),并且創(chuàng)建一個(gè)備忘錄對(duì)象將這個(gè)狀態(tài)存儲(chǔ)起來;然后將發(fā)起人對(duì)象
      81:         的狀態(tài)改成“Off”(或者任何狀態(tài));最后又將發(fā)起人對(duì)象恢復(fù)到備忘錄對(duì)象所存儲(chǔ)起來的狀態(tài),即“On”狀態(tài)(或者先前所
      82:         存儲(chǔ)的任何狀態(tài))
      83:         
      84:         備忘錄系統(tǒng)運(yùn)行的時(shí)序是這樣的:
      85:             (1)將發(fā)起人對(duì)象的狀態(tài)設(shè)置成“On”。
      86:             (2)調(diào)用發(fā)起人角色的createMemento()方法,創(chuàng)建一個(gè)備忘錄對(duì)象將這個(gè)狀態(tài)存儲(chǔ)起來。
      87:             (3)將備忘錄對(duì)象存儲(chǔ)到負(fù)責(zé)人對(duì)象中去。
      88:         備忘錄系統(tǒng)恢復(fù)的時(shí)序是這樣的:
      89:             (1)將發(fā)起人對(duì)象的狀態(tài)設(shè)置成“Off”;
      90:             (2)將備忘錄對(duì)象從負(fù)責(zé)人對(duì)象中取出;
      91:             (3)將發(fā)起人對(duì)象恢復(fù)到備忘錄對(duì)象所存儲(chǔ)起來的狀態(tài),“On”狀態(tài)。
      92:         
      93:         白箱實(shí)現(xiàn)的優(yōu)缺點(diǎn)
      94:             白箱實(shí)現(xiàn)的一個(gè)明顯的好處是比較簡(jiǎn)單,因此常常用做教學(xué)目的。白箱實(shí)現(xiàn)的一個(gè)明顯的缺點(diǎn)是破壞對(duì)發(fā)起人狀態(tài)的封裝。
      95:             
      96:     窄接口或者黑箱實(shí)現(xiàn)
      97:         //發(fā)起人角色
      98:         public class Originator{
      99:             private String state;
     100:             
     101:             public Originator(){
     102:             }
     103:             
     104:             //工廠方法,返還一個(gè)新的備忘錄對(duì)象
     105:             public MementoIF createMemento(){
     106:                 return new Memento(this.state);    
     107:             }
     108:             
     109:             //將發(fā)起人恢復(fù)到備忘錄對(duì)象記錄的狀態(tài)
     110:             public void restoreMemento(MementoIF memento){
     111:                 Memento aMemento = (Memento)memento;
     112:                 this.setState(aMemento.getState());
     113:             }
     114:             
     115:             public String getState(){
     116:                 return this.state;
     117:             }
     118:             
     119:             public void setState(){
     120:                 this.state = state;
     121:                 System.out.println("state = " + state);
     122:             }
     123:             
     124:             protected class Memento implements MementoIF{
     125:                 private String savedState;
     126:                 private Mememto(String someState){
     127:                     savedState = someState;
     128:                 }
     129:                 
     130:                 private void setState(String someState){
     131:                     savedState = someState;
     132:                 }
     133:                 
     134:                 private String getState(){
     135:                     return savedState;
     136:                 }
     137:             }
     138:         }
     139:         
     140:         public interface MementoIF{}
     141:         
     142:         public class Caretaker{
     143:             private MementoIF memento;
     144:             
     145:             public MementoIF retrieveMemento(){
     146:                 return this.memento;
     147:             }
     148:             
     149:             public void saveMemento(MementoIF memento){
     150:                 this.memento = memento;
     151:             }
     152:         }
     153:         
     154:         public class Client{
     155:             private static Originator o = new Originator();
     156:             private static Caretaker c = new Caretaker();
     157:             
     158:             public static void main(String args[]){
     159:                 //改變負(fù)責(zé)人對(duì)象的狀態(tài)
     160:                 o.setState("On");
     161:                 //創(chuàng)建備忘錄對(duì)象,并將發(fā)起人對(duì)象的狀態(tài)存儲(chǔ)起來
     162:                 c.saveMemento(o.createMemento());
     163:                 //修改發(fā)起人對(duì)象的狀態(tài)
     164:                 o.setState("Off");
     165:                 //恢復(fù)發(fā)起人對(duì)象的狀態(tài)
     166:                 o.restoreMemento(c.retrieveMemento());
     167:             }
     168:         }
     169:         
     170:         黑箱實(shí)現(xiàn)運(yùn)行時(shí)的時(shí)序?yàn)?
     171:             (1)將發(fā)起人對(duì)象的狀態(tài)設(shè)置成“On”。
     172:             (2)調(diào)用發(fā)起人角色的 createMemento()方法,創(chuàng)建一個(gè)備忘錄對(duì)象將這個(gè)狀態(tài)存儲(chǔ)起來。
     173:             (3)將備忘錄對(duì)象存儲(chǔ)到負(fù)責(zé)人對(duì)象中去。由于負(fù)責(zé)人對(duì)象拿到的僅是 MementoIF類型,因此無法讀出備忘錄內(nèi)部的狀態(tài)。
     174:         恢復(fù)時(shí)的時(shí)序?yàn)椋?/pre>
     175:             (1)將發(fā)起人對(duì)象的狀態(tài)設(shè)置成“Off”;
     176:             (2)將備忘錄對(duì)象從負(fù)責(zé)人對(duì)象中取出。注意此時(shí)僅能得到 MementoIF接口,因此無法讀出此對(duì)象的內(nèi)部狀態(tài)
     177:             (3)將發(fā)起人對(duì)象的狀態(tài)恢復(fù)成備忘錄對(duì)象所存儲(chǔ)起來的狀態(tài),,由于發(fā)起人對(duì)象的內(nèi)部類Memento實(shí)現(xiàn)了MementoIF接口
     178:                  這個(gè)內(nèi)部類是傳入的備忘錄對(duì)象的真實(shí)類型,因此發(fā)起人對(duì)象可以利用內(nèi)部類Memento 的私有 接口讀出此對(duì)象的內(nèi)部狀態(tài)
     179:                  
     180: 存儲(chǔ)多個(gè)狀態(tài)的備忘錄模式:
     181:         //發(fā)起人角色
     182:         import java.util.Vector;
     183:         import java.util.Enumeration;
     184:         
     185:         public class Originator{
     186:             private Vector states;
     187:             private int index;
     188:             
     189:             public Originator(){
     190:                 states = new Vector();
     191:                 index = 0;
     192:             }
     193:             
     194:             public Memento createMementor(){
     195:                 return new Mementor(states,index);
     196:             }
     197:             
     198:             public void restoreMementor(Mementor memento){
     199:                 states = memento.getStates();
     200:                 index = memento.getIndex();
     201:             }
     202:             
     203:             public void setState(String state){
     204:                 this.states.addElement(state);
     205:                 index ++;
     206:             }
     207:             
     208:             //輔助方法,打印出所有的狀態(tài)
     209:             public void printStates(){
     210:                 System.out.println("Total number of states: " + index);
     211:                 for(Enumeration e = states.elements();e.hasMoreElements();){
     212:                     system.out.println(e.nextElement());
     213:                 }
     214:             }
     215:         } 
     216:         
     217:         //備忘錄角色
     218:         import java.util.Vector;
     219:         
     220:         public class Memento{
     221:             private Vector states;
     222:             private int index;
     223:             
     224:             public Memento(Vector states,int index){
     225:                 this.states = (Vector)states.clone();
     226:                 this.index = index;
     227:             }
     228:             
     229:             //狀態(tài)取值方法
     230:             Vector getStates(){
     231:                 return states;
     232:             }
     233:             
     234:             //檢查點(diǎn)取值方法
     235:             int getIndex(){
     236:                 return this.index;
     237:             }
     238:         }
     239: ******************備忘錄的構(gòu)造子克隆了傳入的states,然后將克隆存入到備忘錄對(duì)象內(nèi)部,這是一個(gè)重要的細(xì)節(jié),因?yàn)椴贿@樣的話,將會(huì)
     240:           將會(huì)造成客戶端和備忘錄對(duì)象持有對(duì)同一個(gè)Vector對(duì)象的引用,也可以同時(shí)修改這個(gè)Vector對(duì)象,會(huì)造成系統(tǒng)崩潰。
     241:           
     242:         //負(fù)責(zé)人角色
     243:         import java.util.Vector;
     244:         
     245:         public class Caretaker{
     246:             private Originator o;
     247:             private Vector mementos = new Vector();
     248:             private int current;
     249:             
     250:             public Caretaker(Originator o){
     251:                 this.o = o;
     252:                 current = 0;
     253:             }
     254:             
     255:             public int createMemento(){
     256:                 Memento memento = o.createMemento();
     257:                 mementos.addElement(memento);
     258:                 return current ++;
     259:             }
     260:             
     261:             //將發(fā)起人恢復(fù)到某個(gè)檢查點(diǎn)
     262:             public void restoreMemento(int index){
     263:                 Memento memento = (Memento)mementos.elementAt(index);
     264:                 o.restoreMemento(memento);
     265:             }
     266:             
     267:             //某個(gè)檢查點(diǎn)刪除
     268:             public void removeMemento(int index){
     269:                 mementos.removeElementAt(index);
     270:             }
     271:         }
     272:         
     273:         //客戶端
     274:         public class Client{
     275:             private static Originator o = new Originator();
     276:             private static Caretaker c = new Caretaker(o);
     277:             public static void main(String[] args){
     278:                 //改變狀態(tài)
     279:                 o.setState("state 0");
     280:                 //建立一個(gè)檢查點(diǎn)
     281:                 c.createMemento();
     282:                 //改變狀態(tài)
     283:                 o.setState("state 1");
     284:                 
     285:                 c.createMemento();
     286:                 
     287:                 o.setState("state 2");
     288:                 
     289:                 c.createMemento();
     290:                 
     291:                 o.setState("state 3");
     292:                 
     293:                 c.createMemento();
     294:                 
     295:                 o.setState("state 4");
     296:                 
     297:                 c.createMemento();
     298:                 
     299:                 o.printStates();
     300:                 
     301:                 //恢復(fù)到第二個(gè)檢查點(diǎn)
     302:                 System.out.println("Restoring to 2");
     303:                 
     304:                 c.restoreMemento(2);
     305:                 
     306:                 o.printStates();
     307:                 
     308:                 System.out.println("Restoring to 0");
     309:                 
     310:                 c.restoreMemento(0);
     311:                 
     312:                 o.printStates();
     313:                 
     314:                 System.out.println("Restoring to 3");
     315:                 
     316:                 c.restoreMemento(3);
     317:                 
     318:                 o.printStates();
     319:                 
     320:                 
     321:             }
     322:         }
     323:         
     324: 自述歷史模式(備忘錄模式的一個(gè)變種):
     325:         //窄接口
     326:         public interface MementoIF{}
     327:         
     328:         //發(fā)起人角色
     329:         public class Originator{
     330:             public String state;
     331:             
     332:             public Originator(){}
     333:             
     334:             public void changeState(String state){
     335:                 this.state = state;
     336:                 System.out.println("State has been changed to : " + state);
     337:             }
     338:             
     339:             public Memento createMemento(){
     340:                 return new Memento(this);
     341:             }
     342:             
     343:             public void restoreMemento(MementoIF memento){
     344:                 Memento m = (Memento)memento;
     345:                 changeState(m.state);
     346:             }
     347:             
     348:             class Memento implements MementoIF{
     349:                 private String state;
     350:                 
     351:                 private String getState(){
     352:                     return state;
     353:                 }
     354:                 
     355:                 private Memento(Originator o){
     356:                     this.state = o.state;
     357:                 }
     358:             }
     359:         }
     360:         
     361:         //客戶端
     362:         public class Client{
     363:             private static Originator o;
     364:             private static MementoIF memento;
     365:             
     366:             public static void main(String args[]){
     367:                 o = new Originator();
     368:                 o.changeState("State 1");
     369:                 memento = o.createMemento();
     370:                 o.changeState("State 2");
     371:                 o.restoreMemento(memento);
     372:             }
     373:         }
     374:         

    模式的優(yōu)缺點(diǎn):
    由于“自述歷史”作為一個(gè)備忘錄模式的特殊實(shí)現(xiàn)形式非常簡(jiǎn)單易懂,它可能是備忘錄模式最為流行的實(shí)現(xiàn)形式。
    備忘錄模式的操作過程
    1、客戶端為發(fā)起人角色創(chuàng)建一個(gè)備忘錄對(duì)象。
    2、調(diào)用發(fā)起人對(duì)象的某個(gè)操作,這個(gè)操作是可以撤銷的。
    3、檢查發(fā)起人對(duì)象所出狀態(tài)的有效性。檢查的方式可以是發(fā)起人對(duì)象的內(nèi)部自查,也可以由某個(gè)外部對(duì)象進(jìn)行檢查。
    4、如果需要的話,將發(fā)起人的操作撤銷,也就是說根據(jù)備忘錄對(duì)象的記錄,將發(fā)起人對(duì)象的狀態(tài)恢復(fù)過來。
    “假如”協(xié)議模式的操作過程:
    1、將發(fā)起人對(duì)象做一個(gè)拷貝。
    2、在拷貝上執(zhí)行某個(gè)操作。
    3、檢查這個(gè)拷貝的狀態(tài)是否有效和自恰。
    4、如果檢查結(jié)果是無效或者不自恰的,那么扔掉這個(gè)拷貝,并觸發(fā)異常處理程序;相反,如果檢查是有效和自恰的,那么在原對(duì)象上執(zhí)行這個(gè)操作
    顯然這一做法對(duì)于撤銷一個(gè)操作并恢復(fù)操作前狀態(tài)較為復(fù)雜和困難的發(fā)起人對(duì)象來說是一個(gè)較為謹(jǐn)慎和有效的做法。
    “假如”協(xié)議模式的優(yōu)點(diǎn)和缺點(diǎn)
    具體來說,這個(gè)做法的長(zhǎng)處是可以保證發(fā)起人對(duì)象永遠(yuǎn)不會(huì)處于無效或不自恰的狀態(tài)上,這樣作的短處是成功的操作必須執(zhí)行兩次。
    如果操作的成功率較低的話,這樣做就比較劃算,反之就不太劃算。
    使用備忘錄模式的優(yōu)點(diǎn)和缺點(diǎn)
    一、備忘錄模式的優(yōu)點(diǎn)
    1、有時(shí)一些發(fā)起人對(duì)象的內(nèi)部信息必須保存在發(fā)起人對(duì)象以外的地方,但是必須要由發(fā)起人對(duì)象自己讀取,這時(shí),
       使用備忘錄模式可以把復(fù)雜的發(fā)起人內(nèi)部信息對(duì)其他的對(duì)象屏蔽起來,從而可以恰當(dāng)?shù)乇3址庋b的邊界。
    2、本模式簡(jiǎn)化了發(fā)起人類。發(fā)起人不再需要管理和保存其內(nèi)部狀態(tài)的一個(gè)個(gè)版本,客戶端可以自行管理他們所需
       要的這些狀態(tài)的版本。
    3、當(dāng)發(fā)起人角色的狀態(tài)改變的時(shí)候,有可能這個(gè)狀態(tài)無效,這時(shí)候就可以使用暫時(shí)存儲(chǔ)起來的備忘錄將狀態(tài)復(fù)原。
    二、備忘錄模式的缺點(diǎn):
    1、如果發(fā)起人角色的狀態(tài)需要完整地存儲(chǔ)到備忘錄對(duì)象中,那么在資源消耗上面?zhèn)渫泴?duì)象會(huì)很昂貴。
    2、當(dāng)負(fù)責(zé)人角色將一個(gè)備忘錄 存儲(chǔ)起來的時(shí)候,負(fù)責(zé)人可能并不知道這個(gè)狀態(tài)會(huì)占用多大的存儲(chǔ)空間,從而無法
       提醒用戶一個(gè)操作是否很昂貴。882——P
    3、當(dāng)發(fā)起人角色的狀態(tài)改變的時(shí)候,有可能這個(gè)協(xié)議無效。如果狀態(tài)改變的成功率不高的話,不如采取“假如”協(xié)議模式。

    posted on 2011-02-08 16:48 人在江湖 閱讀(3539) 評(píng)論(0)  編輯  收藏 所屬分類: design pattern
    主站蜘蛛池模板: 免费无码精品黄AV电影| 中文字幕乱码免费看电影| 最近免费最新高清中文字幕韩国 | 日韩中文字幕免费| 亚洲人成网站18禁止久久影院 | 亚洲精品午夜视频| 6080午夜一级毛片免费看| 亚洲自偷自拍另类12p| 91免费福利精品国产| 亚洲欧洲日本天天堂在线观看| 污视频在线免费观看| 亚洲成人午夜电影| 成人黄软件网18免费下载成人黄18免费视频| 国产精品亚洲精品观看不卡| 免费黄色大片网站| 色爽黄1000部免费软件下载| 亚洲综合精品香蕉久久网| 久操视频在线免费观看| 亚洲日韩中文字幕天堂不卡| 成人免费无遮挡无码黄漫视频| 久久久久亚洲国产AV麻豆| 久久久久亚洲av成人无码电影| 国产精品网站在线观看免费传媒| 亚洲激情电影在线| 日韩免费无砖专区2020狼| av片在线观看永久免费| 亚洲黄色免费电影| 免费的一级片网站| a级午夜毛片免费一区二区| 麻豆亚洲AV永久无码精品久久| 午夜私人影院免费体验区| 一级特黄aaa大片免费看| 在线电影你懂的亚洲| 国产精品成人无码免费| 免费萌白酱国产一区二区三区 | 2019中文字幕免费电影在线播放| 亚洲人成色4444在线观看| 精品国产亚洲男女在线线电影| 97公开免费视频| 色屁屁在线观看视频免费| 亚洲AV日韩AV高潮无码专区|