שלום חבר! היום נמשיך ללמוד איתך דפוסי עיצוב. בהרצאה זו נדבר על המפעל. נדון איתך באיזו בעיה נפתרת באמצעות תבנית זו, ונראה דוגמה כיצד מפעל עוזר לפתוח בית קפה. ואני גם אתן לך 5 שלבים פשוטים ליצירת מפעל. כדי להיות באותו עמוד עם כולם ולתפוס בקלות את המהות, עליך להכיר את הנושאים הבאים:
- ירושה בג'אווה
- צמצום והרחבת סוגי הפניות ב-Java
- אינטראקציה בין מחלקות ואובייקטים שונים
מה זה מפעל?
תבנית העיצוב של המפעל מאפשרת לך לשלוט ביצירת אובייקטים. תהליך יצירת אובייקט חדש הוא לא כל כך פשוט, אבל הוא גם לא מסובך מדי. כולנו יודעים שכדי ליצור אובייקט חדש עלינו להשתמש ב-new
. ואולי נראה שאין מה לנהל כאן, אבל זה לא כך. קשיים עשויים להתעורר כאשר לאפליקציה שלנו יש מחלקה מסוימת שיש לה צאצאים רבים, ויש צורך ליצור מופע של מחלקה מסוימת בהתאם לתנאים מסוימים. מפעל הוא דפוס עיצובי שעוזר לפתור את הבעיה של יצירת אובייקטים שונים בהתאם לתנאים מסוימים. מופשט, לא? יותר ספציפיות ובהירות יופיעו כאשר נסתכל על הדוגמה למטה.
אנו יוצרים סוגים שונים של קפה
נניח שאנחנו רוצים להפוך בית קפה לאוטומטי. עלינו ללמוד כיצד להכין סוגים שונים של קפה. לשם כך, באפליקציה שלנו ניצור מחלקת קפה ונגזרותיו: אמריקנו, קפוצ'ינו, אספרסו, לאטה - אותם סוגי קפה שנכין. נתחיל עם שיעור הקפה הכללי: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 {}
הלקוחות שלנו יזמינו סוג של קפה, ואת המידע הזה צריך להעביר לתוכנית. ניתן לעשות זאת בדרכים שונות, למשל באמצעות String
. אבל זה הכי מתאים למטרות אלה enum
. בואו ניצור enum
ונגדיר בו את סוגי הקפה עליהם אנו מקבלים הזמנות:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
מעולה, עכשיו בואו נכתוב את הקוד לבית הקפה שלנו:
public class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappucсino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
ניתן לחלק את השיטה orderCoffee
לשני מרכיבים:
- יצירת מופע קפה ספציפי בבלוק
switch-case
. זה המקום שבו מה שהמפעל עושה הוא יצירת סוג מסוים בהתאם לתנאים. - ההכנה עצמה היא טחינה, בישול ומזיגה לספל.
- אלגוריתם ההכנה עצמו (טחינה, בישול ומזיגה לכוס) יישאר ללא שינוי (לפחות אנו מקווים שכן).
- אבל טווח הקפה עשוי להשתנות. אולי נתחיל להכין מוקה.. מוקה.. מוקה... אלוהים יברך אותו, סוג חדש של קפה.
switch-case
. ייתכן גם שבבית הקפה שלנו השיטה orderCoffee
לא תהיה המקום היחיד בו אנו יוצרים סוגי קפה שונים. לפיכך, יהיה צורך לבצע שינויים במספר מקומות. אתה בטח כבר מבין למה אני מתכוון. אנחנו צריכים לעשות מחדש. העבר את הבלוק האחראי ליצירת קפה למחלקה נפרדת משתי סיבות:
- נוכל לעשות שימוש חוזר בהיגיון של יצירת קפה במקומות אחרים.
- אם הטווח ישתנה, לא נצטרך לערוך את הקוד בכל מקום שבו ייעשה שימוש ביצירת קפה. זה יספיק לשנות את הקוד במקום אחד בלבד.
אנחנו מנסרים את המפעל הראשון שלנו
לשם כך, בואו ניצור מחלקה חדשה שתהיה אחראית רק ליצירת המקרים הדרושים של שיעורי קפה: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 Cappucino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
מזל טוב! זה עתה יישמנו את תבנית העיצוב של המפעל בצורה הפשוטה ביותר שלו. למרות שהכל יכול להיות אפילו יותר פשוט אם השיטה הייתה createCoffee
סטטית. אבל אז נאבד שתי אפשרויות:
- קבל בירושה
SimpleCoffeeFactory
ועקוף את ה-createCoffee
. - יישם את היישום הנדרש במפעל בכיתות שלנו.
הכנסת מפעל לבית קפה
בואו נשכתב מחדש את שיעור בית הקפה שלנו באמצעות מפעל: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;
}
}
גדול. כעת ננסה לתאר בצורה סכמטית ותמציתית את המבנה של דפוס עיצוב המפעל.
5 שלבים לפתיחת מפעל משלך
שלב 1. בתוכנית שלך יש לך מחלקה עם מספר צאצאים, כמו בתמונה למטה: שלב 2. אתה יוצר מחלקהenum
שבה אתה מגדיר משתנה enum עבור כל מחלקה צאצא:
enum CatType {
LION,
TIGER,
BARSIK
}
שלב 3. אתה בונה את המפעל שלך. אתה קורא לזה MyClassFactory
, הקוד נמצא למטה:
class CatFactory {}
שלב 4. אתה יוצר שיטה במפעל שלך createMyClass
שלוקחת את המשתנה - enum
MyClassType
. קוד למטה:
class CatFactory {
public Cat createCat(CatType type) {
}
}
שלב 5. אתה כותב בלוק בגוף השיטה switch-case
שבה אתה חוזר על כל ערכי ה-enum ויוצר מופע של המחלקה המתאים לערך enum
:
class CatFactory {
public Cat createCat(CatType type) {
Cat cat = null;
switch (type) {
case LION:
cat = new Barsik();
break;
case TIGER:
cat = new Tiger();
break;
case BARSIK:
cat = new Lion();
break;
}
return cat;
}
}
כמו בוס.
GO TO FULL VERSION