สวัสดี! วันนี้เราจะมาศึกษารูปแบบการออกแบบกันต่อและพูดคุยเกี่ยวกับวิธีโรงงาน (FactoryMethod)
คุณจะพบว่าเทมเพลตนี้คืออะไรและเหมาะกับงานใดบ้าง เราจะดูรูปแบบการออกแบบนี้ในทางปฏิบัติและสำรวจโครงสร้างของมัน เพื่อให้สิ่งที่กล่าวมาทั้งหมดชัดเจน คุณต้องเข้าใจหัวข้อต่อไปนี้:
สามารถสรุปข้อสรุปอะไรได้บ้าง?
แผนภาพด้านบนแสดงโครงสร้างทั่วไปของรูปแบบวิธีการของโรงงาน มีอะไรสำคัญอีกที่นี่?
- การสืบทอดใน Java
- วิธีการเชิงนามธรรมและคลาสใน Java
วิธีการของโรงงานแก้ปัญหาอะไรได้บ้าง?
ในรูปแบบการออกแบบโรงงานทั้งหมด มีผู้เข้าร่วมสองกลุ่ม - ผู้สร้าง (โรงงานเอง) และผลิตภัณฑ์ (วัตถุที่สร้างขึ้นโดยโรงงาน) ลองนึกภาพสถานการณ์: เรามีโรงงานผลิตรถยนต์ภายใต้แบรนด์ AutoRush เธอสามารถสร้างโมเดลรถยนต์ที่มีตัวถังประเภทต่างๆ ได้:- รถเก๋ง
- รถสเตชั่นแวกอน
- รถเก๋ง
- รถซีดานออโต้รัช
- AutoRush สเตชั่นแวกอน
- คูเป้ออโต้รัช
- รถเก๋งวันออโต้
- OneAuto สเตชั่นแวกอน
- คูเป้ วันออโต้
เล็กน้อยเกี่ยวกับเทมเพลตโรงงาน
ฉันขอเตือนคุณ: เราสร้างร้านกาแฟเสมือนจริงขนาดเล็กกับคุณ ในนั้น เราได้เรียนรู้วิธีสร้างสรรค์กาแฟประเภทต่างๆ ด้วยความช่วยเหลือจากโรงงานที่เรียบง่าย วันนี้เราจะปรับแต่งตัวอย่างนี้ ลองนึกถึงร้านกาแฟที่มีโรงงานเรียบง่ายของเราดูสิ เรามีชั้นเรียนดื่มกาแฟ:public class Coffee {
public void grindCoffee(){
// перемалываем кофе
}
public void makeCoffee(){
// делаем кофе
}
public void pourIntoCup(){
// наливаем в чашку
}
}
และทายาทอีกหลายคนของเขา ซึ่งเป็นกาแฟประเภทเฉพาะที่โรงงานของเราสามารถผลิตได้:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
เพื่อความสะดวกในการรับคำสั่งซื้อ เราได้แนะนำการโอนเงิน:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
โรงงานผลิตกาแฟมีลักษณะดังนี้:
public class SimpleCoffeeFactory {
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappuccino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
และสุดท้าย ร้านกาแฟนั่นเอง:
public class CoffeeShop {
private final SimpleCoffeeFactory coffeeFactory;
public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
การปรับปรุงโรงงานที่เรียบง่ายให้ทันสมัย
ร้านกาแฟของเราไปได้ดี มากจนเราคิดที่จะขยาย เราต้องการเปิดจุดใหม่หลายจุด ในฐานะผู้ชายที่กล้าได้กล้าเสีย เราจะไม่ปั่นร้านกาแฟที่ซ้ำซากจำเจ ฉันอยากให้แต่ละคนมีความเป็นของตัวเอง ดังนั้นในการเริ่มต้นเราจะเปิดสองประเด็น: ในรูปแบบอิตาลีและอเมริกัน การเปลี่ยนแปลงจะไม่เพียงส่งผลต่อการตกแต่งภายในเท่านั้น แต่ยังรวมถึงเครื่องดื่มด้วย:- ในร้านกาแฟอิตาลี เราจะใช้กาแฟยี่ห้ออิตาลีโดยเฉพาะ ที่มีการบดและคั่วแบบพิเศษ
- ส่วนของอเมริกาจะใหญ่กว่านี้เล็กน้อย และเราจะเสิร์ฟมาร์ชเมลโลว์ละลาย - มาร์ชเมลโลว์ในแต่ละออเดอร์
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
และมันกลายเป็น 8:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}
public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
เนื่องจากเราต้องการคงรูปแบบธุรกิจปัจจุบันไว้ไม่เปลี่ยนแปลง เราจึงต้องการให้วิธีorderCoffee(CoffeeType type)
การได้รับการเปลี่ยนแปลงจำนวนน้อยที่สุด ลองมาดูกัน:
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
ตัวเลือกที่เรามีอะไรบ้าง? เรารู้วิธีเขียนโรงงานอยู่แล้วใช่ไหม? สิ่งที่ง่ายที่สุดที่อยู่ในใจทันทีคือเขียนโรงงานที่คล้ายกันสองแห่ง จากนั้นส่งต่อการใช้งานที่จำเป็นไปยังร้านกาแฟของเราในตัวสร้าง แล้วคลาสของร้านกาแฟก็จะไม่เปลี่ยนแปลง ขั้นแรก เราต้องสร้างคลาสโรงงานใหม่ สืบทอดจากโรงงานที่เรียบง่ายของเรา และแทนที่createCoffee (CoffeeType type)
. มาเขียนโรงงานสำหรับสร้างกาแฟสไตล์อิตาลีและอเมริกากัน:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
ตอนนี้เราสามารถส่งต่อการใช้งานโรงงานที่จำเป็นไปยัง CoffeeShop ได้แล้ว มาดูกันว่าโค้ดในการสั่งกาแฟจากร้านกาแฟต่างๆ จะเป็นอย่างไร ตัวอย่างเช่น คาปูชิโน่สไตล์อิตาลีและอเมริกัน:
public class Main {
public static void main(String[] args) {
/*
Закажем капучино в итальянском стиле:
1. Создадим фабрику для приготовления итальянского кофе
2. Создадим новую кофейню, передав ей в конструкторе фабрику итальянского кофе
3. Закажем наш кофе
*/
SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
/*
Закажем капучино в американском стиле
1. Создадим фабрику для приготовления американского кофе
2. Создадим новую кофейню, передав ей в конструкторе фабрику американского кофе
3. Закажем наш кофе
*/
SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
}
}
เราสร้างร้านกาแฟสองแห่งที่แตกต่างกัน โดยย้ายแต่ละร้านไปยังโรงงานที่ต้องการ ในอีกด้านหนึ่ง เราบรรลุเป้าหมายของเราแล้ว แต่ในทางกลับกัน... มีบางอย่างกำลังเกาจิตวิญญาณของผู้ประกอบการที่ไม่อาจระงับได้... เรามาดูกันว่ามีอะไรผิดปกติบ้าง ประการแรก ความอุดมสมบูรณ์ของโรงงาน เป็นไปได้หรือไม่ที่จะสร้างโรงงานของคุณเองทุกครั้งสำหรับจุดใหม่ และนอกจากนี้ ตรวจสอบให้แน่ใจว่าเมื่อสร้างร้านกาแฟ โรงงานที่ต้องการจะถูกโอนไปยังผู้สร้างหรือไม่ ประการที่สอง ยังคงเป็นโรงงานที่เรียบง่าย ปรับปรุงให้ทันสมัยเพียงเล็กน้อย เรายังคงศึกษารูปแบบใหม่ที่นี่ ประการที่สาม เป็นไปไม่ได้ที่จะทำอย่างอื่นอีกหรือ? คงจะดีไม่น้อยถ้าเราสามารถตอบคำถามทั้งหมดเกี่ยวกับการชงกาแฟในห้องเรียนCoffeeShop
เชื่อมโยงกระบวนการชงกาแฟและการให้บริการตามคำสั่งซื้อ แต่ในขณะเดียวกันก็รักษาความยืดหยุ่นเพียงพอในการทำกาแฟในสไตล์ที่แตกต่างกัน คำตอบคือใช่ คุณทำได้ สิ่งนี้เรียกว่ารูปแบบการออกแบบวิธีโรงงาน
จากโรงงานธรรมดาๆ สู่วิธีการแบบโรงงาน
เพื่อแก้ไขปัญหาอย่างมีประสิทธิภาพที่สุดเท่าที่จะเป็นไปได้ เรา:- ลองคืนวิธีการให้กับ
createCoffee(CoffeeType type)
ชั้นเรียนCoffeeShop
- มาทำให้วิธีนี้เป็นนามธรรมกัน
- ชั้นเรียน
CoffeeShop
จะกลายเป็นนามธรรม - ชั้น
CoffeeShop
จะมีทายาท
CoffeeShop
โดยใช้วิธีการcreateCoffee(CoffeeType type)
ตามประเพณีที่ดีที่สุดของบาริสต้าชาวอิตาลี ดังนั้นตามลำดับ ขั้นตอนที่ 1 มาทำให้ชั้นเรียนCoffee
เป็นนามธรรมกัน ตอนนี้เรามีผลิตภัณฑ์ที่แตกต่างกันสองตระกูล เครื่องดื่มกาแฟอิตาเลียนและอเมริกันยังคงมีบรรพบุรุษร่วมกัน: Coffee
. มันจะถูกต้องถ้าจะทำให้เป็นนามธรรม:
public abstract class Coffee {
public void makeCoffee(){
// делаем кофе
}
public void pourIntoCup(){
// наливаем в чашку
}
}
ขั้นตอนที่ 2 ทำให้เป็นCoffeeShop
นามธรรมด้วยวิธีนามธรรมcreateCoffee(CoffeeType type)
public abstract class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = createCoffee(type);
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
protected abstract Coffee createCoffee(CoffeeType type);
}
ขั้นตอนที่ 3. สร้างร้านกาแฟสไตล์อิตาลี ซึ่งเป็นคลาสที่สืบทอดมาจากร้านกาแฟแนวนามธรรม ในนั้นเราใช้วิธีการcreateCoffee(CoffeeType type)
โดยคำนึงถึงข้อมูลเฉพาะของอิตาลี
public class ItalianCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
ขั้นตอนที่ 4. มาทำแบบเดียวกันกับร้านกาแฟสไตล์อเมริกันกัน
public class AmericanCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
ขั้นตอนที่ 5. มาดูกันว่าการสั่งลาเต้สไตล์อเมริกันและอิตาลีจะเป็นอย่างไร:
public class Main {
public static void main(String[] args) {
CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
}
}
ยินดีด้วย. เราเพิ่งนำรูปแบบการออกแบบวิธีโรงงานมาใช้ในร้านกาแฟของเรา
วิธีการทำงานของโรงงาน
ทีนี้เรามาดูสิ่งที่เราได้รับกันดีกว่า แผนภาพด้านล่างแสดงคลาสผลลัพธ์ บล็อกสีเขียวคือคลาสผู้สร้าง บล็อกสีน้ำเงินคือคลาสผลิตภัณฑ์
- ผลิตภัณฑ์ทั้งหมดเป็นการใช้งานของคลาส
Coffee
นามธรรม CoffeeShop
ผู้สร้างทั้งหมดเป็นการใช้งานของคลาสนามธรรม- เราสังเกตลำดับชั้นของคลาสคู่ขนานสองลำดับชั้น:
- ลำดับชั้นของผลิตภัณฑ์ เราเห็นลูกหลานชาวอิตาลีและลูกหลานชาวอเมริกัน
- ลำดับชั้นของผู้สร้าง เราเห็นลูกหลานชาวอิตาลีและลูกหลานชาวอเมริกัน
- ซูเปอร์คลาส
CoffeeShop
ไม่มีข้อมูลเกี่ยวกับการใช้งานผลิตภัณฑ์เฉพาะ (Coffee
) ที่จะถูกสร้างขึ้น - ซูเปอร์คลาส
CoffeeShop
มอบหมายการสร้างผลิตภัณฑ์เฉพาะให้กับลูกหลาน - คลาสลูกหลานแต่ละคลาส
CoffeeShop
ใช้วิธีการแบบโรงงานcreateCoffee()
ตามลักษณะเฉพาะของมัน กล่าวอีกนัยหนึ่ง ภายในการใช้งานคลาสผู้สร้าง จะมีการตัดสินใจที่จะเตรียมผลิตภัณฑ์เฉพาะตามข้อมูลเฉพาะของคลาสผู้สร้าง
โครงสร้างวิธีการของโรงงาน

- คลาส Creator มีการนำไปใช้ของวิธีการทั้งหมดที่โต้ตอบกับผลิตภัณฑ์ ยกเว้นวิธีการจากโรงงาน
- วิธีการนามธรรม จะ ต้อง
factoryMethod()
ดำเนินการโดยผู้สืบทอดทั้งหมดของคลาสCreator
- ชั้นเรียน
ConcreteCreator
ใช้วิธีการfactoryMethod()
ที่สร้างผลิตภัณฑ์โดยตรง - คลาสนี้มีหน้าที่สร้างผลิตภัณฑ์เฉพาะ นี่เป็นคลาสเดียวที่มีข้อมูลเกี่ยวกับการสร้างผลิตภัณฑ์เหล่านี้
- ผลิตภัณฑ์ทั้งหมดต้องใช้อินเทอร์เฟซทั่วไป - ต้องสืบทอดจากประเภทผลิตภัณฑ์ทั่วไป นี่เป็นสิ่งจำเป็นเพื่อให้คลาสที่ใช้ผลิตภัณฑ์สามารถทำงานได้ในระดับนามธรรมมากกว่าการใช้งานที่เป็นรูปธรรม
GO TO FULL VERSION