مرحبا يا صديق! اليوم سنواصل دراسة أنماط التصميم. في هذا الدرس سنتحدث عن المصانع. سنناقش المشكلة التي يحلها هذا النمط وننظر إلى مثال لكيفية قيام المصنع بمساعدتك في فتح مقهى. بالإضافة إلى ذلك، سأعطيك 5 خطوات بسيطة لإنشاء مصنع. للتأكد من أننا جميعًا على نفس الموجة وأنك ستفهم هذا المفهوم بسرعة، يجب أن تكون على دراية بالمواضيع التالية:
- الميراث في جاوة
- تضييق وتوسيع أنواع المراجع في جافا
- التفاعل بين الفئات والأشياء المختلفة.
ما هو المصنع؟
يتيح لك نمط تصميم المصنع التحكم في إنشاء الكائنات. إن عملية إنشاء كائن جديد ليست بسيطة للغاية، ولكنها ليست معقدة للغاية. نعلم جميعًا أننا بحاجة إلىnew
المشغل لإنشاء كائن جديد. ربما يبدو أنه لا يوجد شيء يمكن السيطرة عليه هنا، لكن هذا ليس صحيحا. لنفترض أن تطبيقنا يحتوي على فئة معينة لها العديد من الأحفاد. قد تنشأ صعوبات عندما يكون من الضروري إنشاء مثيل لفئة معينة وفقًا لشروط معينة. المصنع هو نمط تصميمي يساعد في حل مشكلة إنشاء كائنات متنوعة وفقًا لشروط معينة . كيف يتم ذلك بالنسبة لمفهوم مجرد؟ سيصبح هذا أكثر وضوحًا وتحديدًا عندما ننظر إلى المثال أدناه.
دعونا نعد أنواعًا مختلفة من القهوة
لنفترض أننا نريد أتمتة مقهى. نحن بحاجة لتعليم برنامجنا كيفية صنع أنواع مختلفة من القهوة. للقيام بذلك، سنقوم بإنشاء فئة القهوة وبعض الفئات المشتقة لتمثيل أنواع القهوة التي سنقوم بتحضيرها: أمريكانو، كابتشينو، إسبرسو، ولاتيه. لنبدأ بفصل القهوة العام:public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
بعد ذلك، سنقوم بإنشاء فئاتها الفرعية:
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("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
ويمكن تقسيم الطريقة orderCoffee
إلى قسمين:
- إنشاء مثيل معين من القهوة في
switch
بيان. هذا هو المكان الذي يقوم فيه المصنع بما يفعله - إنشاء نوع معين حسب الظروف. - التحضير - هذا هو الطحن والتخمير والصب في كوب.
- ستبقى خطوات التحضير نفسها (الطحن والتخمير والصب في الكوب) دون تغيير (على الأقل نعول على ذلك).
- لكن تشكيلة القهوة قد تتغير. ربما سنبدأ في صنع الموكا... فرابو... موكاتشي... أيًا كان، نوع جديد من القهوة.
switch
. من الممكن أيضًا ألا تكون الطريقة في المقهى الخاص بنا 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("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
ممتاز. الآن سنقدم وصفًا موجزًا للهيكل العام لنمط تصميم المصنع.
5 خطوات لفتح مصنعك الخاص
الخطوة 1. يحتوي برنامجك على فئة ذات فروع متعددة، كما هو موضح في الرسم البياني أدناه: الخطوة 2. قم بإنشاءenum
حقل لكل فئة فرعية:
enum CatType {
LION,
TIGER,
FLUFFY
}
الخطوة 3. بناء المصنع الخاص بك. نسميها CatFactory
. إليك الكود:
class CatFactory {}
الخطوة 4. في المصنع الخاص بك، قم بإنشاء createCat
طريقة تأخذ وسيطة CatType
. إليك الكود:
class CatFactory {
public Cat createCat(CatType type) {
}
}
الخطوة 5. في نص الطريقة، اكتب switch
عبارة تعداد حقول التعداد وإنشاء مثيل للفئة التي تتوافق مع enum
القيمة التي تم تمريرها:
class CatFactory {
public Cat createCat(CatType type) {
Cat cat = null;
switch (type) {
case LION:
cat = new Fluffy();
break;
case TIGER:
cat = new Tiger();
break;
case FLUFFY:
cat = new Lion();
break;
}
return cat;
}
}
الآن يمكنك تشغيل مصنع مثل رئيسك. :)
GO TO FULL VERSION