กลับไปหน้าบทความ

อ่าน 6 นาที

ลวดลายของที่ระลึก

รูป แบบ Memento เป็น รูปแบบการออกแบบซอฟต์แวร์ ในสาขา การเขียนโปรแกรมเชิงวัตถุ ที่ช่วยให้สามารถย้อนกลับสถานะของวัตถุได้ การใช้งานรูปแบบการออกแบบนี้ได้แก่การ ยกเลิก การกระทำ...

ลวดลายของที่ระลึก

รูปแบบ Mementoเป็นรูปแบบการออกแบบซอฟต์แวร์ในสาขาการเขียนโปรแกรมเชิงวัตถุที่ช่วยให้สามารถย้อนกลับสถานะของวัตถุได้ การใช้งานรูปแบบการออกแบบนี้ได้แก่การยกเลิกการกระทำ การควบคุมเวอร์ชันและการทำให้เป็นอนุกรม

รูปแบบ Memento ถูกนำไปใช้ด้วยวัตถุสามชิ้น ได้แก่ผู้สร้าง (originator ) ผู้ดูแล (caretaker)และสิ่ง เตือนใจ ( memento ) ผู้สร้างคือวัตถุที่มีสถานะภายใน ผู้ดูแลจะทำการเปลี่ยนแปลงบางอย่างกับผู้สร้าง แต่ต้องการที่จะสามารถย้อนกลับไปยังสถานะก่อนหน้าได้อย่างง่ายดาย ผู้ดูแลจะขอวัตถุสิ่งเตือนใจจากผู้สร้างก่อน จากนั้นจึงทำการเปลี่ยนแปลง (หรือลำดับของการเปลี่ยนแปลง) ที่ตั้งใจจะทำ เพื่อย้อนกลับไปยังสถานะก่อนการเปลี่ยนแปลง ผู้ดูแลจะส่งคืนวัตถุสิ่งเตือนใจให้กับผู้สร้าง วัตถุสิ่งเตือนใจนั้นไม่สามารถเปลี่ยนแปลงได้เมื่อใช้รูปแบบนี้ ควรระมัดระวังหากผู้สร้างอาจเปลี่ยนแปลงวัตถุหรือทรัพยากรอื่นๆ เนื่องจากรูปแบบ Memento ทำงานกับวัตถุเพียงชิ้นเดียว

ตัวอย่างคลาสสิกของรูปแบบนี้คือเครื่องกำเนิดเลขสุ่มเทียม (PRNG) ในกรณีนี้ ผู้ใช้ PRNG แต่ละรายทำหน้าที่เป็นผู้ดูแล ซึ่งสามารถเริ่มต้น PRNG (ผู้สร้าง) ด้วยค่าเริ่มต้นเฉพาะ (ของที่ระลึก) เพื่อสร้างลำดับเลขสุ่มเทียมที่เหมือนกัน

โครงสร้าง

แผนภาพคลาสและลำดับ UML

ตัวอย่างคลาส UML และไดอะแกรมลำดับสำหรับรูปแบบการออกแบบ Memento [ 1 ]

ในแผนภาพคลาส UML ข้างต้นCaretakerคลาสนี้หมายถึงOriginatorคลาสสำหรับการบันทึก ( createMemento()) และการกู้คืน ( restore(memento)) สถานะภายในของผู้สร้าง คลาส นี้Originatorดำเนินการ (1) createMemento()โดยการสร้างและส่งคืนMementoอ็อบเจ็กต์ที่เก็บสถานะภายในปัจจุบันของผู้สร้าง และ (2) restore(memento)โดยการกู้คืนสถานะจากMementoอ็อบเจ็กต์ ที่ส่งผ่านเข้ามา

แผนภาพ ลำดับ UMLแสดงปฏิสัมพันธ์ขณะรันไทม์: (1) การบันทึกสถานะภายในของผู้สร้าง: Caretakerวัตถุเรียกใช้createMemento()บนOriginatorวัตถุ ซึ่งสร้างMementoวัตถุ บันทึกสถานะภายในปัจจุบัน ( setState()) และส่งคืนMementoไปยัง (2) การกู้คืนสถานะภายในของผู้สร้าง: Caretakerเรียก ใช้บนวัตถุ และระบุวัตถุที่จัดเก็บสถานะที่ควรกู้คืน จะได้รับสถานะ ( ) จากเพื่อตั้งค่าสถานะของตนเอง Caretakerrestore(memento)OriginatorMementoOriginatorgetState()Memento

ตัวอย่างภาษา Java

โปรแกรม Java ต่อไปนี้แสดงตัวอย่างการใช้งาน "ยกเลิก" (undo) ของรูปแบบ memento

แพ็คเกจorg.wikipedia.examples ;import java.util.ArrayList ; import java.util.List ;คลาสOriginator { private String state ; // คลาสนี้ยังสามารถมีข้อมูลเพิ่มเติมที่ไม่ใช่ส่วนหนึ่งของ // สถานะที่บันทึกไว้ใน Memento ได้อีกด้วย public void set(String state) { this.state = state ; System.out.printf ( " Originator : Setting state to % s % n " , state ) ; } public Memento saveToMemento ( ) { System.out.println ( " Originator : Saving to Memento ." ) ; return new Memento ( this.state ) ; } public void restoreFromMemento ( Memento memento ) { this.state = memento.getSavedState (); System.out.printf ( " Originator : State after restoring from Memento : % s % n " , state ) ; } public static class Memento { private final String state ;public Memento ( String stateToSave ) { state = stateToSave ; } // เข้าถึงได้เฉพาะคลาสภายนอกเท่านั้นprivate String getSavedState () { return state ; } } } class Caretaker { public static void main ( String [] args ) { List < Originator . Memento > savedStates = new ArrayList < Originator . Memento > (); Originator originator = new Originator (); originator . set ( "State1" ); originator . set ( "State2" ); savedStates . add ( originator . saveToMemento ()); originator . set ( "State3" ); // เราสามารถขอ memento ได้หลายรายการ และเลือกรายการที่จะย้อนกลับไปsavedStates . add ( originator . saveToMemento ()); originator . set ( "State4" ); originator . restoreFromMemento ( savedStates . get ( 1 )); } }

ผลลัพธ์คือ:

ผู้ริเริ่ม: กำหนดสถานะเป็น State1 ผู้ริเริ่ม: ตั้งค่าสถานะเป็น State2 ผู้ริเริ่ม: การบันทึกไปยัง Memento ผู้ริเริ่ม: ตั้งค่าสถานะเป็น State3 ผู้ริเริ่ม: การบันทึกไปยัง Memento ผู้ริเริ่ม: ตั้งค่าสถานะเป็น State4 ผู้สร้าง: สถานะหลังจากกู้คืนจาก Memento: สถานะ 3 

ตัวอย่างนี้ใช้สตริงเป็นสถานะ ซึ่งเป็นอ็อบเจ็กต์ที่ไม่สามารถเปลี่ยนแปลงได้ใน Java ในสถานการณ์จริง สถานะมักจะเป็นอ็อบเจ็กต์ที่สามารถเปลี่ยนแปลงได้ ดังนั้นจึงจำเป็นต้องสร้างสำเนาของสถานะนั้น

ต้องยอมรับว่าการใช้งานที่แสดงอยู่นี้มีข้อเสียอยู่บ้าง คือ มันประกาศคลาสภายใน จะเป็นการดีกว่าหากกลยุทธ์การจดจำนี้สามารถนำไปใช้กับผู้สร้างมากกว่าหนึ่งรายได้

โดยหลักแล้วมีอีกสามวิธีที่จะได้รับ Memento:

  1. การแปลงเป็นอนุกรม (Serialization)
  2. คลาสที่ประกาศไว้ในแพ็กเกจเดียวกัน
  3. นอกจากนี้ ยังสามารถเข้าถึงวัตถุผ่านพร็อกซี ซึ่งสามารถดำเนินการบันทึก/กู้คืนข้อมูลใดๆ บนวัตถุได้

ตัวอย่าง C#

รูปแบบ Memento ช่วยให้สามารถบันทึกสถานะภายในของวัตถุได้โดยไม่ละเมิดหลักการห่อหุ้มข้อมูล (encapsulation) ทำให้สามารถยกเลิก/ย้อนกลับการเปลี่ยนแปลงได้ในภายหลังหากจำเป็น ในที่นี้จะเห็นได้ว่าวัตถุ Mementoถูกนำมาใช้เพื่อย้อนกลับการเปลี่ยนแปลงที่เกิดขึ้นกับวัตถุนั้น

เนมสเปซWikipedia.Examples ;คลาสMemento { private readonly string _savedState ;private Memento ( string stateToSave ) { _savedState = stateToSave ; }public class Originator { private string _state ; // คลาสนี้ยังสามารถมีข้อมูลเพิ่มเติมที่ไม่ใช่ส่วนหนึ่งของ// สถานะที่บันทึกไว้ใน memento ได้ อีกด้วยpublic void Set ( string state ) { Console.WriteLine ( f " Originator: Setting state to {state}" ); _state = state ; }public Memento SaveToMemento () { Console . WriteLine ( "Originator: Saving to Memento." ); return new Memento ( _state ); }public void RestoreFromMemento ( Memento memento ) { _state = memento . savedState ; Console . WriteLine ( f "Originator: State after restoring from Memento: {_state}" ); } } }คลาสCaretaker { static void Main ( string [] args ) { List < Memento > savedStates = new ();Memento.Originator originator = new (); originator.Set ( " State1" ); originator.Set ( "State2" ); savedStates.Add ( originator.SaveToMemento ( ) ) ; originator.Set ( " State3" ); // เราสามารถ ขอ memento ได้ หลาย รายการ และเลือกรายการ ที่จะย้อนกลับไปsavedStates.Add ( originator.SaveToMemento ( ) ) ; originator.Set ( " State4 " ) ;originator.RestoreFromMemento ( savedStates [ 1 ] ) ; } }

ตัวอย่าง Python

""" ตัวอย่างลวดลายของที่ระลึก"""คลาสOriginator : สถานะ: str = ""def set ( self , state : str ) - > None : print ( f "Originator: Setting state to { state } " ) self.state = statedef save_to_memento ( self ) - > " Memento " : return self.Memento ( self.state )def restore_from_memento ( self , memento : "Memento" ) -> None : self . state = memento . get_saved_state () print ( f "Originator: State after restoring from Memento: { self . state } " )คลาสMemento : สถานะ: strdef __init__ ( self , state : str ) -> None : self . state = statedef get_saved_state ( self ) - > str : return self.statesaved_states : รายการ[ Memento ] = [] originator : Originator = Originator ()originator.set ( " State1 " ) originator.set ( " State2 " ) saved_states.append ( originator.save_to_memento ( ) )originator.set ( " State3 " ) saved_states.append ( originator.save_to_memento ( ) )originator.set ( " State4 " )originator.restore_from_memento ( saved_states [ 1 ] )

ตัวอย่าง JavaScript

// รูปแบบ Memento ใช้สำหรับบันทึกและเรียกคืนสถานะของวัตถุ// Memento คือภาพรวมของสถานะของวัตถุlet Memento = { // Namespace: Memento savedState : null , // สถานะที่บันทึกไว้ของวัตถุบันทึก: ฟังก์ชัน( สถานะ) { // บันทึกสถานะของวัตถุthis.savedState = state ; } ,restore : function () { // คืนค่าสถานะของวัตถุreturn this . savedState ; } };// Originator คือวัตถุที่สร้าง memento // กำหนดเมธอดสำหรับบันทึกสถานะภายใน memento let Originator = { // เนมสเปซ: Originator state : null , // สถานะที่จะจัดเก็บ// สร้างผู้สร้างใหม่โดยมีสถานะเริ่มต้นเป็น null createMemento : function () { return { state : this . state // สถานะจะถูกคัดลอกไปยัง memento }; }, setMemento : function ( memento ) { // ตั้งค่าสถานะของผู้สร้างจาก memento this . state = memento . state ; } };// ผู้ดูแลจะจัดเก็บของที่ระลึกของวัตถุและ// มีการดำเนินการเพื่อเรียกค้นของที่ระลึกเหล่านั้นlet Caretaker = { // เนมสเปซ: Caretaker mementos : [], // ของที่ระลึกของวัตถุaddMemento : function ( memento ) { // เพิ่มของที่ระลึกลงในคอลเลก ชัน this . mementos . push ( memento ); }, getMemento : function ( index ) { // ดึงของที่ระลึกจากคอลเลกชันreturn this . mementos [ index ]; } };let action_step = "Foo" ; // การกระทำที่จะดำเนินการ/สถานะของวัตถุที่จะถูกจัดเก็บlet action_step_2 = "Bar" ; // การกระทำที่จะดำเนินการ/สถานะของวัตถุที่จะถูกจัดเก็บ// กำหนดสถานะเริ่มต้นOriginator.state = action_step ; Caretaker.addMemento ( Originator.createMemento ( ) ); // บันทึกสถานะลงในประวัติconsole.log ( " สถานะเริ่มต้น: " + Originator.state ) ; // Foo// เปลี่ยนสถานะOriginator.state = action_step_2 ; Caretaker.addMemento ( Originator.createMemento ( ) ); // บันทึกสถานะลงในประวัติconsole.log ( " State After Change: " + Originator.state ) ; // แถบ// คืนค่าสถานะแรก - ยกเลิกOriginator.setMemento ( Caretaker.getMemento ( 0 ) ) ; console.log ( " State After Undo: " + Originator.state ) ; // Foo// คืน ค่าสถานะที่สอง - ทำซ้ำOriginator.setMemento ( Caretaker.getMemento ( 1 ) ) ; console.log ( " สถานะหลังทำซ้ำ: " + Originator.state ) ; // แถบ
  • คำอธิบายลวดลาย Memento ในภาษาเอดา
  • แผนภาพคลาส UML ของ Memento พร้อมตัวอย่างโค้ด C# และ .NET
  • บทช่วยสอนการสร้างซอร์สโค้ด
  • รูปแบบการออกแบบ Memento โดยใช้ภาษา Java
ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=Memento_pattern&oldid=1348708191 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ ลวดลายของที่ระลึก

รูป แบบ Memento เป็น รูปแบบการออกแบบซอฟต์แวร์ ในสาขา การเขียนโปรแกรมเชิงวัตถุ ที่ช่วยให้สามารถย้อนกลับสถานะของวัตถุได้ การใช้งานรูปแบบการออกแบบนี้ได้แก่การ ยกเลิก การกระทำ...

แผนภาพคลาสและลำดับ UML

ในแผนภาพคลาส UML ข้างต้น Caretaker คลาสนี้หมายถึง Originator คลาสสำหรับการบันทึก ( createMemento() ) และการกู้คืน ( restore(memento) ) สถานะภายในของผู้สร้าง คลาส นี้ Originator ดำเนินการ (1) createMemento() โดยการสร้างและส่งคืน Memento...

ตัวอย่างภาษา Java

โปรแกรม Java ต่อไปนี้แสดงตัวอย่างการใช้งาน "ยกเลิก" (undo) ของรูปแบบ memento

ตัวอย่าง C#

รูปแบบ Memento ช่วยให้สามารถบันทึกสถานะภายในของวัตถุได้โดยไม่ละเมิดหลักการห่อหุ้มข้อมูล (encapsulation) ทำให้สามารถยกเลิก/ย้อนกลับการเปลี่ยนแปลงได้ในภายหลังหากจำเป็น ในที่นี้จะเห็นได้ว่า วัตถุ Memento ถูกนำมาใช้เพื่อ ย้อนกลับ...