Java สถานะรูปแบบ สถานะ
อนุญาตให้วัตถุเปลี่ยนแปลงพฤติกรรมขึ้นอยู่กับสถานะภายใน จากภายนอกดูเหมือนว่าคลาสของวัตถุมีการเปลี่ยนแปลง
รูปแบบ "สถานะ" เกี่ยวข้องกับการจัดสรรคลาสพื้นฐานหรืออินเทอร์เฟซสำหรับการดำเนินการที่ถูกต้องทั้งหมดและผู้สืบทอดสำหรับแต่ละสถานะที่เป็นไปได้
เมื่อใดจึงจะใช้รูปแบบของรัฐ
เมื่อพฤติกรรมของวัตถุต้องขึ้นอยู่กับสถานะและสามารถเปลี่ยนแปลงแบบไดนามิกได้ที่รันไทม์
เมื่อโค้ดของเมธอดของอ็อบเจ็กต์ใช้โครงสร้างแบบมีเงื่อนไขจำนวนมาก การเลือกจะขึ้นอยู่กับสถานะปัจจุบันของอ็อบเจ็กต์
แผนภาพ UML ของรูปแบบ "สถานะ":
การใช้รูปแบบ "สถานะ" ใน C #
ใช้ระบบ; เนมสเปซ DoFactory.GangOfFour.State.Structural ( ///ตัวอย่างรูปแบบรัฐจากชีวิตจริง
ตัวอย่างใน .NET Framework
- CommunicationObject ใช้เครื่องสถานะสำหรับการเปลี่ยนระหว่างสถานะไคลเอ็นต์ WCF: สร้าง เปิด เปิด ปิด ปิด และผิดพลาด
- งานใช้เครื่องสถานะจำกัดสำหรับการเปลี่ยนระหว่างสถานะของงาน: สร้างแล้ว กำลังรอการเปิดใช้งาน กำลังรอเรียกใช้ ทำงาน กำลังดำเนินการจนเสร็จสมบูรณ์ ยกเลิก ผิดพลาด
ในระบอบการปกครองของรัฐ (แบบจำลองรัฐ) พฤติกรรมของชั้นเรียนจะขึ้นอยู่กับสถานะที่เปลี่ยนแปลงไป รูปแบบการออกแบบประเภทนี้หมายถึงแบบจำลองเชิงพฤติกรรม
ในโมเดลสถานะ เราสร้างออบเจ็กต์และสถานะพฤติกรรมต่างๆ พร้อมกับสถานะของออบเจ็กต์ที่ได้รับการแก้ไขโดยการแสดงบริบทของออบเจ็กต์ที่ปรับเปลี่ยน
การแนะนำ
เจตนา: อนุญาตให้วัตถุเปลี่ยนพฤติกรรมเมื่อสถานะภายในเปลี่ยนแปลง จากนั้นวัตถุดูเหมือนจะเปลี่ยนคลาส
แก้ปัญหาเป็นหลัก: พฤติกรรมของวัตถุขึ้นอยู่กับสถานะ (คุณลักษณะ) และคุณสามารถเปลี่ยนแปลงได้ตามสถานะที่เกี่ยวข้องกับการเปลี่ยนแปลงพฤติกรรม
เมื่อใดควรใช้: รหัสประกอบด้วยออบเจ็กต์จำนวนมากที่เกี่ยวข้องกับสถานะของคำสั่งแบบมีเงื่อนไข
วิธีแก้ไข: สถานะของคลาสนามธรรมที่เป็นรูปธรรมดับแล้ว
รหัสคีย์: โหมดอินเทอร์เฟซคำสั่งโดยปกติจะมีเพียงวิธีเดียวเท่านั้นสถานะของอินเทอร์เฟซที่มีหนึ่งหรือหลายวิธี นอกจากนี้ เมธอดโหมดสถานะของคลาสการใช้งานมักจะส่งคืนค่าหรือเปลี่ยนค่าของตัวแปรอินสแตนซ์ นั่นคือสถานะและสถานะของโมเดลออบเจ็กต์มักจะเป็นข้อมูลล่าสุด วิธีการเรียนการใช้งานมีฟังก์ชั่นต่าง ๆ วิธีการอินเตอร์เฟซจะครอบคลุม โหมดเงื่อนไขและโหมดคำสั่งเดียวกันสามารถใช้เพื่อกำจัดเงื่อนไขอื่น ๆ ได้หาก... การเลือกอื่น
ตัวอย่างการใช้งาน: 1 การเล่นบาสเก็ตบอล ผู้เล่นสามารถมีสภาวะปกติ ไม่ใช่สภาวะปกติ และสภาวะผิดปกติได้ 2, Marquise Yi Zeng bells จากนั้น "clock abstract interface", "clock A" และสถานะที่เป็นรูปธรรมอื่น ๆ สภาพแวดล้อมเฉพาะ "" ระฆังจีน (บริบท)
ข้อดี: 1 สรุปกฎการเปลี่ยนแปลง 2 ระบุสถานะที่เป็นไปได้ก่อนที่จะแสดงรายการรัฐจำเป็นต้องกำหนดสถานะของชนิด 3 ทุกอย่างที่มีพฤติกรรมของรัฐนั้นเกี่ยวข้องกับคลาส และคุณสามารถเพิ่มสถานะใหม่ได้อย่างง่ายดาย คุณเพียงแค่ต้องเปลี่ยนสถานะของวัตถุก็สามารถเปลี่ยนพฤติกรรมของวัตถุได้ เวอร์ชัน 4 ซึ่งทำให้สามารถทำการเปลี่ยนแปลงสถานะได้ - สถานะตรรกะของวัตถุในหนึ่งเดียว แทนที่จะเป็นบล็อกคำสั่งแบบมีเงื่อนไขขนาดใหญ่เพียงบล็อกเดียว 5 อนุญาตให้หลายอ็อบเจ็กต์แบ่งปันสภาพแวดล้อมสถานะของอ็อบเจ็กต์ ซึ่งจะช่วยลดจำนวนอ็อบเจ็กต์ในระบบ
ข้อเสีย: 1 รูปแบบสถานะการใช้งานสัมพันธ์กับการเพิ่มจำนวนคลาสและอ็อบเจ็กต์ของระบบ 2 โครงสร้างและการดำเนินการของแบบฟอร์มสถานะมีความซับซ้อนมากขึ้นหากใช้ไม่ถูกต้องอาจทำให้เกิดความสับสนในโครงสร้างโปรแกรมและโค้ดได้ 3 การสนับสนุนโมเดลสถานะ "หลักการเปิดแบบเปิด" ไม่ค่อยดีนัก คุณสามารถเปลี่ยนสถานะของโมเดลสถานะได้โดยการเพิ่มคลาสใหม่ คุณต้องเปลี่ยนสถานะของผู้ที่รับผิดชอบในการเปลี่ยนสถานะซอร์สโค้ด หรือไม่สามารถเปลี่ยนไปใช้ สถานะใหม่และเปลี่ยนสถานะของคลาสให้ดำเนินการเช่นกัน จำเป็นต้องแก้ไขซอร์สโค้ดของคลาสที่เกี่ยวข้อง
กรณีการใช้งาน: 1 พร้อมการเปลี่ยนแปลงสถานะและพฤติกรรมการเปลี่ยนฉาก 2 การยืนยันการเปลี่ยนแปลงแบบมีเงื่อนไขโดยการแทนที่
หมายเหตุ: เมื่อใช้พฤติกรรมสถานะที่จำกัดตามโหมดสถานะ และสถานะจะไม่เกินห้า
การดำเนินการ
เราจะสร้างอินเทอร์เฟซสถานะและเอนทิตี สถานะคลาสการใช้งานอินเทอร์เฟซ สถานะ.บริบทแสดงถึงคลาสที่มีสถานะเฉพาะ
รัฐรูปแบบสาธิต,เราสาธิตการใช้วัตถุ บริบทบริบทของชั้นเรียนและสถานะเพื่อแสดงการเปลี่ยนแปลงพฤติกรรมในสภาวะของการเปลี่ยนแปลง
ขั้นตอนที่ 1
สร้างอินเทอร์เฟซ
State.java
สถานะอินเทอร์เฟซสาธารณะ ( doAction โมฆะสาธารณะ (บริบทบริบท); )
ขั้นตอนที่ 2
สร้างคลาสเอนทิตีที่ใช้อินเทอร์เฟซ
StartState.java
คลาสสาธารณะ StartState ใช้สถานะ ( public void DoAction(บริบทบริบท) ( System.out.println("Player is in beginning state"); context.setState(this); ) public String ToString() (return "starting state"; ) )
StopState.java
คลาสสาธารณะ StopState ใช้สถานะ ( public void doAction(Context context) ( System.out.println("Player is in stop state"); context.setState(this); ) public String toString())( return "Stop State"; ) )
ขั้นตอนที่ 3
การสร้างชั้นเรียน บริบท.
บริบท.java
คลาสสาธารณะ (บริบทของรัฐรัฐเอกชน; บริบทสาธารณะ () (รัฐ = NULL; ) โมฆะสาธารณะ SetState (รัฐรัฐ) ( this.state = รัฐ; ) รัฐสาธารณะ GetState () (สถานะกลับมา; ))
ขั้นตอนที่ 4
ใช้ บริบทเพื่อดูพฤติกรรมเมื่อสถานะการเปลี่ยนแปลงเปลี่ยนแปลง เงื่อนไข.
StatePatternDemo.java
คลาสสาธารณะ StatePatternDemo (สถานะแรงคงที่ของรัฐ main (สตริง) (บริบทบริบท agdz = บริบทใหม่ (); StartState startState = new StartState (); startState.doAction (บริบท); System.out.println (context.getState ()) ToString ( ) .); StopState stopState = new StopState().));
ขั้นตอนที่ 5
ตรวจสอบผลลัพธ์
ผู้เล่นอยู่ในสถานะเริ่มต้น สถานะเริ่ม ผู้เล่นอยู่ในสถานะหยุด หยุดแล้ว
ใช้ระบบ; สถานะเนมสเปซ ( ///
ชื่อรูปแบบและการจำแนกประเภท
รัฐเป็นรูปแบบพฤติกรรมของวัตถุ
วัตถุประสงค์ของแบบแผนของรัฐ
รูปแบบสถานะอนุญาตให้วัตถุเปลี่ยนพฤติกรรมขึ้นอยู่กับสถานะภายใน ปรากฏว่าวัตถุได้เปลี่ยนคลาสของมัน
รูปแบบสถานะคือการดำเนินการเชิงวัตถุของเครื่องสถานะ
ปัญหาที่ต้องแก้ไข
พฤติกรรมของอ็อบเจ็กต์ขึ้นอยู่กับสถานะและต้องเปลี่ยนแปลงระหว่างการทำงานของโปรแกรม โครงการดังกล่าวสามารถนำไปใช้ได้โดยใช้ตัวดำเนินการตามเงื่อนไขหลายตัว: การดำเนินการบางอย่างจะดำเนินการตามการวิเคราะห์สถานะปัจจุบันของวัตถุ อย่างไรก็ตาม ด้วยสถานะจำนวนมาก ข้อความสั่งแบบมีเงื่อนไขจะกระจัดกระจายไปทั่วโค้ด และโปรแกรมดังกล่าวจะรักษาได้ยาก
รูปแบบของรัฐแก้ไขปัญหานี้ดังนี้:
- แนะนำคลาสบริบทซึ่งกำหนดส่วนต่อประสานกับโลกภายนอก
- แนะนำคลาสรัฐนามธรรม
- แสดงถึง "สถานะ" ต่างๆ ของเครื่องสถานะเป็นคลาสย่อยของ State
- คลาสบริบทมีตัวชี้ไปยังสถานะปัจจุบัน ซึ่งจะเปลี่ยนแปลงเมื่อสถานะของเครื่องสถานะเปลี่ยนแปลง
รูปแบบสถานะไม่ได้กำหนดว่าเงื่อนไขในการเปลี่ยนไปสู่สถานะใหม่ถูกกำหนดไว้ที่ใด มีสองตัวเลือก: คลาสบริบทหรือคลาสย่อยของรัฐ ข้อดีของตัวเลือกหลังคือสามารถเพิ่มคลาสที่ได้รับใหม่ๆ ได้อย่างง่ายดาย ข้อเสียคือแต่ละคลาสย่อยของรัฐจะต้องรู้เกี่ยวกับเพื่อนบ้านของตนเพื่อทำการเปลี่ยนผ่านไปสู่สถานะใหม่ ซึ่งทำให้เกิดการพึ่งพาระหว่างคลาสย่อย
นอกจากนี้ยังมีแนวทางอื่นที่ใช้ตารางในการออกแบบเครื่องจักรสถานะจำกัด โดยอิงจากการใช้ตารางที่แมปข้อมูลอินพุตกับการเปลี่ยนระหว่างสถานะโดยไม่ซ้ำกัน อย่างไรก็ตาม วิธีการนี้มีข้อเสีย: เป็นการยากที่จะเพิ่มการดำเนินการเมื่อดำเนินการเปลี่ยนภาพ แนวทางรูปแบบสถานะใช้โค้ด (แทนโครงสร้างข้อมูล) เพื่อทำการเปลี่ยนระหว่างสถานะ ดังนั้นจึงเพิ่มการดำเนินการเหล่านี้ได้ง่าย
โครงสร้างรูปแบบของรัฐ
คลาสบริบทกำหนดอินเทอร์เฟซภายนอกสำหรับไคลเอนต์และจัดเก็บการอ้างอิงถึงสถานะปัจจุบันของวัตถุสถานะ อินเทอร์เฟซของสถานะคลาสฐานนามธรรมจะเหมือนกับอินเทอร์เฟซบริบท ยกเว้นพารามิเตอร์เพิ่มเติมหนึ่งรายการ - ตัวชี้ไปยังอินสแตนซ์บริบท คลาสที่ได้มาจากรัฐจะกำหนดพฤติกรรมเฉพาะของรัฐ คลาส Wrapper บริบทมอบหมายคำขอที่ได้รับทั้งหมดให้กับออบเจ็กต์ "สถานะปัจจุบัน" ซึ่งสามารถใช้พารามิเตอร์เพิ่มเติมที่ได้รับเพื่อเข้าถึงอินสแตนซ์บริบท
แผนภาพคลาส UML ของรูปแบบรัฐโครงสร้างของรูปแบบสถานะแสดงไว้ในรูปที่ 1 71.
บริบท setState (StateTwo);
ข้าว. 71. แผนภาพ UML ของรูปแบบรัฐ
ผู้เข้าร่วม
บริบท - บริบท:
- กำหนดอินเทอร์เฟซที่สนใจให้กับลูกค้า
- เก็บอินสแตนซ์ของคลาสย่อย ConcreteState ที่กำหนดสถานะปัจจุบัน
สถานะ: กำหนดอินเทอร์เฟซสำหรับการสรุปพฤติกรรมที่เกี่ยวข้องกับสถานะบริบทเฉพาะ
คลาสย่อย StateOne, StateTwo, StateThree - สถานะเฉพาะ: แต่ละคลาสย่อยใช้พฤติกรรมที่เกี่ยวข้องกับสถานะของบริบท
ความสัมพันธ์
คลาสบริบทมอบหมายคำขอที่ขึ้นกับสถานะให้กับอ็อบเจ็กต์ ConcreteState ปัจจุบัน
บริบทสามารถส่งผ่านตัวเองเป็นอาร์กิวเมนต์ไปยังวัตถุ State ที่จะประมวลผลคำขอได้ ซึ่งช่วยให้วัตถุสถานะสามารถเข้าถึงบริบทได้เมื่อจำเป็น
บริบทเป็นอินเทอร์เฟซหลักสำหรับลูกค้า ลูกค้าสามารถกำหนดค่าบริบทด้วยวัตถุสถานะ เมื่อกำหนดค่าบริบทแล้ว ไคลเอ็นต์ไม่จำเป็นต้องสื่อสารโดยตรงกับออบเจ็กต์สถานะอีกต่อไป
คลาสย่อย Context หรือ ConcreteState สามารถตัดสินใจได้ภายใต้เงื่อนไขใดและสถานะการเปลี่ยนแปลงลำดับใด
ตัวอย่างรูปแบบของรัฐ
รูปแบบสถานะอนุญาตให้วัตถุเปลี่ยนพฤติกรรมขึ้นอยู่กับสถานะภายใน ภาพที่คล้ายกันสามารถสังเกตได้ในการทำงานของเครื่องจำหน่ายสินค้าอัตโนมัติ ตู้จำหน่ายสินค้าอัตโนมัติอาจมีสถานะที่แตกต่างกันขึ้นอยู่กับความพร้อมของสินค้า จำนวนเหรียญที่ได้รับ ความเป็นไปได้ในการแลกเปลี่ยนเงิน ฯลฯ หลังจากที่ผู้ซื้อเลือกและชำระค่าสินค้าแล้ว สถานการณ์ (สถานะ) ต่อไปนี้จะเป็นไปได้:
- มอบสินค้าให้กับผู้ซื้อโดยไม่จำเป็นต้องเปลี่ยนแปลง
- ให้ผู้ซื้อสินค้าและการเปลี่ยนแปลง;
- ผู้ซื้อจะไม่ได้รับสินค้าเนื่องจากขาดเงินเพียงพอ
- ผู้ซื้อจะไม่ได้รับสินค้าเนื่องจากไม่มีสินค้า
การใช้รูปแบบของรัฐ
กำหนดคลาส wrapper บริบทที่มีอยู่หรือสร้างใหม่ที่ไคลเอ็นต์จะใช้เป็นเครื่องสถานะ
สร้างคลาสสถานะพื้นฐานที่จำลองแบบอินเทอร์เฟซของคลาสบริบท แต่ละวิธีใช้พารามิเตอร์เพิ่มเติมหนึ่งตัว: อินสแตนซ์ของคลาสบริบท คลาส State สามารถกำหนดพฤติกรรมเริ่มต้นที่เป็นประโยชน์ได้
สร้างคลาสที่ได้มาจากรัฐสำหรับรัฐที่เป็นไปได้ทั้งหมด
คลาสบริบทเพียงมอบหมายคำขอทั้งหมดที่ได้รับจากไคลเอนต์ไปยังวัตถุ "สถานะปัจจุบัน" และที่อยู่ของวัตถุบริบทจะถูกส่งผ่านเป็นพารามิเตอร์เพิ่มเติม
การใช้ที่อยู่นี้ วิธีการของคลาส State สามารถเปลี่ยน "สถานะปัจจุบัน" ของคลาส Context ได้หากจำเป็น
การดำเนินการตามรูปแบบของรัฐ
ลองพิจารณาตัวอย่างของเครื่องสถานะจำกัดที่มีสถานะที่เป็นไปได้สองสถานะและสองเหตุการณ์
ใช้เนมสเปซมาตรฐาน;
สถานะคลาส * ปัจจุบัน; สาธารณะ:
เป็นโมฆะ setCurrent (สถานะ * s)
เป็นโมฆะเมื่อ (); เป็นโมฆะปิด ();
โมฆะเสมือนบน (เครื่อง * m)
โมฆะเสมือนของ T (เครื่อง * m)
เครื่องเป็นโมฆะ::on()
ปัจจุบัน -> เปิด (นี้);
เครื่องเป็นโมฆะ::ปิด()
ปัจจุบัน -> ปิด (นี่);
ชั้นเรียน ON: รัฐสาธารณะ
เป็นโมฆะปิด (เครื่อง * m);
คลาสปิด: รัฐสาธารณะ
เป็นโมฆะบน(เครื่อง *m)
ศาล setCurrent (เปิดใหม่ ()); ลบสิ่งนี้;
เป็นโมฆะ ON::off (เครื่อง * m)
ศาล setCurrent (ปิดใหม่ ()); ลบสิ่งนี้;
เครื่อง::เครื่อง()
ปัจจุบัน = ปิดใหม่ (); ศาล
เป็นโมฆะ(เครื่อง:: *ptrs)() =
เครื่อง::ปิด เครื่อง::เปิด
เครื่องจักร fsm; หมายเลข int; ในขณะที่ (1)
(fsm. *ptrs)