นี่คือโพสต์ที่แปลด้วย AI
[วัตถุ] บทที่ 2. การเขียนโปรแกรมเชิงวัตถุ
- ภาษาที่เขียน: ภาษาเกาหลี
- •
- ประเทศอ้างอิง: ทุกประเทศ
- •
- เทคโนโลยีสารสนเทศ
เลือกภาษา
สรุปโดย AI ของ durumis
- อธิบายรูปแบบการเขียนโปรแกรมเชิงวัตถุเพื่อใช้ในการสร้างระบบจองตั๋วภาพยนตร์ รวมถึงการแนะนำแนวคิดของการทำงานร่วมกัน วัตถุ และคลาส โดยเน้นโครงสร้างโปรแกรมที่เป็นไปตามโครงสร้างโดเมน
- โดยเฉพาะการรักษาความเป็นอิสระของวัตถุและการห่อหุ้มเพื่อลดการแทรกแซงจากภายนอก รวมถึงการแยกอินเทอร์เฟซและการใช้งานเพื่อ รับประกันเสรีภาพของนักพัฒนา
- นอกจากนี้ยังอธิบายวิธีการเขียนโค้ดที่ยืดหยุ่นและสามารถขยายได้โดยใช้การทำงานร่วมกัน การสืบทอด และการพหุรูปลักษณะเพื่อคำนวณ ค่าส่วนลด รวมถึงเน้นย้ำถึงความสำคัญของการนามธรรมและข้อดีของการประพันธ์เพื่อนำโค้ดกลับมาใช้ใหม่
ระบบจองตั๋วภาพยนตร์
ตรวจสอบข้อกำหนด
- เราต้องการสร้างระบบจองตั๋วภาพยนตร์ออนไลน์
- ภาพยนตร์แสดงข้อมูลพื้นฐานเกี่ยวกับภาพยนตร์
- ชื่อเรื่อง เวลาฉาย ข้อมูลราคา ฯลฯ
- การฉายแสดงถึงเหตุการณ์จริงที่ผู้ชมชมภาพยนตร์
- วันที่ฉาย เวลา หมายเลขการฉาย ฯลฯ
- ผู้คนจองตั๋วภาพยนตร์ แต่จริงๆ แล้วพวกเขาจองตั๋วภาพยนตร์ที่เฉพาะเจาะจงการฉายถูกต้อง
- เงื่อนไขส่วนลด
- ส่วนลดราคาหรือไม่
- เงื่อนไขตามลำดับ: ใช้หมายเลขการฉายเพื่อกำหนดส่วนลดหรือไม่
- เงื่อนไขระยะเวลา: ใช้เวลาเริ่มต้นการฉายภาพยนตร์เพื่อกำหนดส่วนลดหรือไม่
- นโยบายส่วนลด
- กำหนดอัตราส่วนลด
- นโยบายส่วนลดจำนวนเงิน: ส่วนลดจำนวนเงินคงที่จากค่าธรรมเนียมการจอง
- นโยบายส่วนลดเปอร์เซ็นต์: ส่วนลดเปอร์เซ็นต์คงที่จากราคาปกติ
- แต่ละภาพยนตร์สามารถกำหนดนโยบายส่วนลดได้เพียงหนึ่งนโยบายหรือไม่เลย และเงื่อนไขส่วนลดสามารถผสมผสานเงื่อนไขส่วนลดหลายอย่างเข้าด้วยกันได้
- หากมีการใช้นโยบายส่วนลด แต่เงื่อนไขส่วนลดไม่ตรงตามเงื่อนไข หรือไม่มีการใช้นโยบายส่วนลด ค่าธรรมเนียมจะไม่ถูก ส่วนลด
สู่การเขียนโปรแกรมเชิงวัตถุ
ความร่วมมือ วัตถุ คลาส
- การเขียนโปรแกรมเชิงวัตถุคือการมุ่งเน้นไปที่วัตถุ
- หลังจากตัดสินใจเกี่ยวกับคลาสแล้ว ไม่ควรพิจารณาว่าคลาสต้องการคุณสมบัติและวิธีการใด
- คุณต้องตัดสินใจว่าวัตถุใดมีสถานะและพฤติกรรมอย่างไร
- วัตถุไม่ควรเป็นหน่วยอิสระ แต่ควรเป็นส่วนหนึ่งของชุมชนที่ทำงานร่วมกัน
โครงสร้างโปรแกรมที่สอดคล้องกับโครงสร้างโดเมน
- โดเมนคือสาขาที่ผู้ใช้ใช้โปรแกรมเพื่อแก้ไขปัญหา
- โดยทั่วไป ชื่อของคลาสควรเหมือนกันหรืออย่างน้อยคล้ายกับชื่อของแนวคิดโดเมนที่เกี่ยวข้อง
- ความสัมพันธ์ระหว่างคลาสควรคล้ายกับความสัมพันธ์ที่เกิดขึ้นระหว่างแนวคิดโดเมนให้มากที่สุดเพื่อให้โครงสร้างของโปรแกรม เข้าใจและคาดเดาได้ง่าย
การนำคลาสไปใช้
- คลาสแบ่งออกเป็นส่วนภายในและส่วนภายนอก และเพื่อออกแบบคลาสที่ยอดเยี่ยม คุณต้องตัดสินใจว่าจะเปิดเผยส่วนใดต่อ สาธารณะและซ่อนส่วนใด
- คุณสมบัติของวัตถุถูกปิดกั้นเป็นส่วนตัว และวิธีการที่จำเป็นในการเปลี่ยนแปลงสถานะภายในจะถูกเปิดเผยเป็น สาธารณะ
- การแยกส่วนภายในและภายนอกของคลาสช่วยรับประกันความเป็นอิสระของวัตถุ ทำให้โปรแกรมเมอร์มีอิสระในการ นำไปใช้
วัตถุที่เป็นอิสระ
- วัตถุควรเป็นวัตถุที่เป็นอิสระที่มีสถานะและพฤติกรรม
- การรวมข้อมูลและฟังก์ชันเข้าด้วยกันภายในวัตถุเรียกว่าการห่อหุ้ม
- การควบคุมการเข้าถึงควรลดการแทรกแซงจากภายนอก เพื่อให้วัตถุสามารถตัดสินใจเกี่ยวกับการกระทำของตนเองได้
- หลักการแยกส่วนต่อประสานและการนำไปใช้เป็นหลักการสำคัญที่ต้องปฏิบัติตามเพื่อการเขียนโปรแกรมเชิงวัตถุ
- อินเทอร์เฟซสาธารณะ: ส่วนที่สามารถเข้าถึงได้จากภายนอก
- การนำไปใช้: ส่วนที่สามารถเข้าถึงได้ภายในเท่านั้น
เสรีภาพของโปรแกรมเมอร์
- บทบาทของโปรแกรมเมอร์แบ่งออกเป็นนักเขียนคลาสและโปรแกรมเมอร์ไคลเอนต์
- นักเขียนคลาสเพิ่มประเภทข้อมูลใหม่
- โปรแกรมเมอร์ไคลเอนต์ใช้ประเภทข้อมูลที่นักเขียนคลาสเพิ่ม
- การซ่อนการนำไปใช้
- นักเขียนคลาสสามารถซ่อนการนำไปใช้ภายในโดยการมอบเฉพาะส่วนที่จำเป็นให้กับโปรแกรมเมอร์ไคลเอนต์
- โปรแกรมเมอร์ไคลเอนต์เพียงรู้ส่วนต่อประสานเท่านั้น ดังนั้นจึงสามารถลดปริมาณความรู้ได้
ชุมชนของวัตถุที่ทำงานร่วมกัน
- เมื่อแสดงเงิน ไม่ควรประกาศตัวแปรประเภท Long อย่างง่าย แต่ควรห่อหุ้มด้วยวัตถุ เช่น Money การใช้วัตถุช่วยให้ การส่งข้อความมีความหมายมากขึ้น และสามารถดำเนินการคำนวณซ้ำๆ ได้ในที่เดียว
- การโต้ตอบที่เกิดขึ้นระหว่างวัตถุเพื่อดำเนินการบางอย่างในระบบเรียกว่าการทำงานร่วมกัน
เรื่องราวสั้น ๆ เกี่ยวกับความร่วมมือ
- วิธีเดียวที่วัตถุสามารถโต้ตอบกับวัตถุอื่นได้คือการส่งหรือรับข้อความ
- วิธีการของตนเองในการจัดการข้อความที่ได้รับเรียกว่าวิธีการ
- การแยกข้อความและวิธีการเป็นสิ่งสำคัญ และนี่คือจุดเริ่มต้นของแนวคิดของความหลากหลาย
ค้นหาค่าธรรมเนียมส่วนลด
เริ่มต้นความร่วมมือเพื่อคำนวณค่าธรรมเนียมส่วนลด
- คลาส Movie ไม่ได้มีตรรกะที่ซับซ้อนเกี่ยวกับนโยบายส่วนลด แต่ได้มอบหมายให้กับอินเทอร์เฟซ DiscountPolicy การใช้การสืบทอด ความหลากหลาย และการทำให้เป็นนามธรรมเป็นสิ่งสำคัญอย่างยิ่ง
นโยบายส่วนลดและเงื่อนไขส่วนลด
การสืบทอดและความหลากหลาย
การพึ่งพาเวลาคอมไพล์และการพึ่งพาเวลาทำงาน
- การพึ่งพาของโค้ดและการพึ่งพาเวลาทำงานอาจแตกต่างกัน
- ยิ่งการพึ่งพาระหว่างกันมีความแตกต่างมากขึ้นเท่าใด ก็ยิ่งทำให้เข้าใจโค้ดได้ยากขึ้น แต่ก็ทำให้โค้ดมีความยืดหยุ่นและ สามารถขยายได้มากขึ้น
การเขียนโปรแกรมโดยเน้นความแตกต่าง
- การสืบทอดช่วยให้สามารถเพิ่มคลาสใหม่ได้อย่างรวดเร็วและง่ายดายบนพื้นฐานของคลาสที่มีอยู่ และสามารถนำการนำไปใช้ ของคลาสพาเรนต์มาใช้ซ้ำได้
- วิธีการสร้างคลาสใหม่โดยเพิ่มเฉพาะส่วนที่แตกต่างจากคลาสพาเรนต์เรียกว่าการเขียนโปรแกรมโดยเน้นความแตกต่าง
การสืบทอดและอินเทอร์เฟซ
- การสืบทอดทำให้คลาสลูกสืบทอดส่วนต่อประสานทั้งหมดที่คลาสพาเรนต์มอบให้
- อินเทอร์เฟซกำหนดรายการข้อความที่วัตถุสามารถเข้าใจได้
public class Movie {
public Money calculateMovieFee(Screening screening) {
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
- Movie ส่งข้อความ calculateDiscountAmount ไปยัง DiscountPolicy Movie ไม่สนใจว่าอินสแตนซ์ของคลาสใดตอบสนอง ตราบใดที่การตอบสนองนั้นประสบความสำเร็จ
- ดังนั้น AmountDiscountPolicy และ PercentDiscountPolicy สามารถทำงานร่วมกับ Movie ได้ แทนที่ DiscountPolicy
- การที่คลาสลูกแทนที่คลาสพาเรนต์เรียกว่าการอัพแคสต์ เนื่องจากดูเหมือนว่าคลาสลูกจะถูกแปลงประเภทเป็นคลาส พาเรนต์ที่อยู่ด้านบนโดยอัตโนมัติ
ความหลากหลาย
- ความหลากหลายหมายถึงความสามารถในการตอบสนองต่าง ๆ ตามประเภทของวัตถุเมื่อได้รับข้อความเดียวกัน
- Movie ส่งข้อความเดียวกัน แต่การเรียกใช้วิธีการจริงขึ้นอยู่กับว่าคลาสของวัตถุที่ได้รับข้อความคืออะไร
- ความหลากหลายนั้นขึ้นอยู่กับความจริงที่ว่าการพึ่งพาของโปรแกรมอาจแตกต่างกันไปในเวลาคอมไพล์และเวลาทำงาน
- ความหลากหลายกำหนดวิธีการที่จะเรียกใช้ในเวลาทำงาน ดังนั้นจึงเรียกว่าการผูกมัดล่าช้าหรือการผูกมัดแบบไดนามิก
อินเทอร์เฟซและความหลากหลาย
- หากคุณไม่ต้องการแชร์การนำไปใช้ แต่ต้องการแชร์เฉพาะส่วนต่อประสาน คุณสามารถใช้อินเทอร์เฟซแทนคลาส นามธรรมได้
การทำให้เป็นนามธรรมและความยืดหยุ่น
พลังแห่งการทำให้เป็นนามธรรม
- ข้อดีของการทำให้เป็นนามธรรม
- หากคุณดูเฉพาะลำดับชั้นการทำให้เป็นนามธรรมเท่านั้น คุณสามารถอธิบายนโยบายของข้อกำหนดในระดับสูง
- การออกแบบมีความยืดหยุ่นมากขึ้น
การออกแบบที่ยืดหยุ่น
- การทำให้เป็นนามธรรมช่วยป้องกันการออกแบบไม่ให้ผูกติดกับสถานการณ์ที่เฉพาะเจาะจง ดังนั้นจึงสามารถสร้างการออกแบบ ที่ยืดหยุ่น
การแลกเปลี่ยนระหว่างคลาสนามธรรมและอินเทอร์เฟซ
public abstract class DiscountPolicy {
private List conditions;
public DiscountPolicy(DiscountCondition... conditions) {
this.conditions = Arrays.asList(conditions);
}
public Money calculateDiscountAmount(Screening screening) {
for (DiscountCondition condition : conditions) {
if (condition.isSatisfiedBy(screening)) {
return getDiscountAmount(screening);
}
}
return Money.ZERO;
}
abstract protected Money getDiscountAmount(Screening screening);
}
public class NoneDiscountPolicy extends DiscountPolicy {
@Override
protected Money getDiscountAmount(Screening screening) {
return Money.ZERO;
}
- ในปัจจุบัน NoneDiscountPolicy นั้นแท้จริงแล้วไม่จำเป็น เพราะวิธีการ calculateDiscountAmount() ของ DiscountPolicy จะส่งคืน 0 หากไม่มีเงื่อนไขส่วนลด ดังนั้นจึงไม่มีปัญหาใดๆ อย่างไรก็ตาม จากมุมมองของผู้ใช้ จำเป็นต้องใส่ None policy ที่ไม่มีนโยบายส่วนลดเป็นอาร์กิวเมนต์ของ Movie ดังนั้นจึงได้เพิ่ม NoneDiscountPolicy เข้ามา
- ดังนั้น คลาส NoneDiscountPolicy จึงทำให้เกิดความสับสน ดังนั้นการแก้ไขดังต่อไปนี้จะทำให้เข้าใจได้ง่ายขึ้น
public interface DiscountPolicy {
Money calculdateDiscountAmount(Screening screening);
}
public abstract class DefaultDiscountPolicy implements DiscountPolicy {
private List conditions;
public DefaultDiscountPolicy(DiscountCondition... conditions) {
this.conditions = Arrays.asList(conditions);
}
public Money calculateDiscountAmount(Screening screening) {
for (DiscountCondition condition : conditions) {
if (condition.isSatisfiedBy(screening)) {
return getDiscountAmount(screening);
}
}
return Money.ZERO;
}
abstract protected Money getDiscountAmount(Screening screening);
}
public class NoneDiscountPolicy implements DiscountPolicy {
@Override
public Money calculateDiscountAmount(Screening screening) {
return Money.ZERO;
}
}
public class PercentDiscountPolicy extends DefaultDiscountPolicy {
private double percent;
public PercentDiscountPolicy(double percent, DiscountCondition... conditions) {
super(conditions);
this.percent = percent;
}
@Override
protected Money getDiscountAmount(Screening screening) {
return screening.getMovieFee().times(percent);
}
}
public class AmountDiscountPolicy extends DefaultDiscountPolicy {
private Money discountAmount;
public AmountDiscountPolicy(Money discountAmount, DiscountCondition... conditions) {
super(conditions);
this.discountAmount = discountAmount;
}
@Override
protected Money getDiscountAmount(Screening screening) {
return discountAmount;
}
- สิ่งนี้ทำให้ DiscountPolicy เป็นอินเทอร์เฟซแบบนามธรรม และแบ่งการนำไปใช้ออกเป็น NoneDiscountPolicy และ DefaultDiscountPolicy ซึ่งหมายถึงนโยบายส่วนลดทั่วไป
- คุณอาจคิดว่าการเพิ่มอินเทอร์เฟซเพียงเพื่อ NoneDiscountPolicy นั้นเป็นการเพิ่มความซับซ้อนมากเกินไป เมื่อเทียบกับประสิทธิภาพ
- คุณต้องตระหนักถึงความจริงที่ว่าทุกสิ่งที่เกี่ยวข้องกับการนำไปใช้เป็นเป้าหมายของการแลกเปลี่ยน ดังนั้นทุกโค้ดที่คุณเขียนควรมีเหตุผลที่ถูกต้อง
การนำโค้ดไปใช้ซ้ำ
- การสืบทอดสามารถใช้เพื่อนำโค้ดไปใช้ซ้ำได้
- แต่สำหรับการนำโค้ดไปใช้ซ้ำ การใช้การสังเคราะห์จะดีกว่าการสืบทอด
- ในโค้ดปัจจุบัน วิธีการที่ Movie นำโค้ดของ DiscountPolicy ไปใช้ซ้ำคือการสังเคราะห์
- หากคุณใช้ Movie เป็นคลาสระดับบน และแยกออกเป็น AmountDiscountMovie และ PercentDiscountMovie คุณกำลังใช้การสืบทอด
การสืบทอด
- ข้อเสียของการสืบทอด
- ละเมิดการห่อหุ้ม
- คุณต้องรู้โครงสร้างภายในของคลาสพาเรนต์
- โอกาสที่จะต้องเปลี่ยนคลาสลูกพร้อมกันกับการเปลี่ยนแปลงคลาสพาเรนต์นั้นสูง
- ทำให้การออกแบบไม่ยืดหยุ่น
- ความสัมพันธ์ระหว่างคลาสพาเรนต์และคลาสลูกถูกกำหนดในเวลาคอมไพล์
- การเปลี่ยนประเภทของวัตถุในเวลาทำงานเป็นไปไม่ได้
- แต่การสังเคราะห์ทำให้สามารถเปลี่ยนอินสแตนซ์ในเวลาทำงานได้ผ่านวิธีการ เช่น chageDiscountPolicy() ในฝั่งของวัตถุที่ใช้
- ละเมิดการห่อหุ้ม
การสังเคราะห์
- วิธีการนำโค้ดไปใช้ซ้ำโดยใช้เฉพาะข้อความที่กำหนดไว้ในส่วนต่อประสานเรียกว่าการสังเคราะห์
- สามารถใช้การห่อหุ้มและรักษาการเชื่อมโยงที่หลวมได้
- เมื่อใช้อินเทอร์เฟซเพื่อความหลากหลาย คุณต้องใช้การสืบทอดและการสังเคราะห์ร่วมกัน
- ตัวอย่างเช่น คุณต้องใช้การสืบทอดเพื่อนำไปใช้กับอินเทอร์เฟซ DiscountPolicy
แหล่งที่มา
- ออบเจกต์