แนวคิดการออกแบบซอฟแวร์เชิงวัตถุ (Object-Oriented Software Design)
แนวคิดของการออกแบบซอฟแวร์เชิงวัตถุ
เพื่อให้ซอฟแวร์ที่พัฒนาขึ้นมีลักษณะเป็นส่วนประกอบที่ชัดเจน
และมีโครงสร้างที่ยืดหยุ่นเพียงพอสำหรับการเปลี่ยนแปลง แก้ไขที่จะเกิดขึ้นในอนาคต
เราจำเป็นต้องใช้วิธีการเชิงวัตถุในการออกแบบ
และพัฒนาซอฟแวร์ร่วมด้วย ลักษณะของวัตถุที่ประกอบอยู่ในระบบงานจะมีวัตถุหลายชนิดขึ้นอยู่กับการวิเคราะห์ระบบ
ซึ่งอาจจะมีทั้งวัตถุที่เป็นตัวแทนของวัตถุจริงในโลกที่เราอาศัยอยู่ (Real-World
Object) หรือวัตถุที่สมมุติขึ้นมาเพื่อให้ทำหน้าที่บางอย่างในระบบงาน
(Imaginary Object)
วัตถุจะมีองค์ประกอบสองอย่างคือ
ส่วนข้อมูล เรียกว่าแอททริบิวท์ และส่วนการกระทำ เรียกว่าเมธอด ส่วนข้อมูลใช้สำหรับเก็บข้อมูลที่เป็นคุณสมบัติเฉพาะของวัตถุชนิดนั้น
เช่น ถ้าเป็นวัตถุรถยนต์ส่วนข้อมูลจะได้แก่ สี ขนาด น้ำหนัก ราคา หรือ ยี่ห้อ
เป็นต้น สำหรับส่วนการกระทำ ใช้สำหรับบอกให้รู้ว่าวัตถุสามารถทำอะไรหรือถูกกระทำอะไรได้บ้าง
ตัวอย่างเช่น วัตถุรถยนต์ อาจจะมีส่วนการกระทำคือ รถยนต์วิ่ง
รถยนต์กำลังเร่งเครื่อง รถยนต์กำลังหยุดเครื่อง รถยนต์ถูกซื้อมาและขายไป เป็นต้น
คลาส
ชนิดของวัตถุเราเรียกว่า
คลาส คลาสเป็นเหมือนแม่พิมพ์ของวัตถุ ซึ่งภายในคลาสจะใช้กำหนดว่าวัตถุที่ถูกสร้างขึ้นจากคลาสนี้จะมีส่วนข้อมูลและส่วนการกระทำเป็นอย่างไร
ดังนั้น
วัตถุที่เกิดขึ้นมาจากคลาสเดียวกันจะมีส่วนข้อมูลและส่วนการกระทำเป็นรูปแบบเดียวกัน
แต่หลังจากที่วัตถุทำงานไปได้ระยะเวลาหนึ่งแล้ว วัตถุชนิดเดียวกันอาจจะมีข้อมูลบางอย่างที่แตกต่างกันไปแล้วแต่สถานะที่กำลังเป็นอยู่ในขณะนั้นก็ได้
ถ้าจะเปรียบเทียบกับวัตถุในโลกความจริงเราอาจจะเปรียบเทียบคลาสได้เหมือนกับเป็นพิมพ์เขียวหรือแบบที่ใช้สำหรับก่อสร้างสิ่งต่าง
ๆ เช่น แบบบ้าน แบบรถยนต์
และวัตถุที่สร้างขึ้นตามพิมพ์เขียวเดียวกันจะปรากฏออกมารูปร่างหน้าตาเหมือน ๆ กัน ตัวอย่างเช่น
รถยนต์ที่ผลิตขึ้นมาในรุ่นเดียวกันจะมีคุณลักษณะเหมือนกันเนื่องจากใช้แม่แบบเดียวกันในการผลิต
ในการใช้งานจริงเราไม่สามารถนำคลาสไปใช้งานได้โดยตรงแต่เราจะต้องนำคลาสมาสร้างเป็นวัตถุก่อน
แล้วจึงสั่งให้วัตถุทำงานตามที่เราต้องการ
เช่นเดียวกับที่เราไม่สามารถขับขี่แม่แบบของรถยนต์ (ซึ่งเป็นกระดาษพิมพ์เขียว
เปรียบเหมือนกับคลาส)
แต่เราจะต้องนำแม่แบบไปสร้างเป็นตัวรถยนต์ออกมาก่อนเราจึงจะสามารถขับขี่รถยนต์
(ซึ่งเป็นวัตถุ) ได้
จากภาพที่
1 เราจะเห็นตัวอย่างการออกแบบคลาส Patient (ผู้ป่วย)
ซึ่งประกอบด้วยแอททริบิวท์[1]คือ id หมายถึงรหัสของผู้ป่วย firstName คือชื่อผู้ป่วย dateOfBirth
คือวันเดือนปีเกิดของผู้ป่วย สำหรับเมธอดที่ผู้ป่วยสามารถกระทำ
(หรือถูกกระทำ) ได้แก่ register คือลงทะเบียนผู้ป่วย และ transferTo
คือย้ายสถานพยาบาล ในตัวอย่างนี้เป็นเพียงตัวอย่างเล็ก ๆ เพื่อแสดงให้เห็นถึงการออกแบบคลาสที่แทนที่วัตถุที่อยู่ในระบบงานจริง
แม้ว่าเราจะมีคลาสแล้วก็ตาม
แต่ในความเป็นจริงเราจะไม่ได้ใช้คลาส เนื่องจากเราจะต้องนำคลาสไปสร้างเป็นวัตถุก่อน
แล้วจึงสามารถสั่งงานวัตถุให้ทำตามที่โปรแกรมต้องการ จากภาพที่ 1 นี้
แม้ว่าเราจะมีคลาส Patient ตามเรายังไม่มีวัตถุผู้ป่วย
แม้แต่สักคนเดียว เราจะต้องนำคลาส Patient นี้ไปสร้างเป็นวัตถุ
Patient โดยใช้กระบวนการที่เรียกว่า อินสแตนทิเอชัน (Instantiation)
วัตถุ
(อินสแตนซ์)
เป็นสิ่งที่ถูกสร้างขึ้นจากคลาส
โดยวัตถุที่สร้างขึ้นจะมีแอททริบิวท์และเมธอดเหมือนกับที่ได้บรรยายไว้ในคลาส
ในทางโปรแกรมเรียกวัตถุว่าอินสแตนซ์เนื่องจากการเก็บวัตถุจะต้องใช้หน่วยความจำของเครื่องคอมพิวเตอร์และการสั่งงานให้วัตถุกระทำตามเมธอดจะต้องใช้หน่วยประมวลผล
(CPU)
รันตามคำสั่งที่อยู่ภายในเมธอดนั้น ๆ
จากภาพที่
2 เราจะเห็นว่าเราสามารถนำคลาส Patient มาสร้างขึ้นเป็นวัตถุกี่ตัวก็ได้[2]
วัตถุแต่ละตัวจะมีค่าแอททริบิวท์เป็นของตัวเองไม่ขึ้นต่อกัน
เช่นในภาพจะเห็นว่าวัตถุ a
มี id เป็น P123 ส่วนวัตถุ
b จะมี id เป็น P201 ค่าของแอททริบิวท์อาจจะเปลี่ยนไปได้ตามการใช้งาน
จากภาพที่ 2 เราจะเห็นว่า a และ b เป็น Reference
Variable ซึ่ง Reference Variable ก็คือตัวแปรอ้างอิงที่ใช้สำหรับอ้างอิงวัตถุ
เราจำเป็นต้องมีตัวแปรอ้างอิงวัตถุถึงจะสามารถใช้งานวัตถุได้
เนื่องจากการเข้าถึงแอททริบิวท์หรือเมธอดของวัตถุใด ๆ ก็ตามจะต้องขึ้นต้นด้วยชื่อตัวแปรอ้างอิงแล้วตามด้วยชื่อแอททริบิวท์หรือเมธอดที่มีอยู่ในวัตถุตัวนั้นเสมอ
ดังนั้นถ้าเราไม่มีตัวแปรอ้างอิงเราจะไม่สามารถเข้าถึงวัตถุได้เลย
และวัตถุที่ปราศจากตัวแปรอ้างอิง เราจะถือว่าเป็นขยะ (Gabage) เนื่องจากเป็นวัตถุที่ไม่สามารถเข้าถึงเพื่อใช้งานใด ๆ ได้[3]
โปรแกรม
OC-1
ตัวอย่างการนำคลาส Patient ไปโปรแกรมเพื่อสร้างวัตถุ
a ตามภาพที่ 2 (ภาษา Java)
Patient a=new Patient();
a.id="P123";
a.firstName="Somchai";
a.dateOfBirth="17/09/1976 ";
ความสัมพันธ์กันระหว่างวัตถุ
(Association)
วัตถุแต่ละตัวในระบบสามารถสร้างความสัมพันธ์กับวัตถุอีกตัวหนึ่งได้
(แม้ว่าจะเป็นความสัมพันธ์กับตัวมันเองก็ได้ด้วย[4]) ความสัมพันธ์ที่เกิดขึ้นจะเป็นมีคุณลักษณะที่เกี่ยวข้องดังต่อไปนี้
1. เหตุผลที่นำมาสัมพันธ์กันและบทบาทที่รับผิดชอบ
2. ทิศทางของความสัมพันธ์ (Navigability)
3. จำนวนนับของวัตถุที่มาสัมพันธ์กัน
(Multiplicity)
1. เหตุผลที่นำมาสัมพันธ์กันและบทบาทที่รับผิดชอบ
เมื่อวัตถุสองตัวมาสัมพันธ์กัน
เนื่องมาจากการวิเคราะห์ความต้องการของระบบแล้วพบว่าวัตถุสองตัวนี้จะต้องเกี่ยวข้องกัน
เช่น วัตถุผู้ป่วย และวัตถุสถานพยาบาล
มาเกี่ยวข้องกันเนื่องจากผู้ป่วยไปรักษาไข้อยู่ที่สถานพยาบาล
หรือวัตถุผู้ป่วยกับวัตถุแพทย์ มาเกี่ยวข้องกันเนื่องจากผู้ป่วยมาให้แพทย์รักษา
ดังนี้เราจะพบว่าในระบบงานหนึ่งจะเกิดขึ้นจากการทำงานร่วมกัน ระหว่างวัตถุหลาย ๆ ตัวและวัตถุแต่ละตัวก็จะมีหน้าที่ที่ต้องรับผิดชอบแตกต่างกันไป
เมื่อเราสามารถจัดวางวัตถุและความสัมพันธ์ให้สอดคล้องกันได้อย่างลงตัวแล้วเราจะได้โครงสร้างของระบบงานที่ชัดเจนและพร้อมสำหรับการนำไปพัฒนาเป็นแอพพลิเคชันในขั้นต่อไป
จากภาพที่
3 เราจะเห็นว่าวัตถุ a คือผู้ป่วยที่ชื่อสมชาย
ไปรักษาที่โรงพยาบาลวิภาวดี 1 คือวัตถุ h เราสามารถเขียนเส้นลากเชื่อมโยงระหว่างวัตถุ a และวัตถุ
h และเรียกเส้นนี้ว่า assication ที่เหนือเส้นหรือใต้เส้นจะมีข้อความกำกับไว้
(Association Verb) เพื่อบอกให้ทราบว่าเกี่ยวข้องกันอย่างไร
ซึ่งบางครั้งอาจจะมีไม่จำเป็นต้องเขียนบอกไว้ก็ได้ถ้าความหมายของภาพชัดเจนและเป็นที่รู้กันอยู่แล้ว
เมื่อวัตถุมาเกี่ยวข้องสัมพันธ์กันเราจะสามารถเขียนบรรยายเป็นลักษณะของคลาสได้
ดังภาพที่ 4
ต่อไปนี้
ในภาพที่
4 เราจะเห็นว่าเมื่อวัตถุมาเกี่ยวข้องสัมพันธ์กัน
เราจะเขียนเส้นเชื่อมโยงระหว่างคลาสของวัตถุทั้งสองชนิดที่เกี่ยวข้องกันไว้[5] เมื่อลากเส้นเชื่อมโยงแล้ว
ทางปลายเส้นแต่ละด้านเราอาจจะใส่ข้อความกำกับบทบาท (Role Name) ไว้ด้วยก็ได้
Role
Name ใช้สำหรับบอกให้ผู้อ่านไดอะแกรมทราบว่าวัตถุที่เกี่ยวข้องกันนั้นทำหน้าที่อะไร
เช่นในภาพที่ 4 เราจะเห็นว่าวัตถุ a ทำหน้าที่เป็น
patient (ผู้ป่วย) และวัตถุ b ทำหน้าที่เป็น
nursing home (สถานพยาบาล) การใส่ Role Name เข้าไปในไดอะแกรมจะช่วยให้เราเห็นบทบาทหน้าที่ของวัตถุได้ชัดเจนยิ่งขึ้น
ซึ่งในภาพที่ 4 อาจจะไม่แสดงความสำคัญของ Role Name เท่าใดนักเนื่องจากชื่อคลาสเองก็สื่อความหมายที่ชัดเจนอยู่แล้วว่าเป็นผู้ป่วย
และเป็นโรงพยาบาล
แต่ในกรณีที่ชื่อคลาสไม่บ่งบอกหน้าที่ที่ชัดเจนลงไปเราอาจจะต้องใช้ Role
Name กำกับไว้ด้วย
จากภาพที่
5 เราจะเห็นว่าคลาส Person ไม่บ่งบอกความหมายที่ชัดเจนเพียงพอ
ในกรณีที่เป็นโรงพยาบาลว่าจ้างพยาบาล เราจะเห็นว่าโรงพยาบาลมีบทบาทเป็นผู้ว่าจ้าง
(employer) และบุคคลรับบทบาทเป็นพยาบาล (nurse) แต่ในขณะเดียวกันถ้าเป็นความสัมพันธ์ระหว่างบุคคลที่เป็นผู้ป่วยกับโรงพยาบาล
โรงพยาบาลจะรับบทบาทเป็น สถานพยาบาล (nursing home) และบุคคลรับบทบาทเป็นผู้ป่วย (patient)
2. ทิศทางของความสัมพันธ์ (Navigatability)
ความสัมพันธ์ที่เกิดขึ้นระหว่างวัตถุสามารถเกิดได้สองแบบคือ
ทิศทางเดียว (Uni-direction)
หรือ สองทิศทาง (Bi-direction) ทั้งสองแบบนี้บ่งบอกให้เห็นว่าเราสามารถดึงค่าของวัตถุตัวหนึ่งออกมาจากวัตถุอีกตัวหนึ่งที่กำลังทำความสัมพันธ์กันอยู่ได้หรือไม่
ตัวอย่างของทิศทางเช่น
ถ้าเรามีวัตถุผู้ป่วยอยู่หนึ่งคน หรือผู้ป่วย a เราต้องรู้ว่าปัจจุบันผู้ป่วย
a เค้ารักษาตัวอยู่ที่สถานพยาบาลแห่งไหน
เราสามารถสอบถามได้จากผู้ป่วย a โดยตรงเมื่อถามวัตถุผู้ป่วย a
แล้วเค้าจะตอบกลับมาว่าเค้ารักษาตัวอยู่ที่สถานพยาบาล h ในกรณีอย่างนี้เราบอกได้ว่า
วัตถุผู้ป่วยสามารถเชื่อมโยงไปที่วัตถุสถานพยาบาลที่เกี่ยวข้องกันอยู่ได้
และทิศทางของความสัมพันธ์จะชี้จากวัตถุผู้ป่วยไปที่วัตถุสถานพยาบาล ดังรูปภาพที่ 6
จากภาพที่
6 แสดงให้เห็นในกรณีของวัตถุที่สัมพันธ์กันอยู่
แต่เมื่อเรานำมาเขียนเป็นคลาสไดอะแกรมแล้วเราจะสามารถเขียนได้ดังภาพที่ 7
การออกแบบโปรแกรมเพื่อให้เกิดความสัมพันธ์แบบทิศทางเดียวก็คือความสามารถในการดึงวัตถุอีกตัวหนึ่งออกมาจากวัตถุที่กำลังใช้งานอยู่
ดังนั้นวัตถุที่จะสัมพันธ์กับวัตถุอื่นและสามารถเชื่อมโยงไปถึงวัตถุนั้นได้จะต้องจัดให้มีแอททริบิวท์หรือเมธอดที่สามารถดึงวัตถุที่เชื่อมโยงกันอยู่ออกมาใช้งานได้
จากภาพที่
8 เราให้วัตถุ Patient
ทุกตัวมีตัวแปรอ้างอิงไปที่วัตถุ Hospital ชื่อตัวแปรว่า hospital เพื่อเก็บไว้ว่าสถานพยาบาลไหนที่เป็นสถานพยาบาลปัจจุบันที่ผู้ป่วยคนนี้กำลังใช้บริการอยู่
สำหรับเมธอด getCurrentHospital เราจัดเตรียมไว้ให้ Client
Code[6] เรียกใช้ในกรณีที่ไม่ต้องการให้เข้าถึงแอททริบิวท์ได้โดยตรง[7]
การเชื่อมโยงแบบสองทิศทาง
จะเกิดขึ้นเนื่องจากเราสามารถดึงวัตถุที่เชื่อมโยงกันอยู่ออกมาจากวัตถุใดวัตถุหนึ่งก็ได้
เช่นในกรณีของผู้ป่วยกับสถานพยาบาล ถ้าเรามีวัตถุสถานพยาบาล h อยู่เราต้องการรู้ว่าปัจจุบันสถานพยาบาล
h มีผู้ป่วยมารักษาอยู่ทั้งหมดกี่คน
แล้วเราสามารถเรียกใช้เมธอด getAllPatients เพื่อให้ได้วัตถุผู้ป่วยทั้งหมดที่กำลังรักษาตัวอยู่ที่สถานพยาบาล
h ได้ เราสามารถบอกได้ว่า
วัตถุสถานพยาบาลเชื่อมโยงอยู่กับวัตถุผู้ป่วย
จากภาพที่
9 แสดงให้เห็นว่าเราสามารถดึงวัตถุ Patient ทุกคนที่กำลังรักษาตัวอยู่ที่สถานพยาบาลออกมาได้โดยเรียกใช้เมธอด
getAllPatients[8]
จากภาพที่ 9
ถ้าเรานำไปรวมเข้าด้วยกันภาพที่ 8 ก็จะได้ความสัมพันธ์แบบสองทิศทางที่วัตถุ
Patient สามารถเชื่อมโยงไปถึงวัตถุ Hospital และในขณะเดียวกันวัตถุ Hospital ก็สามารถเชื่อมโยงมาที่วัตถุ Patient ได้เช่นเดียวกัน
จากภาพที่
10 เราจะสังเกตเห็นว่าถ้าเป็นความสัมพันธ์แบบสองทิศทางเราไม่จำเป็นต้องใส่หัวลูกศรเข้าไปที่ปลายเส้นด้านใดด้านหนึ่ง
ในการออกแบบระบบจริง
เราอาจจะยังไม่ระบุทิศทางของความสัมพันธ์ที่ชัดเจนในระดับของการออกแบบขั้นคอนเซ็ปต์
(Conceptual
Design) เนื่องจากความต้องการของระบบยังไม่ชัดเจน
เราอาจจะทิศไว้เป็นเส้นเชื่อมโยงธรรมดาที่ไม่แสดงหัวลูกศร
แต่เมื่อผ่านการออกแบบมาถึงขั้นออกแบบรายละเอียด (Detailed Design) สถาปนิกซอฟแวร์อาจจะวิเคราะห์และออกแบบให้เหลือเป็นความสัมพันธ์แบบทิศทางเดียวก็ได้
เนื่องจากความสัมพันธ์แบบทิศทางเดียวจะง่ายสำหรับการนำไปสร้างเป็นโปรแกรมมากกว่าความสัมพันธ์แบบสองทิศทาง
3. จำนวนนับของวัตถุที่มาสัมพันธ์กัน
(Multiplicity)
เมื่อวัตถุมาเกี่ยวข้องสัมพันธ์กัน
เราจะวิเคราะห์ว่าวัตถุเหล่านั้นสามารถเกิดความสัมพันธ์กันได้ด้วยจำนวนเท่าใด
ตัวอย่างเช่น รถยนต์นั่งธรรมดาจะสัมพันธ์กับล้อรถด้วยจำนวนเป็น 4 หรือ
โรงพยาบาลแห่งหนึ่งสามารถรักษาผู้ป่วยได้หลายคน เป็นต้น
จากภาพที่
11 จำนวนนับระหว่างวัตถุ[9]สองชนิดคือ
Patient และ Hospital เราสามารถแปลความหมายได้จากการอ่านทั้งสองทิศทางคือ
อ่านจากทางซ้ายไปทางขวา หรืออ่านจากทางขวามาทางซ้าย
จากภาพที่
12 ถ้าเราพิจารณาภาพที่ 11 จากซ้ายมาขวา จะได้ว่าวัตถุ Patient หนึ่งตัวจะเชื่อมโยงไปที่วัตถุ Hospital หนึ่งตัวที่ทำหน้าที่เป็นสถานพยาบาลปัจจุบันที่ผู้ป่วยคนนี้กำลังใช้รักษาตัวอยู่
จากภาพที่
13 เป็นการอ่านจากภาพที่ 11 แต่อ่านจากทางขวามาทางซ้ายเราจะได้ความหมายว่าวัตถุ Hospital หนึ่งตัวสามารถเชื่อมโยงกับวัตถุ Patient ได้หลายคน
ซึ่งภาพที่ 12 และภาพที่ 13 เป็นเพียงแนวคิดในการอ่านคลาสไดอะแกรมที่มี
Multiplicity อยู่ให้สามารถเข้าใจเรื่อง Multiplicity
ได้ง่ายขึ้น แต่เวลาที่เขียนในคลาสไดอะแกรมจริง ๆ จะเขียนเหมือนกับที่แสดงในภาพที่ 11
ตัวเลขที่บอกจำนวนนับของวัตถุที่ปลายเส้น
Association
อาจจะมีจำนวนตั้งแต่เท่าไรถึงเท่าไรก็ได้ เช่น 0..* หมายถึงมีจำนวนวัตถุตั้งแต่ 0 ถึงเท่าไรก็ได้
หรือถ้ามีเลขจำนวนเป็น 4..8 หมายถึงจะต้องสร้างความสัมพันธ์ที่จำนวนวัตถุตั้งแต่
4 ถึง 8 ตัวเท่านั้น
จากเรื่องของวัตถุ
คลาส และความสัมพันธ์ เราจะสามารถนำมาใช้ในการออกแบบออบเจกต์โมเดล (Object Model) ได้ ต่อไปนี้เป็นตัวอย่างของการวิเคราะห์ Problem Statement[10] บางส่วนของระบบงานที่ยกมาเป็นกรณีศึกษา
เพื่อให้เข้าใจวิธีการของ Object-Oriented มากขึ้น
ตัวอย่าง
–
1
การวิเคราะห์ File และ Folder
Problem
Statement ไฟล์จะเก็บอยู่ในโฟลเดอร์
โฟลเดอร์หนึ่งสามารถเก็บไฟล์ได้หลาย ๆ ไฟล์
ในโฟลเดอร์สามารถเก็บโฟลเดอร์ได้หลาย ๆ โฟลเดอร์
ไฟล์สามารถมีแอททริบิวส์ได้หลาย ๆ แอททริบิวส์
เช่น อ่านอย่างเดียว เขียนอย่างเดียว อ่านและเขียน และอื่น ๆ
ตัวอย่าง
–
2
การวิเคราะห์ Song Album
Problem
Statement อัลบัมหนึ่งสามารถมีเพลงได้มากกว่าหนึ่งเพลง
เพลงหนึ่งสามารถไปอยู่ในอัลบัมไหนก็ได้
เพลงหนึ่งสามารถมีศิลปินผู้ร้องเพลงได้เพียงคนเดียว เพลงหนึ่งสามารถมีได้หลายเวอร์ชัน
และแต่ละเวอร์ชันสามารถมีผู้ร้องเพลงได้ต่างจากเวอร์ชันที่แล้ว
ตัวอย่าง
–
3
การวิเคราะห์ Task Assignment
Problem
Statement พนักงานหนึ่งคนจะมีงานที่ต้องรับผิดชอบมากกว่าหนึ่งในเวลาเดียวกัน
พนักงานสามารถอยู่ในทีมงานไหนก็ได้ ขึ้นอยู่กับงานที่รับผิดชอบ
ทีมงานแต่ละทีมจะประกอบด้วยพนักงานหลาย ๆคน และมีคนหนึ่งคนที่เป็นหัวหน้าทีม
ตัวอย่าง
–
4
การวิเคราะห์ Hotel Room Reservation
Problem
Statement โรงแรมแห่งหนึ่งมีห้องพักแบ่งให้ลูกค้าสั่งจองเข้าพักได้
โดยห้องนึงสามารถพักได้มากกว่าหนึ่งคน และลูกค้าสามารถสั่งจองได้มากกว่าหนึ่งห้อง
ห้องพักห้องนึงสามารถถูกสั่งจองโดยลูกค้ามากกว่าหนึ่งรายในช่วงเวลาที่ต่างกัน
ความสัมพันธ์พื้นฐาน
7
ชนิด
ความสัมพันธ์พื้นฐาน
7 ชนิดเกิดจากการแยกประเภท Multiplicity ออกเป็น 4
แบบคือ 1-1[11] 1-*[12] *-1 และ *-* โดย 1-1 จะหมายถึงความสัมพันธ์ระหว่างวัตถุหนึ่งชิ้นกับวัตถุอีกหนึ่งชิ้นมาเชื่อมโยงกันด้วยความสัมพันธ์บางอย่าง
และ 1-* หมายถึงวัตถุหนึ่งชิ้นสัมพันธ์กับวัตถุอีกหลาย ๆ ชิ้น โดย * หมายถึงตั้งแต่
0 ขึ้นไปถึงจำนวนกี่ชิ้นก็ได้ สำหรับ *-1 หมายถึงวัตถุหลาย ๆ ชิ้นสัมพันธ์กับวัตถุชิ้นเดียวกัน
โดยแบ่งวัตถุที่มีเพียงชิ้นเดียวนั้นใช้งานร่วมกันในหลายวัตถุ และสุดท้าย *-*
หมายถึงวัตถุหลาย ๆ ชิ้นทำความสัมพันธ์กับวัตถุอีกหลาย
ๆ ชิ้น
เมื่อเรานำจำนวน
Multiplicity
มารวมกับเรื่องทิศทางของความสัมพันธ์จะทำให้ได้ตารางแจกแจงประเภทความสัมพันธ์ออกมาตาม
ตารางที่ 1
ตารางที่
1 – ความสัมพันธ์พื้นฐาน 7 ชนิด
Mutliplicity
|
Uni-Direction
|
Bi-Direction
|
1-1
|
One
to One Uni-Direction
|
One
to One Bi-Direction
|
1-*
|
One
to Many Uni-Direction
|
One
to Many Bi-Direction
|
*-1
|
Many
to One Uni-Direction
|
ไม่จำเป็นเนื่องจากซ้ำกับแบบ
One
to Many Bi-Direction เพียงแต่มองกลับด้าน
|
*-*
|
Many
to Many Uni-Direction
|
Many
to Many Bi-Direction
|
ความสัมพันธ์พื้นฐานทั้ง
7 ชนิดนี้ยังตรงกับรูปแบบของ Container-Managed Relationship ที่ใช้กันอยู่ในมาตรฐาน EJB 2.0 (Enterprise JavaBeans) เพื่อใช้สำหรับออกแบบสถาปัตยกรรมของระบบในระดับองค์กร
คุณลักษณะพื้นฐานของ
Object-Oriented
การออกแบบซอฟแวร์ด้วยแนวคิดเชิงวัตถุจะใช้ภาษาโปรแกรมที่มีคุณลักษณะสำคัญ
3 อย่างคือ
1. Encapsulation ความสามารถในการปิดบังการทำงานที่สลับซับซ้อนไว้ภายในตัววัตถุและเปิดเผยให้ผู้ใช้วัตถุเห็นเฉพาะส่วนที่จำเป็นสำหรับการใช้งานเท่านั้น[13]
2. Inheritance ความสามารถในการขยายต่อ โดยการสร้างคลาสให้สืบทอดต่อจากคลาสแม่ ซึ่งจะทำให้คลาสลูกที่สืบทอดต่อมาได้รับคุณสมบัติทุกอย่างมาจากคลาสแม่
และไม่จำเป็นต้องเขียนโปรแกรมซ้ำกับส่วนที่มีอยู่แล้วในคลาสแม่ ซึ่งถ้าเรานำ Inheritance
มาใช้ในรูปแบบที่เหมาะสมจะช่วยทำให้ลดความซ้ำซ้อนในการเขียนโปรแกรมและทำการแก้ไขเปลี่ยนแปลงโปรแกรมได้ง่ายขึ้นอีก
3. Polymorphism ความสามารถในการแปรเปลี่ยนการกระทำไปตามชนิดของวัตถุ
เราสามารถนำวัตถุที่อยู่ในตระกูลเดียวกัน[14]
มาทำงานร่วมกันได้โดยผ่านตัวแปรอ้างอิงเพียงตัวเดียว
และใช้การสั่งงานวัตถุที่เหมือนกันตลอดทั้งการทำงาน
แต่ตัวแปรอ้างอิงจะย้ายไปอ้างอิงวัตถุที่ต่างชนิดกันและจะมีผลให้เกิดการทำงานที่แตกต่างกันไปตามชนิดของวัตถุที่ตัวแปรอ้างอิงกำลังอ้างถึงอยู่
1. การออกแบบเพื่อให้เกิด Encapsulation
ในกรณีที่เราไม่ต้องการให้ไคลเอ็นต์สามารถเข้าถึงค่าที่ใช้ภายในตัววัตถุ
เราจะกำหนดระดับการมองเห็น (Visibility) ให้กับแอททริบิวท์นั้นเป็น
private ซึ่งแอททริบิวท์ที่มีระดับการมองเห็นเป็น private
จะสามารถมองเห็นได้เฉพาะภายในคลาสเดียวกันเท่านั้น
คลาสอื่นจะไม่สามารถมองเห็นแอททริบิวท์ที่เป็น private ได้
ปกติแล้วเราจะกำหนดแอททริบิวท์ทั้งหมดเป็น
private
แต่จะให้เมธอดเป็น public เพื่อเป็นการบังคับให้ไคลเอ็นต์โค้ดต้องใช้วัตถุผ่านทางเมธอดเสมอ
ซึ่งเราจะสามารถควบคุมสถานะของวัตถุได้เองจากภายในคลาสและไม่จำเป็นต้องให้ภายนอกคลาสรู้กระบวนการที่เกิดขึ้นภายในวัตถุด้วย
การบังคับให้ไคลเอ็นต์ใช้งานผ่านทาง
public
เมธอดเสมอ ยังเป็นผลดีคือเมื่อเกิดการเปลี่ยนแปลงวิธีการอิมพลีเมนต์ภายในตัววัตถุโดยที่รูปแบบของเมธอดไม่เปลี่ยน
ไคลเอ็นต์จะไม่ได้รับผลกระทบรุนแรงหรืออาจจะไม่จำเป็นต้องแก้ไขโค้ดเลยก็ได้
เนื่องจากไคลเอ็นต์โค้ดไม่ได้ใช้งานแอททริบิวท์ของวัตถุโดยตรงแต่ใช้งานผ่านทางเมธอด
ตราบใดที่รูปแบบการเรียกใช้เมธอดไม่เปลี่ยนไปไคลเอ็นต์โค้ดก็ไม่จำเป็นต้องเปลี่ยนแปลงอะไร
แม้ว่าภายในตัววัตถุจะมีการเปลี่ยนแปลง อย่างไรบ้างก็ตาม
ตัวอย่างในภาพที่
15 เราจะเห็นคลาส User ที่ไม่ได้กำหนดให้แอททริบิวท์เป็น
private ทำให้ไคลเอ็นต์โค้ดสามารถกำหนดค่าให้กับแอททริบิวท์ได้โดยตรง
ซึ่งที่จริงแล้วเราจะไม่ยอมให้ค่า id สามารถเปลี่ยนแปลงได้
ดังนั้นเราจะให้ไคลเอ็นต์สามารถอ่านค่า id ไปดูได้อย่างเดียว
แต่ไม่สามารถเปลี่ยนแปลงค่าของ id ได้
ตัวอย่างในภาพที่
16 จะสังเกตเห็นว่าถ้าเราทำให้แอททริบิวท์ id เป็น private
จะมีผลให้ไคลเอ็นต์โค้ดไม่สามารถเข้าถึงแอททริบิวท์ id ได้โดยตรงโดยผ่านทางตัวแปรอ้างอิงเหมือนกับในภาพที่ 15 แต่เราจะจัดให้มีเมธอด getId เพื่อดึงค่าแอททริบิวท์
id ออกไปให้ไคลเอ็นต์นำไปใช้งานต่อ
แต่ไคลเอ็นต์โค้ดจะไม่สามารถแก้ไขค่าของ id ได้เนื่องจากเราไม่ได้จัดเตรียมเมธอดอะไรไว้ให้
2. การออกแบบโดยใช้ Inheritance
เราจะออกแบบคลาสให้สืบทอดต่อจากอีกคลาสหนึ่งก็ต่อเมื่อคลาสทั้งสองคลาสนี้อยู่ในตระกูล
(Family)
เดียวกัน เมื่อสืบทอดแล้วเราจะเรียกคลาสที่สืบทอดมาว่าคลาสลูก (Sub-Class[15]) และเรียกคลาสที่ถูกสืบทอดต่อไปว่าเป็นคลาสแม่
(Super-Class[16])
จากภาพที่
17 เราจะเห็นว่าเมื่อคลาส Person สืบทอดต่อจากคลาส User
จะทำให้คลาส Person ได้แอททริบิวท์และเมธอดทุกอย่างของคลาส
User ไปด้วย ดังนั้นในภาพนี้เราสรุปได้ว่าคลาส Person
มีแอททริบิวท์อยู่ 5 ตัวคือ username และ password ที่ได้รับสืบทอดมาจากคลาส User และแอททริบิวท์ pid firstName และ lastName ที่มีอยู่ในคลาสตัวเอง
การสืบทอดจะแสดงให้เห็นในคลาสไดอะแกรมด้วยเส้น
Generalization
ซึ่งจะชี้จากคลาสที่เป็นคลาสลูกไปหาคลาสแม่ เนื่องจากหัวลูกศรจะชี้ไปที่คลาสแม่ที่มีความเป็นทั่วไป
(General) มากกว่าคลาสลูกดังนั้นจึงเรียกลูกศรนี้ว่า Generalization
การ
Override
เมื่อคลาสลูกสืบทอดต่อมาจากคลาสแม่
คลาสลูกจะได้เมธอดมาจากคลาสแม่ด้วย
ทำให้การโปรแกรมที่คลาสลูกไม่จำเป็นต้องเขียนโปรแกรมในส่วนที่คลาสแม่ได้เขียนไว้แล้ว
แต่อย่างไรก็ตาม
ในบางครั้งถ้าคลาสลูกไม่ต้องการทำงานเช่นเดียวกับที่คลาสแม่เคยทำไว้
เราอาจจะสร้างเมธอดชื่อเดียวกันกับคลาสแม่ไว้ในคลาสลูก
แล้วใส่โปรแกรมที่ทำงานแตกต่างไปจากที่คลาสแม่ได้ทำไว้ก็ได้
วิธีดังกล่าวนี้เราเรียกว่า Override[17] และเมธอดที่สร้างขึ้นไว้ในคลาสลูกให้ทับเมธอดในคลาสแม่นี้เราเรียกว่า
Overriding Method
ตัวอย่างในภาพที่
18 แสดงให้เห็นเมธอด save ในคลาส Person ไม่ได้ใช้กระบวนการ save ที่ได้รับมาจากคลาส User
แต่สร้างเมธอด save เป็นของตัวเองแล้วมีกระบวนการ
save ที่แตกต่างกันออกไปจากที่คลาสแม่ทำไว้
3. Polymorphism
เป็นวิธีการที่ช่วยให้โปรแกรมสามารถทำงานได้หลาย
ๆ แบบ
โดยใช้วิธีการเขียนโปรแกรมแบบเดียวกัน วิธีการของ Polymorphism มักจะนำมาใช้ในกรณีที่มีวัตถุหลายชนิด
และวัตถุแต่ละชนิดมีรูปแบบการสั่งงานเหมือนกันและมีวิธีการทำงานแตกต่างกันไป
ตัวอย่างเช่นในรูปที่
18 เราจะเห็นว่าถ้าเรานำคลาส User และคลาส Person
มาสร้างเป็นวัตถุแล้ว
เราจะสามารถสั่งให้วัตถุทั้งสองชนิดนี้บันทึกข้อมูลเก็บไว้ในระบบได้โดยสั่งผ่านทางเมธอด
save() ซึ่งจะมีรูปแบบการสั่งงานเหมือนกันคือคำว่า save()
แต่การทำงานของวัตถุทั้งสองชนิดนี้แตกต่างกัน วัตถุ User จะบันทึกข้อมูลเฉพาะ username และ password แต่วัตถุ person จะบันทึกข้อมูลทั้ง username
password firstName lastName และ pid ด้วย
จากภาพที่
19 เราจะเห็นว่าคลาส Circle Rectangle และ Triangle
ต่างก็สืบทอดมาจากคลาสแม่ Shape และได้สร้างเมธอดชื่อ
getArea() ทับเมธอด getArea() ในคลาสแม่
เนื่องจากวิธีการคำนวณพื้นที่ของรูปร่างแต่ละแบบใช้สูตรคำนวณไม่เหมือนกัน
แต่มีรูปแบบการเรียกใช้คำสั่งเป็นแบบเดียวกันคือ
เมื่อไคลเอ็นต์โค้ดต้องการทราบพื้นที่ของวัตถุรูปร่างใดก็ตาม
ไคลเอ็นต์โค้ดจะเรียกใช้เมธอด getArea() เหมือนกันทั้งหมด
ด้วยวิธีการออกแบบเช่นนี้
ถ้าสมมุติว่าเราต้องคำนวณหาพื้นที่รวมของวัตถุรูปร่างทุกวัตถุที่อยู่ในระบบ
เราจะสามารถทำได้ด้วยการเรียกเมธอด getArea() แล้วนำค่าพื้นที่ที่ได้มารวมไว้ในพื้นที่ทั้งหมด
จากภาพที่
20 จะเห็นว่าเราสามารถนำวัตถุที่อยู่ในตระกูลเดียวกันมาวางไว้ในคอลเลคชันเดียวกัน
เพื่อให้เกิดเป็น Heterogenous Collection แล้วเราสามารถใช้คำสั่งเพียงคำสั่งเดียวเพื่อเรียกใช้เมธอด
getArea ของวัตถุทั้งหมด ขณะที่เรียกใช้เมธอด getArea
จะไปเรียกใช้เมธอดของคลาสที่ตรงกับชนิดของวัตถุตัวนั้นโดยอัตโนมัติ[19]
รหัสโปรแกรม – 1 ตัวอย่างไคลเอ็นต์โค้ดที่เขียนแบบ
Polymorphism
for(int i=0; i <shapes.length; i++) {
allArea+=shapes[i].getArea(); // polymorphism
//
dynamic depend on type of object.
}
จากรหัสโปรแกรม
1 เราจะสามารถเขียนเรียกใช้เมธอด getArea() ได้เหมือนกันทุกรอบของการทำงานในลูป
โดยในขณะที่รันโปรแกรมจริง ๆ จะไปเรียกใช้เมธอด
getArea() ของคลาสไหน
จะขึ้นอยู่กับชนิดของวัตถุว่าถูกสร้างขึ้นมาจากคลาส Circle Triangle หรือ Rectangle และจะใช้สูตรการคำนวณพื้นที่ที่เป็นของวัตถุชนิดนั้น
ๆ เอง
รหัสโปรแกรม – 2
ตัวอย่างไคลเอ็นต์โค้ดที่เขียนโดยไม่ใช้ Polymorphism
for(int i=0; i <shapes.length; i++) {
if(shapes[i].type==Shape.CIRCLE)
{
allArea+=((Circle)shapes[i]).getCircleArea();
}
else if(shapes[i].type==Shape.RECTANGLE) {
allArea+=((Rectangle)shapes[i]).getRectangleArea();
}
else if(shapes[i].type==Shape.TRIANGLE) {
allArea+=((Triangle)shapes[i]).getTriangleArea();
}
}
ในรหัสโปรแกรม
2 เราจะสังเกตเห็นว่าถ้าไม่ใช้วิธีการแบบ Polymorphism เราจะต้องเขียนโปรแกรมเพื่อตรวจสอบก่อนว่าวัตถุมีชนิดเป็นอะไร
แล้วจึงเรียกใช้เมธอดที่มีเฉพาะในวัตถุชนิดนั้น ๆ
ซึ่งเป็นวิธีการที่ไม่สะดวกเนื่องจากมีลักษณะที่จำเพาะเจาะจงเกินไป
แล้วทำให้ต้องเขียนโปรแกรมมากขึ้นเรื่อย ๆ
ถ้ามีวัตถุหลากหลายชนิดขึ้นอีก
การแบ่งแยกคุณลักษณะพื้นฐานออกจากคุณลักษณะพิเศษ
(Abstraction)
ในการพัฒนาระบบงานที่สลับซับซ้อน
เราจะมีวัตถุหลากหลายชนิด ซึ่งแต่ละวัตถุก็จะมีคุณลักษณะที่ซ้ำซ้อนกัน และมีคุณลักษณะที่พิเศษเป็นของตัววัตถุชนิดนั้น
ๆ เอง ในกรณีที่เราต้องการจะนำระบบเดิมกลับมาใช้ใหม่โดยให้มีการแก้ไขน้อยที่สุด[20] เราจำเป็นต้องออกแบบระบบโดยแบ่งแยกระดับ
(Layer)
ออกเป็นสองระดับคือ
1. ส่วนเฟรมเวิร์ค (Framework)
เป็นส่วนที่รวบรวมเอาคุณลักษณะพื้นฐานของระบบไว้
แม้ว่าจะมีการเปลี่ยนแปลงสภาวะแวดล้อมหรือความต้องการของผู้ใช้เปลี่ยนไป
ส่วนเฟรมเวิร์คนี้จะไม่มีการเปลี่ยนแปลง[21] หรือถ้ามีการเปลี่ยนแปลงก็น้อยมาก
บางครั้งเราเรียกส่วนนี้ว่าส่วน Generic
2. ส่วนแอพพลิเคชัน (Application)
เป็นส่วนที่เปลี่ยนแปลงไปตามสภาวะและความต้องการของผู้ใช้โดยขยายการทำงานต่อจากกรอบที่เฟรมเวิร์คได้วางไว้แล้ว
เนื่องจากโครงสร้างพื้นฐานต่าง ๆ จะถูกกำหนดไว้แล้วในระดับเฟรมเวิร์คทำให้การพัฒนาระบบต่อจากเฟรมเวิร์คจะสามารถขึ้นรูประบบได้อย่างรวดเร็วและลดจุดบกพร่องต่าง
ๆ ไปได้เป็นจำนวนมากเนื่องจากจุดบกพร่องส่วนใหญ่จะถูกขจัดออกไปตั้งแต่ตอนพัฒนาเฟรมเวิร์คแล้ว
การพัฒนาเฟรมเวิร์คและแอพพลิเคชันจำเป็นต้องใช้ความสามารถของภาษาโปรแกรมเชิงวัตถุอีกสองอย่างคือ
1. แอบส์แทรค (Abstract) การออกแบบส่วนนามธรรม
2. อินเตอร์เฟส (Interface)
การออกแบบความสามารถของวัตถุ
1.
แอบส์แทรค (Abstract)
การออกแบบคลาสให้เป็นแอบส์แทรคคลาส
(Abstract
Class) จะมีผลบังคับให้ไคลเอ็นต์โค้ดไม่สามารถนำแอบส์แทรคไปสร้างเป็นวัตถุได้เหมือนกับคลาสปกติ
แต่โปรแกรมเมอร์ที่นำแอบส์แทรคคลาสมาใช้จะถูกบังคับให้ต้องสร้างคลาสสืบทอดต่อจากแอบส์แทรคคลาสแล้วจึงนำคลาสลูกไปใช้สร้างเป็นวัตถุได้
เราอาจจะคิดได้อีกอย่างว่าแอบส์แทรคคลาสคือคลาสที่ยังไม่สมบูรณ์
แต่มีวัตถุประสงค์เพื่อใช้เป็นคลาสแม่เท่านั้น
โดยในแอบส์แทรคคลาสจะกำหนดโครงสร้างว่าวัตถุชนิดนี้ควรจะมีแอททริบิวท์และเมธอดอะไรอยู่บ้าง
เพื่อบังคับให้คลาสลูกที่สืบทอดไปต้องยึดตามโครงสร้างที่แอบส์แทรคคลาสได้กำหนดเอาไว้
จากภาพที่
21 จะพบว่าคลาส Shape เป็นแอบส์แทรคคลาส และเมธอด getArea
เป็นแอบส์แทรคเมธอด ใน UML จะเขียนเป็นอักษรตัวเอน
คลาสลูกที่สืบทอดต่อจากคลาส Shape จะถูกบังคับว่าต้องทำเมธอด
getArea ให้สมบูรณ์ จึงจะสามารถคอมไพล์ผ่านไปได้
ตัวอย่างเช่นคลาสลูก Circle และคลาส Rectangle จะต้องสร้างเมธอด getArea ที่สมบูรณ์ไว้ สำหรับคลาส Triangle
ในภาพที่ 21 ถ้าไม่ต้องการสร้างเมธอด getArea
จะทำให้คลาส Triangle คอมไพล์ไม่ผ่านหรือไม่ก็จะทำให้คลาส
Triangle ต้องกลายสภาพเป็นแอบส์แทรคไปด้วย
การใช้แอบส์แทรคจะช่วยในการออกแบบโครงสร้างเฟรมเวิร์คโดยในเฟรมเวิร์คจะกำหนดคลาสไว้เป็นแอบส์แทรคคลาส
และดำเนินการในส่วนที่เป็นปฏิบัติการขั้นพื้นฐานเตรียมไว้ให้
เมื่อคลาสลูกที่ระดับแอพพลิเคชันสืบทอดต่อมาจากคลาสแม่ที่เป็นแอบส์แทรคคลาสคลาสลูกจะต้องเพิ่มปฏิบัติการพิเศษที่เป็นรายละเอียดเฉพาะในแต่ละระบบงานใส่เข้าไปเองอีกทีให้สมบูรณ์
2.
อินเตอร์เฟส (Interface)
อินเตอร์เฟสใช้สำหรับเป็นข้อตกลงระหว่างไคลเอ็นต์โค้ดและอิมพลีเมนต์โค้ด[22]
เพื่อให้โปรแกรมเมอร์ที่นำวัตถุไปใช้งานสามารถใช้งานได้ตามข้อตกลงที่ทำกันไว้ตั้งแต่แรก
โดยที่โปรแกรมเมอร์ที่เขียนไคลเอ็นต์โค้ดไม่จำเป็นต้องรู้ว่าวัตถุที่ทำงานให้จริง ๆ นั้นเป็นวัตถุของคลาสอะไร
เนื่องจากไคลเอ็นต์โค้ดจะเรียกใช้งานวัตถุผ่านทางอินเตอร์เฟสเสมอ
อินเตอร์เฟสมีความสำคัญอย่างมากสำหรับการพัฒนา
API
(Application Programming Interface) หรือการพัฒนา Design
Specification เพื่อใช้สำหรับแบ่งงานกันทำระหว่างโปรแกรมเมอร์ผู้สร้างวัตถุ
และโปรแกรมเมอร์ผู้เรียกใช้วัตถุ ให้สามารถทำงานไปได้พร้อม ๆ กัน
และทำให้สถาปนิกซอฟแวร์สามารถแบ่งแยกระบบงานออกเป็นระบบย่อย ๆ ได้โดยสะดวกขึ้น
จากภาพที่
22 จะเห็นว่าวัตถุ LoginForm จะรับชื่อผู้ใช้ (Username)
และรหัสผ่าน (Password) มาจากผู้ใช้แล้วนำมาตรวจสอบว่าเป็นผู้ใช้ที่ถูกต้องของระบบหรือไม่โดยเรียกใช้เมธอด
isValidUser จากอินเตอร์เฟส Authenticator ในกรณีที่เก็บรายชื่อผู้ใช้อยู่ในไดเร็คทอรีเซอร์วิสอย่างเช่น LDAP
เราจะใช้อิมพลีเมนต์คลาสเป็น LDAPAuthenticator เพื่อให้นำชื่อผู้ใช้และรหัสผ่านไปตรวจสอบกับไดเร็คทอรี แต่ถ้าในกรณีที่รายชื่อผู้ใช้เก็บอยู่ในฐานข้อมูลเราจะใช้อิมพลีเมนต์คลาสเป็น
DatabaseAuthenticator เพื่อให้นำชื่อผู้ใช้และรหัสผ่านไปคิวรีกับตารางในฐานข้อมูล
อย่างไรก็ตามไม่ว่าจะเป็นการใช้อิมพลีเมนต์คลาสตัวไหน
ไคลเอ็นต์โค้ดของเรายังคงเขียนโปรแกรมเหมือนเดิมโดยเรียกใช้ผ่านตัวแปรอ้างอิงที่มีชนิดข้อมูลเป็น
Authenticator
โดยไม่ต้องสนใจว่าอิมพลีเมนต์คลาสที่ทำงานให้จริง ๆ คือวัตถุ LDAPAuthenticator หรือวัตถุ DatabaseAuthenticator
จากวิธีการดังที่กล่าวมานี้ถ้าเรานำอินเตอร์เฟสมาใช้ได้อย่างถูกต้องเหมาะสมจะทำให้เราได้
Pluggable
Software ที่สามารถถอดประกอบชิ้นส่วนบางส่วนเข้าหรือออกได้ตลอดเวลา
เมื่อเรานำส่วนประกอบต่อเข้าไปจะทำให้ระบบงานมีความสามารถพิเศษเพิ่มเติมตามที่ผู้ใช้ต้องการ
และเมื่อเรานำส่วนประกอบถอดออกมาก็จะทำให้ระบบงานทำงานตามค่าปกติที่ได้ตั้งไว้
ใน
UML
จะเขียนอินเตอร์เฟสด้วยสัญลักษณ์สองแบบคือเขียนเป็นรูปสี่เหลี่ยมแล้วหมายเหตุไว้ด้วยสเตอริโอไทป์ว่า
interface อย่างเช่นในภาพที่ 22 หรือเขียนเป็นสัญลักษณ์รูปวงกลมอย่างเช่นในภาพที่
23 ก็ได้
การออกแบบโมเดลวัตถุโดยใช้รูปแบบขั้นพื้นฐาน
รูปแบบขั้นพื้นฐานที่เรานำเสนอในการออกแบบโครงสร้างวัตถุเป็นรูปแบบที่ใช้งานส่วนใหญ่
และปรากฏอยู่ในระบบงานที่เป็น Object-Oriented เกือบทุกระบบงาน ซึ่งจะมีรูปแบบ
8 ชนิดคือ
1. Collection Manager ผู้จัดการกลุ่ม
2. Container ตู้เก็บวัตถุ
3. Relationship Loop ทำความสัมพันธ์กับวัตถุที่อยู่ในตระกูลเดียวกัน
4. Handle-Body ทำให้คุณสมบัติของวัตถุกลายเป็นวัตถุ
5. Dynamic Schema วัตถุที่เก็บข้อมูลโครงสร้างของวัตถุ
6. Shared Object Pool ใช้งานวัตถุร่วมกัน
คำอธิบายอย่างย่อของรูปแบบทั้ง
6 แบบนี้มีดังต่อไปนี้
1. Collection Manager
ในกรณีที่เราออกแบบให้วัตถุสร้างความสัมพันธ์กับวัตถุชนิดอื่น
ด้วยจำนวนที่มากกว่าหนึ่ง หรือที่เราเรียกว่าเป็นความสัมพันธ์แบบ 1-* ทางวัตถุที่เป็นฝั่ง One ก็คือวัตถุที่มีเพียงชิ้นเดียว
ถ้าเราออกแบบให้วัตถุที่เป็นชิ้นเดียวนี้ทำหน้าที่เป็นผู้ควบคุมดูแลวัตถุอีกหลาย ๆ ชิ้นที่นำมาเชื่อมโยงอยู่ที่ตัวมัน
เราจะเรียกวัตถุชิ้นเดียวนี้ว่า Collection Manager หน้าที่ของผู้จัดการกลุ่มก็คือ
ผู้จัดการมีหน้าที่สร้างวัตถุที่เป็นสมาชิกที่อยู่ภายในกลุ่ม และมีหน้าที่ทำลายวัตถุที่เป็นสมาชิกเมื่อไม่ต้องการเก็บไว้ในกลุ่ม
ในภาพที่ 24 จะเห็นว่าเราออกแบบให้คลาส
UserManager ทำหน้าที่เป็น Collection Manager ดังนั้นวัตถุ User Manager หนึ่งตัวจะควบคุมดูแลวัตถุ
User หลาย ๆ ตัว
และเมื่อไรก็ตามที่เราต้องการสร้างวัตถุ User ขึ้นใหม่เราจะต้องเรียกใช้เมธอด
addUser พร้อมกับให้ชื่อของผู้ใช้คนใหม่ที่ต้องการสร้างขึ้นเข้าไปให้
แล้วเมธอด addUser จะทำหน้าที่สร้างวัตถุ User ขึ้นเองภายในตัว UserManager ซึ่งไคลเอ็นต์โค้ดไม่จำเป็นต้องรับรู้กระบวนการสร้างวัตถุ
User และไม่สามารถสร้างวัตถุ User ขึ้นใช้เองภายนอก
วิธีการแบบนี้ใช้สำหรับการออกแบบทั่วไปเมื่อเกิดความสัมพันธ์แบบ
1-*
เราจะพิจารณาให้วัตถุด้านที่เป็นหนึ่งทำหน้าที่เป็น Collection
Manager หรือไม่ขึ้นอยู่กับข้อกำหนดของระบบงานและหลักในการแบ่งงานกันทำ[23]ระหว่างวัตถุ
2. Container
เมื่อไรก็ตามที่เราต้องการให้วัตถุตัวหนึ่งสามารถเก็บวัตถุอีกหลาย
ๆ ตัวไว้ภายในตัวมันเองได้
(ลักษณะเหมือนตู้เก็บของ) เราจะออกแบบให้มันทำหน้าที่เป็น Container ซึ่งมักจะนำมาประยุกต์ใช้กับความสัมพันธ์แบบ 1-* หรือ
*-*
ในภาพที่
25 เราจะสังเกตเห็นว่าวัตถุที่ทำหน้าที่เป็น Container จะไม่ยุ่งเกี่ยวกับกระบวนการสร้างวัตถุที่นำเข้ามาเก็บในตัวมัน
ตัว Container จะทำหน้าที่เก็บวัตถุไว้เท่านั้นโดยไม่ได้ทำหน้าที่เป็นผู้สร้างหรือทำลายวัตถุอย่างในกรณีของ
Collection Manager ซึ่งเราจะสังเกตได้จากเมธอด add ที่จะรับอาร์กิวเมนต์เข้ามามีชนิดเป็น Object ก็หมายความว่าวัตถุตัวที่ใส่เข้ามาให้กับเมธอด
add จะต้องถูกสร้างขึ้นมาอยู่แล้ว โดยไม่ได้มาสร้างขึ้นในเมธอด add
ลักษณะของ
Container
มักจะใช้งาน กับความสัมพันธ์แบบ *-* มากกว่าความสัมพันธ์แบบอื่น
ตัวอย่างเช่นความสัมพันธ์ระหว่าง ผู้ใช้และกลุ่ม ซึ่งกลุ่มจะทำหน้าที่เป็น Container
เก็บผู้ใช้ที่เป็นสมาชิกไว้ภายในกลุ่ม หรือความสัมพันธ์ระหว่าง
สถานพยาบาลกับผู้ป่วย โดยสถานพยาบาลทำหน้าที่เป็น Container เก็บผู้ป่วยไว้ภายใน
เป็นต้น
3. Relationship
Loop
เกิดขึ้นเนื่องจากวัตถุทำความสัมพันธ์กับวัตถุที่อยู่ในตระกูลเดียวกัน
ตัวอย่างเช่น ความสัมพันธ์ระหว่างบุคคลสองคนคือ ผู้ป่วยกับแพทย์
ซึ่งทั้งสองวัตถุนี้ต่างก็เป็นชนิด Person เหมือนกัน
ในการออกแบบที่ระดับคอนเซ็ปท์
(Conceptual
Design) มักจะพบ Relationship Loop อยู่เสมอ
แต่ในขณะที่ออกแบบไปถึงระดับรายละเอียด (Detailed Design) แล้ว
สถาปนิกซอฟแวร์มักจะพยายามเปลี่ยน Relationship Loop ให้กลายเป็น
Binary Association ระหว่างคลาสที่เป็นเจ้าของบทบาท (Role
Player) กับคลาสที่เป็นบทบาท (Role) โดยใช้เทคนิคของ
Handle-Body [Coplien 92] หรือใช้ดีไซน์แพทเทิร์นชื่อ Bridge
[GoF 95]
4. Handle-Body
เป็นวิธีการออกแบบโครงสร้างคลาสโดยแยกส่วนที่เป็นคุณสมบัติของวัตถุออกมาเป็นวัตถุอีกชนิดหนึ่ง
เมื่อแยกคุณสมบัติ
ออกมาจากตัววัตถุแล้วเราจะสามารถแบ่งแยกชนิดของคุณสมบัติให้มีรายละเอียดปลีกย่อยอย่างไรก็ได้
โดยใช้วิธีการสืบทอดแล้วเพิ่มความสามารถพิเศษใส่เข้าไปในคลาสลูก
ในภาพที่
28 จะสังเกตเห็นว่าเราสามารถดึงบทบาทของ Person แยกออกมาเป็นส่วน
Handle ต่างหากจากส่วน Body ซึ่งก็คือตัว
Person นั่นเอง และเนื่องจากบุคคลหนึ่งคนสามารถมีบทบาทได้หลายชนิดเราจึงสืบทอดคลาส
PersonRole ต่อมาเป็นคลาส Patient และคลาส
Doctor
การออกแบบด้วยวิธีของ
Handle-Body
จะทำให้ได้วัตถุที่มีรายละเอียดในส่วน Handle สมบูรณ์และไม่ยึดติดอยู่กับส่วน
Body สำหรับส่วน Body เองจะเป็นคุณสมบัติที่เป็นแก่นแท้ของวัตถุชนิดนั้น
ๆ และไม่เปลี่ยนไปตาม Handle ที่นำมาต่อเข้าด้วยกัน
การออกแบบด้วย
Handle-Body
มักจะถูกนำมาใช้ในการแบ่งระดับของแอพพลิชันออกเป็นหลาย ๆ ชั้นโดยส่วนที่เป็น Handle ก็คือชั้นที่รับหน้าที่บางอย่างมาทำ และสามารถเปลี่ยนชนิดของ Handle
ได้อย่างหลากหลาย
5. Dynamic Schema
เป็นเทคนิคที่ใช้ลดการสืบทอดที่ไม่จำเป็น
และเพื่อทำให้เกิดโครงสร้างข้อมูลที่ยืดหยุ่น สามารถเปลี่ยนแปลงได้ตลอดเวลา ซึ่ง Schema ก็คือวัตถุที่ใช้สำหรับเก็บโครงสร้างข้อมูลให้กับวัตถุอื่นอีกทีหนึ่ง
จากภาพที่
29 ถ้าใช้เทคนิคของ Dynamic Schema จะประกอบด้วย 2
ส่วนคือส่วนที่เป็น Schema ก็คือโครงสร้างวัตถุที่เป็นแม่แบบ
(Template) ให้กับวัตถุกลุ่มหนึ่ง เช่นในภาพนี้ วัตถุ Category
ใช้สำหรับเป็นแม่แบบให้กับวัตถุ Part และวัตถุ
Property ใช้สำหรับเป็นแม่แบบให้กับวัตถุ Attribute
จากภาพที่
30 จะเห็นว่า เราสามารถสร้างตระกูลของชิ้นส่วน (Part) ให้ได้ตามที่ระบบงานต้องการ
โดย ImportedPart คือชิ้นส่วนที่นำเข้ามาจากต่างประเทศ และ AsianPart
คือชิ้นส่วนที่นำเข้าจากประเทศในกลุ่มอาเซียน และ JapanPart คือชิ้นส่วนที่นำเข้าจากประเทศญี่ปุ่น จากโครงสร้างดังกล่าวนี้
ถ้าในอนาคตมีประเภทของชิ้นส่วนประเภทใหม่เกิดขึ้น
จะทำให้เราต้องแก้ไขโครงสร้างดังกล่าวนี้ให้สามารถรองรับประเภทใหม่
แต่เนื่องจากการแก้ไข Inhertiance เป็นเรื่องทางโปรแกรมที่ผู้ใช้ทั่วไปไม่สามารถแก้ไขได้
จะต้องให้โปรแกรมเมอร์เป็นคนแก้ไขโปรแกรมแล้วคอมไพล์โปรแกรมใหม่
ซึ่งเราจะเห็นว่าเป็นวิธีการที่ไม่สะดวกมากถ้าผู้ใช้ต้องการเพิ่มประเภทชิ้นส่วนใหม่
ๆ เข้าไปในระบบอยู่เรื่อย ๆ
ถ้าเราจัดโครงสร้างด้วยวิธี
Dynamic
Schema ตามภาพที่ 29 จะสามารถแก้ปัญหาดังกล่าวในภาพที่
30 ได้ และเมื่อนำมาเขียนเป็นโปรแกรมเพื่อเรียกใช้งาน
จะได้โปรแกรมคล้ายกับในภาพที่ 31 ซึ่งเราจะสังเกตเห็นว่าโปรแกรมในภาพที่
31 ไม่มีการจำเพาะเจาะจงชื่อคลาสลงไปว่าเป็นชิ้นส่วนประเภทใด
(สังเกตในภาพที่ 30 มีการจำเพาะเจาะจงชื่อคลาสไว้ชื่อว่า ImportedPart)
และในภาพที่ 31 ไม่มีการจำเพาะเจาะจงชื่อของแอททริบิวท์ด้วย
แต่ให้ค่าแอททริบิวท์เป็นสตริงหรือค่าตัวเลขที่ใส่เข้าไปในวัตถุ StringAttribute
หรือวัตถุ FloatAttribute ตามลำดับ
6.
Shared Object Pool
การสร้างวัตถุขึ้นใหม่ทุกครั้งขณะที่ต้องการใช้งาน
เป็นวิธีการที่ยังไม่ปราณีตเพียงพอและอาจจะทำให้เกิดปัญหาหน่วยความจำไม่เพียงพอ
ถ้าหากว่ามีจำนวนวัตถุที่อยู่ในระบบมากเกินไป
วิธีการที่เหมาะสมก็คือเราควรจะสร้างวัตถุให้อยู่ในปริมาณที่พอเหมาะกับทรัพยากร[24]ที่เครื่องเซิร์ฟเวอร์สามารถรองรับได้
Pool
เป็นโครงสร้างข้อมูลแบบหนึ่ง แต่ใช้คำว่า Pool เนื่องจากมีการจำกัดจำนวนวัตถุสูงสุดที่อยู่ภายใน Pool ว่าสามารถมีวัตถุได้กี่ตัว และวัตถุที่อยู่ภายใน Pool ทุกตัวจะสมมุติว่าไม่มีความแตกต่างกัน โดยไคลเอ็นต์ที่จะใช้วัตถุจาก Pool
สามารถหยิบวัตถุตัวใดตัวหนึ่งภายใน Pool มาใช้งานก็ได้
จากภาพที่
32 สังเกตว่า Pool นี้สามารถเก็บวัตถุได้เพียง 6
ชิ้น เมื่อไคลเอ็นต์ต้องการใช้งานวัตถุ
ไคลเอ็นต์จะไม่ได้สร้างวัตถุขึ้นใหม่ แต่จะมาขอยืมวัตถุไปจาก Pool และเมื่อไคลเอ็นต์ใช้วัตถุนั้นเสร็จแล้วก็จะคืนกลับมาที่ Pool เพื่อให้ไคลเอ็นต์คนอื่นสามารถแบ่งปันไปใช้งานต่อได้
การออกแบบโมเดลของวัตถุโดยใช้รูปแบบขั้นสูง
จากรูปแบบทั้ง
6 ที่ใช้ในการออกแบบขั้นพื้นฐานยังไม่เพียงพอสำหรับการนำไปออกแบบระบบงานที่มีความซับซ้อนและต้องการความยืดหยุ่นสูง
ระบบงานที่ดีจะต้องง่ายต่อการปรับเปลี่ยนไปตามความต้องการที่เกิดขึ้นใหม่ ๆ ของผู้ใช้ระบบ
การเพิ่มคุณลักษณะใหม่เข้าไปในระบบจะต้องสามารถทำได้ง่าย
เหมือนกับการถอดประกอบชิ้นส่วนในผลิตภัณฑ์อื่น ๆ
ในหัวข้อนี้จะนำเสนอรูปแบบ
23 แบบ ที่เป็นนิยมนำมาออกแบบซอฟแวร์ โดยทั้ง 23 แบบนี้ถูกรวบรวมไว้ครั้งแรกในหนังสือ
The Reusable of Software Design Pattern ซึ่งเขียนโดย GoF[25] และตีพิมพ์เผยแพร่เมื่อปี
1995 จนกระทั่งถึงปัจจุบันจะพบว่าเฟรมเวิร์ค[26]เกือบทั้งหมดมีการนำหลักการของ
Design
Pattern เข้าไปร่วมด้วยไม่มากก็น้อย
ตารางที่ 2 รูปแบบทั้ง
23 แบบของ GoF
Pattern
|
Intent
|
1.
Abstract Factory
|
Interface
สำหรับสร้าง Product ที่อยู่ในตระกูลเดียวกัน
โดยที่ Client ไม่จำเป็นต้องรู้ว่ากระบวนการสร้างเป็นอย่างไร
และ Product ในตระกูลทำงานร่วมกัน
|
2.
Builder
|
แยกกระบวนการสร้างวัตถุที่มีโครงสร้างซับซ้อน
ออกจากส่วนแสดงผลเพื่อที่จะใช้กระบวนการสร้างแบบเดียวกันนี้ได้กับการแสดงผลหลายแบบ
|
3.
Factory Method
|
สร้าง
Framework
สำหรับให้ Subclass มา Override เพื่อสร้างวัตถุที่ต้องการ
|
4.
Prototype
|
สร้าง
Object
ขึ้นมาใหม่โดย Copy จากตัวที่ใช้เป็นแม่แบบอยู่แล้ว
|
5.
Singleton
|
ต้องการควบคุมให้มี
Object
เพียงตัวเดียวเท่านั้นตลอดการใช้งาน
|
6.
Adapter
|
เชื่อมต่อเข้ากับอีกระบบที่มี
Interface
ไม่ตรงกัน โดยห่อหุ้ม (Wrap) อีกระบบหนึ่งด้วย
Interface ที่ทำขึ้นมาใหม่ให้ตรงใจเรา
|
7.
Bridge
|
แยกส่วน
Abstract
ออกจากส่วน Implementation เพื่อที่สองส่วนนี้จะได้เปลี่ยนแปลงไปได้อย่างอิสระ
|
8.
Composite
|
สร้างโครงสร้างของ
Object
ในรูปแบบโครงสร้างแบบต้นไม้ (Tree)
|
9.
Decorator
|
ต่อเติมส่วนประกอบของ
Object
ในขณะ Runtime โดยไม่จำเป็นต้อง Subclass
แล้ว Override
|
10. Façade
|
รวบรวมการสั่งงานทั้งระบบมาไว้ที่
Interface
เดียวกัน เพื่อให้ใช้ระบบได้ง่าย
|
11. Flyweight
|
เมื่อต้องรับมือกับ
Object
จำนวนมหาศาล
|
12. Proxy
|
เมื่อต้องการป้องกันการเข้าถึงตัว
Object
โดยแทรกงานบางอย่างเข้าไปก่อน
|
13. Chain of Responsibility
|
ส่งงานให้กับ
Object
ทุกตัวที่อยู่ในสายงาน จนกว่าจะมีตัวใดตัวหนึ่งช่วยทำจนเสร็จ
|
14. Command
|
ทำให้คำสั่งงานเป็น
Object
เพื่อที่จะได้เก็บไว้ในคิวงานหรือ Undo ได้
|
15. Interpreter
|
สร้างไวยากรณ์ภาษาขึ้นใช้เองในแอพพลิเคชัน
|
16. Iterator
|
เข้าถึง
Object
ทุกตัวที่อยู่ในกลุ่ม โดยที่ไม่จำเป็นต้องรู้โครงสร้างภายใน
|
17. Mediator
|
เป็นคนกลางคอยรับส่งงานให้กับ
Object
ที่อยู่ในกลุ่ม โดยไม่ต้องให้ Object เหล่านั้นเชื่อมต่อกันโดยตรง
|
18. Memento
|
ทำให้
Object
สามารถคืนสู่สภาพเดิมได้
|
19. Observer
|
เมื่อ
Object
มีการเปลี่ยนแปลง ทุกตัวที่สังเกตการณ์อยู่จะได้รับสัญญาณ
|
20. State
|
เมื่อ
Object
เปลี่ยนสถานะ ทำให้มีการกระทำที่แตกต่างกันออกไป
|
21. Strategy
|
กลุ่มของ
Algorithm
ที่สามารถสลับสับเปลี่ยนได้ในขณะ Runtime
|
22. Template Method
|
ขั้นตอนการทำงานอยู่ใน Method ของคลาสแม่ แต่วิธีทำในแต่ละขั้นตอนอยู่ในคลาสลูก
|
23. Visitor
|
แยกกระบวนการที่ต้องทำกับ
Object
ทุกตัวในโครงสร้างออกมาเพื่อให้สามารถเพิ่มกระบวนการใหม่ ๆ ให้กับ Object ในโครงสร้างได้โดยที่ไม่กระทบโครงสร้าง
|
ทั้ง 23 แบบนี้จะถูกแบ่งออกเป็น 3 กลุ่มเพื่อใช้สำหรับแก้ปัญหาหลักในการออกแบบ
3 อย่าง คือ
1. Creational Pattern ใช้สำหรับแก้ปัญหาการสร้างวัตถุว่าทำอย่างไรจึงจะสามารถจัดรูปแบบการสร้างวัตถุให้อยู่ในแบบที่ง่ายต่อการเปลี่ยนแปลง
เมื่อมีวัตถุชนิดใหม่เกิดขึ้นในอนาคตเราจะต้องเปลี่ยนแปลงน้อยที่สุด
แต่สามารถนำระบบไปใช้ต่อได้ทันที
2. Structural Pattern ใช้สำหรับแก้ปัญหาการจัดวางโครงสร้างและองค์ประกอบของวัตถุ
เพื่อให้วัตถุมาประกอบต่อกันด้วยโครงสร้างที่ง่ายต่อการเปลี่ยนแปลงในอนาคต
เปรียบเสมือนกับการเสียบปลั๊กไฟ หรือการถอดชิ้นส่วนในอุปกรณ์ไฟฟ้า
ซึ่งจะต้องมีโครงสร้างยืดหยุ่นพอที่จะถอดประกอบได้ตลอดเวลา
3. Behavioral Pattern ใช้สำหรับแก้ปัญหาการแปรเปลี่ยนการทำงานของวัตถุ
เพื่อให้วัตถุสามารถทำงานที่แตกต่างกันในสภาวะแวดล้อมที่แตกต่างกันได้
ในอนาคตโดยไม่ต้องเปลี่ยนแปลงส่วนการทำงานหลักของวัตถุ นอกจากนั้นยังใช้สำหรับแก้ปัญหาการใช้เงื่อนไขในโปรแกรมที่สลับซับซ้อนจนยากต่อการถอดประกอบ
เมื่อใช้รูปแบบในกลุ่มนี้จะช่วยลดความซับซ้อนและเพิ่มความเป็นระเบียบแบบแผนให้กับการทำงานของวัตถุได้
ตารางที่ 3 ประเภทของ
Design Pattern ทั้ง 3 ประเภทแยกตามรูปแบบการนำไปแก้ปัญหา
Creational
Pattern
|
Structural
Pattern
|
Behavioral
Pattern
|
Abstract
Factory
Builder
Factory
Method
Prototype
Singleton
|
Composite
Bridge
Adapter
Decorator
Flyweight
Proxy
Façade
|
Observer
Mediator
Visitor
Iterator
Memento
Strategy
State
Template
Method
Chain
of Responsibility
Interpreter
Command
|
[1] แอททริบิวท์
หมายถึงส่วนข้อมูล เนื่องจากหนังสือบางเล่มใช้คำศัพท์ต่างกัน
คำว่าแอททริบิวท์ใช้ในเชิงของทฤษฏี Object-Oriented สำหรับคำว่า
ส่วนข้อมูล (Member Data) หรือ ตัวแปรอินสแตนซ์ (Instance
Variable) เป็นคำศัพท์ที่เกิดขึ้นเนื่องจากการนำทฤษฏีไปประยุกต์ใช้ในภาษา
C++ และภาษา Java ตามลำดับ
[2] จำนวนของวัตถุขึ้นอยู่กับความต้องการของระบบ
และประสิทธิภาพของเครื่องเซิร์ฟเวอร์ที่สามารถรองรับได้
[3] ในภาษาโปรแกรมปัจจุบันอย่างเช่น
ภาษา Java, JavaScript, C#, VB.NET จะมีคุณลักษณะที่เรียกว่า
Gabage Collection ไว้สำหรับเก็บวัตถุที่เป็นขยะให้ออกไปจากหน่วยความจำ
(Heap Memory) เพื่อให้มีพื้นที่หน่วยความจำใช้สอยมากขึ้น
[4] ความสัมพันธ์กับวัตถุตัวเองเราเรียกว่า
Self Reference ใช้ในกรณีพิเศษบางอย่าง ตัวอย่างเช่น
เป็นวัตถุรูทของโครงข่าย
[5] แม้ว่าเส้นจะเชื่อมโยงระหว่างคลาสแต่แท้ที่จริงคือความสัมพันธ์ระหว่างตัววัตถุแต่ละตัว
ดังนั้นเมื่อผู้อ่านไดอะแกรมเห็นเส้นเชื่อมโยงความสัมพันธ์ขอให้ระลึกไว้เสมอว่าไม่ใช่ความสัมพันธ์ของคลาสกับคลาสแต่เป็นความสัมพันธ์ของวัตถุที่เกิดขึ้นจากคลาสนั้น
[6] โปรแกรมที่มาเรียกใช้วัตถุ
โดยนำคลาสไปสร้างเป็นวัตถุแล้วสั่งงานตามเมธอดต่างๆที่วัตถุได้จัดเตรียมไว้ให้
[7] ตามแนวคิดแบบ Encapsulation
เพื่อป้องกันสถานะของวัตถุให้อยู่ในสถานะที่ถูกต้องตามที่ระบบงานต้องการเสมอ
[8] เครื่องหมาย [*]
ในไดอะแกรมหมายถึงการส่งคืนค่ากลับมาเป็นกลุ่มของวัตถุ
ซึ่งอาจจะไม่ใช่วัตถุเพียงตัวเดียว
[9] แม้ว่าในไดอะแกรมจะแสดงภาพของคลาส
แต่แท้ที่จริงเป็นการนับจำนวนวัตถุที่สัมพันธ์กัน
[10] เป็นคำบรรยายถึงคุณลักษณะบางอย่างของระบบงานที่เรากำลังวิเคราะห์และออกแบบโดยตัดเอามาเฉพาะบางส่วนของระบบทั้งหมด
[12] อ่านว่า
One to Many
[13] เราเรียกส่วนที่เปิดเผยให้ผู้ใช้วัตถุเห็นว่า
Public Interface
[14] เป็นวัตถุที่ถูกสร้างมาจากคลาสลูกที่สืบทอดมาจากคลาสแม่เดียวกัน
หรือเป็นวัตถุที่ถูกสร้างมาจากคลาสที่อิมพลีเมนต์จากอินเตอร์เฟสเดียวกัน
[17] หนังสือบางเล่มใช้คำว่า
Hook หรือคำว่า Subclassing
[19] เรียกว่า
Virtual Method Invocation
[21] ในทางอุดมคติ
เฟรมเวิร์คควรจะสามารถนำไปประยุกต์ใช้ได้กับทุกๆระบบที่อยู่ในโดเมน (Domain) เดียวกัน
[22] อิมพลีเมนต์โค้ด
คือโค้ดส่วนที่อยู่ในตัววัตถุ เช่นโค้ดในเมธอด
ที่รับผิดชอบทำงานให้ตามหน้าที่ที่ได้รับมอบหมาย
[24] หมายถึง CPU, หน่วยความจำ, จำนวน Network Connection, พื้นที่ว่างในฮาร์ดดิสก์, จำนวน Service
Thread
[26] เช่น
Java 2 Standard Edition, Java 2 Enterprise Edition, .NET Framework หรือแม้แต่แอพพลิเคชันทางธุรกิจทั่วๆไป
ความคิดเห็น
แสดงความคิดเห็น