ณ จุดนี้ คุณคงเคยเจอรูปแบบการออกแบบแล้ว ตัวอย่างเช่นซิงเกิลตัน .
ลองนึกดูว่ารูปแบบคืออะไร เหตุใดจึงต้องใช้ และรูปแบบที่สร้างสรรค์คืออะไร (ตัวอย่างจากซิงเกิล) นอกจากนี้ เราจะศึกษารูปแบบใหม่: วิธีการจากโรงงาน
ในการพัฒนาซอฟต์แวร์รูปแบบการออกแบบคือโครงสร้างทางสถาปัตยกรรมที่ทำซ้ำได้ซึ่งแสดงถึงวิธีแก้ปัญหาการออกแบบภายในบริบทที่เกิดซ้ำ
โดยทั่วไปแล้ว รูปแบบไม่ใช่โซลูชันขั้นสุดท้ายที่สามารถแปลงเป็นรหัสได้โดยตรง เป็นเพียงแบบจำลองการแก้ปัญหาที่สามารถนำไปใช้ในสถานการณ์ต่างๆ
รูปแบบการสร้างสรรค์คือรูปแบบการออกแบบที่เกี่ยวข้องกับกระบวนการสร้างวัตถุ ทำให้สามารถสร้างระบบที่เป็นอิสระจากวิธีที่ใช้ในการสร้าง เรียบเรียง และนำเสนอวัตถุ
เมธอดโรงงานเป็นรูปแบบการออกแบบเชิงสร้างสรรค์ที่กำหนดอินเทอร์เฟซทั่วไปสำหรับการสร้างออบเจกต์ในคลาสพาเรนต์ ทำให้สามารถสร้างออบเจกต์เหล่านี้ในระดับลูกหลานได้ ในขณะที่สร้าง ลูกหลานสามารถกำหนดได้ว่าจะสร้างคลาสใด
รูปแบบแก้ปัญหาอะไร
ลองนึกภาพว่าคุณตัดสินใจที่จะสร้างโปรแกรมการจัดส่ง เริ่มแรก คุณจะจ้างคนส่งของพร้อมรถและใช้กรถคัดค้านการเป็นตัวแทนของรถจัดส่งในโปรแกรม บริการจัดส่งพัสดุจากจุด A ไปยังจุด B เป็นต้น ง่ายนิดเดียว.
โปรแกรมกำลังได้รับความนิยม ธุรกิจของคุณกำลังเติบโตและคุณต้องการขยายไปสู่ตลาดใหม่ๆ ตัวอย่างเช่น คุณสามารถเริ่มส่งอาหารและขนส่งด้วย ในกรณีนี้ สามารถส่งอาหารโดยบริการจัดส่งด้วยการเดินเท้า สกู๊ตเตอร์ และจักรยาน แต่รถบรรทุกจำเป็นสำหรับการขนส่งสินค้า
ตอนนี้คุณต้องติดตามหลายสิ่งหลายอย่าง (เมื่อใด ให้ใคร อะไร และราคาเท่าไร) รวมถึงจำนวนที่ขนส่งแต่ละรายการสามารถบรรทุกได้ โหมดการขนส่งใหม่มีความเร็วและความจุที่แตกต่างกัน จากนั้นคุณสังเกตเห็นว่าเอนทิตีส่วนใหญ่ในโปรแกรมของคุณเชื่อมโยงอย่างมากกับรถระดับ. คุณทราบดีว่าเพื่อให้โปรแกรมของคุณทำงานร่วมกับวิธีการจัดส่งอื่นๆ ได้ คุณจะต้องเขียนโค้ดฐานที่มีอยู่ใหม่และทำใหม่ทุกครั้งที่คุณเพิ่มยานพาหนะใหม่
ผลลัพธ์ที่ได้คือโค้ดที่น่ากลัวซึ่งเต็มไปด้วยข้อความแสดงเงื่อนไขที่ดำเนินการต่างๆ กันขึ้นอยู่กับประเภทของการขนส่ง
การแก้ไขปัญหา
รูปแบบเมธอดโรงงานแนะนำให้สร้างอ็อบเจกต์โดยการเรียกเมธอดพิเศษจากโรงงานแทนที่จะใช้โอเปอเรเตอร์ใหม่ โดยตรง คลาสย่อยของคลาสที่มีเมธอดโรงงานสามารถแก้ไขวัตถุที่สร้างขึ้นของยานพาหนะเฉพาะได้ เมื่อมองแวบแรก สิ่งนี้อาจดูไม่มีจุดหมาย: เราเพิ่งย้ายการเรียกตัวสร้างจากที่หนึ่งในโปรแกรมไปยังอีกที่หนึ่ง แต่ตอนนี้คุณสามารถแทนที่เมธอดโรงงานในคลาสย่อยเพื่อเปลี่ยนประเภทการขนส่งที่กำลังสร้างได้
ลองดูแผนภาพชั้นเรียนสำหรับแนวทางนี้:
เพื่อให้ระบบนี้ทำงานได้ อ็อบเจ็กต์ที่ส่งคืนทั้งหมดต้องมีอินเทอร์เฟซร่วมกัน คลาสย่อยจะสามารถสร้างวัตถุของคลาสต่างๆ ที่ใช้อินเทอร์เฟซนี้
ตัวอย่างเช่น คลาส TruckและCarใช้ อินเทอร์เฟซ CourierTransportด้วยวิธีการส่งมอบ แต่ละประเภทเหล่านี้ใช้วิธีที่แตกต่างกัน: รถบรรทุกส่งสินค้า ในขณะที่รถยนต์ส่งอาหาร บรรจุภัณฑ์ และอื่นๆ เมธอดโรงงานใน คลาส TruckCreatorส่งคืนวัตถุรถบรรทุก และ คลาส CarCreatorส่งคืนวัตถุรถยนต์
สำหรับไคลเอ็นต์ของวิธีการโรงงาน ไม่มีความแตกต่างระหว่างวัตถุเหล่านี้ เนื่องจากมันจะถือว่าวัตถุเหล่านี้เป็นCourierTransport ที่ เป็นนามธรรม ลูกค้าจะสนใจอย่างลึกซึ้งว่าวัตถุมีวิธีการส่งมอบ แต่วิธีการทำงานนั้นไม่สำคัญ
การใช้งานใน Java:
public interface CourierTransport {
void deliver();
}
public class Car implements CourierTransport {
@Override
public void deliver() {
System.out.println("The package is being delivered by car");
}
}
public class Truck implements CourierTransport {
@Override
public void deliver() {
System.out.println("The freight is being delivered by truck");
}
}
public abstract class CourierTransportCreator {
public abstract CourierTransport createTransport();
}
public class CarCreator extends CourierTransportCreator {
@Override
public CourierTransport createTransport() {
return new Car();
}
}
public class TruckCreator extends CourierTransportCreator {
@Override
public CourierTransport createTransport() {
return new Truck();
}
}
public class Delivery {
private String address;
private CourierTransport courierTransport;
public void Delivery() {
}
public Delivery(String address, CourierTransport courierTransport) {
this.address = address;
this.courierTransport = courierTransport;
}
public CourierTransport getCourierTransport() {
return courierTransport;
}
public void setCourierTransport(CourierTransport courierTransport) {
this.courierTransport = courierTransport;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
public static void main(String[] args) {
// Accept a new type of order from the database (pseudocode)
String type = database.getTypeOfDeliver();
Delivery delivery = new Delivery();
// Set the transport for delivery
delivery.setCourierTransport(getCourierTransportByType(type));
// Make the delivery
delivery.getCourierTransport().deliver();
}
public static CourierTransport getCourierTransportByType(String type) {
switch (type) {
case "CarDelivery":
return new CarCreator().createTransport();
case "TruckDelivery":
return new TruckCreator().createTransport();
default:
throw new RuntimeException();
}
}
หากเราต้องการสร้างวัตถุนำส่งใหม่ โปรแกรมจะสร้างวัตถุขนส่งที่เหมาะสมให้โดยอัตโนมัติ
เราควรใช้รูปแบบนี้เมื่อใด
1. เมื่อคุณไม่ทราบล่วงหน้าถึงประเภทและการพึ่งพาของออบเจกต์ที่โค้ดของคุณจำเป็นต้องทำงานด้วย
วิธีการของโรงงานจะแยกรหัสสำหรับรูปแบบการขนส่งการผลิตออกจากรหัสที่ใช้การขนส่ง ด้วยเหตุนี้ โค้ดสำหรับสร้างออบเจกต์จึงขยายได้โดยไม่ต้องแตะโค้ดที่เหลือ
ตัวอย่างเช่น หากต้องการเพิ่มการรองรับสำหรับการขนส่งประเภทใหม่ คุณต้องสร้างคลาสย่อยใหม่และกำหนดวิธีการจากโรงงานซึ่งจะส่งคืนอินสแตนซ์ของการขนส่งใหม่
2. เมื่อคุณต้องการประหยัดทรัพยากรระบบโดยการนำวัตถุที่มีอยู่กลับมาใช้ใหม่แทนการสร้างวัตถุใหม่
ปัญหานี้มักเกิดขึ้นเมื่อทำงานกับวัตถุที่ใช้ทรัพยากรมาก เช่น การเชื่อมต่อฐานข้อมูล ระบบไฟล์ เป็นต้น
นึกถึงขั้นตอนที่คุณต้องทำเพื่อนำวัตถุที่มีอยู่กลับมาใช้ใหม่:
-
ขั้นแรก คุณต้องสร้างพื้นที่เก็บข้อมูลที่ใช้ร่วมกันเพื่อจัดเก็บวัตถุทั้งหมดที่คุณสร้างขึ้น
-
เมื่อขอวัตถุใหม่ คุณต้องดูในที่เก็บและตรวจสอบว่ามีวัตถุที่มีอยู่หรือไม่
-
ส่งคืนวัตถุไปยังรหัสลูกค้า
-
แต่ถ้าไม่มีอ็อบเจ็กต์ให้สร้างใหม่และเพิ่มไปยังที่เก็บ
ต้องใส่โค้ดทั้งหมดนี้ไว้ที่ใดที่หนึ่งซึ่งจะไม่เกะกะโค้ดไคลเอนต์ สถานที่ที่สะดวกที่สุดคือตัวสร้างเนื่องจากเราต้องการเพียงการตรวจสอบเหล่านี้ทั้งหมดเมื่อสร้างวัตถุ อนิจจา ตัวสร้างจะสร้างวัตถุใหม่เสมอ — มันไม่สามารถส่งคืนวัตถุที่มีอยู่ได้
นั่นหมายความว่าจำเป็นต้องมีวิธีอื่นที่สามารถส่งคืนทั้งวัตถุที่มีอยู่และวัตถุใหม่ นี่จะเป็นวิธีการของโรงงาน
3. เมื่อคุณต้องการอนุญาตให้ผู้ใช้ขยายส่วนต่างๆ ของเฟรมเวิร์กหรือไลบรารีของคุณ
ผู้ใช้สามารถขยายคลาสเฟรมเวิร์กของคุณผ่านการสืบทอด แต่คุณจะทำให้เฟรมเวิร์กสร้างวัตถุของคลาสใหม่เหล่านี้แทนที่จะเป็นคลาสมาตรฐานได้อย่างไร
วิธีแก้ไขคือให้ผู้ใช้ขยายไม่เพียงแค่คอมโพเนนต์เท่านั้น แต่ยังรวมถึงคลาสที่สร้างคอมโพเนนต์เหล่านั้นด้วย และสำหรับสิ่งนี้ การสร้างคลาสจะต้องมีวิธีการสร้างเฉพาะที่สามารถกำหนดได้
ข้อดี
- แยกคลาสออกจากคลาสการขนส่งเฉพาะ
- เก็บรหัสสำหรับสร้างรูปแบบการขนส่งไว้ในที่เดียว ทำให้รักษารหัสได้ง่ายขึ้น
- ลดความซับซ้อนของการเพิ่มโหมดการขนส่งใหม่ๆ ลงในโปรแกรม
- ใช้หลักการเปิด-ปิด
ข้อเสีย
อาจนำไปสู่ลำดับชั้นของคลาสคู่ขนานขนาดใหญ่ เนื่องจากแต่ละคลาสผลิตภัณฑ์ต้องมีคลาสย่อยของผู้สร้างของตัวเอง
มาสรุปกัน
คุณได้เรียนรู้เกี่ยวกับรูปแบบวิธีการของโรงงานและได้เห็นการใช้งานที่เป็นไปได้อย่างหนึ่ง รูปแบบนี้มักใช้ในไลบรารีต่างๆ ที่มีวัตถุสำหรับสร้างวัตถุอื่นๆ
ใช้รูปแบบเมธอดโรงงานเมื่อคุณต้องการเพิ่มอ็อบเจกต์ใหม่ของคลาสย่อยของคลาสที่มีอยู่เพื่อให้โต้ตอบกับตรรกะทางธุรกิจหลักของคุณ และไม่ทำให้โค้ดของคุณขยายใหญ่ขึ้นเนื่องจากบริบทที่แตกต่างกัน
GO TO FULL VERSION