مرحبا يا صديق! اليوم سنواصل دراسة أنماط التصميم معك. في هذه المحاضرة سنتحدث عن المصنع. سنناقش معك ما هي المشكلة التي تم حلها باستخدام هذا القالب، وننظر إلى مثال لكيفية مساعدة المصنع في فتح مقهى. وسأعطيك أيضًا 5 خطوات بسيطة لإنشاء مصنع. لكي تكون على نفس الصفحة مع الجميع وتتمكن من فهم الجوهر بسهولة، يجب أن تكون على دراية بالمواضيع التالية:
- الميراث في جاوة
- تضييق وتوسيع أنواع المراجع في جافا
- التفاعل بين الفئات والأشياء المختلفة
ما هو المصنع؟
يتيح لك نمط تصميم المصنع التحكم في إنشاء الكائنات. إن عملية إنشاء كائن جديد ليست بهذه البساطة، ولكنها ليست معقدة للغاية أيضًا. نعلم جميعًا أنه لإنشاء كائن جديد يجب علينا استخدام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 CatType {
LION,
TIGER,
BARSIK
}
الخطوة 3. أنت تبني مصنعك. يمكنك تسميتها MyClassFactory
، الكود أدناه:
class CatFactory {}
الخطوة 4. قم بإنشاء طريقة في المصنع الخاص بك createMyClass
تأخذ المتغير - enum
MyClassType
. الرمز أدناه:
class CatFactory {
public Cat createCat(CatType type) {
}
}
الخطوة 5. تكتب كتلة في نص الطريقة switch-case
التي تتكرر بها جميع قيم التعداد وتقوم بإنشاء مثيل للفئة المقابلة للقيمة 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