أهلاً! سنواصل اليوم دراسة أنماط التصميم وسنناقش نمط المصنع المجرد . وهذا ما سنغطيه في الدرس:
- سنناقش ما هو المصنع المجرد وما هي المشكلة التي يحلها هذا النمط
- سنقوم بإنشاء الهيكل العظمي لتطبيق متعدد المنصات لطلب القهوة من خلال واجهة المستخدم
- سوف ندرس تعليمات حول كيفية استخدام هذا النمط، بما في ذلك النظر إلى الرسم التخطيطي والتعليمات البرمجية
- وكمكافأة، يتضمن هذا الدرس بيضة عيد الفصح المخفية التي ستساعدك على تعلم كيفية استخدام Java لتحديد اسم نظام التشغيل، واعتمادًا على النتيجة، لتنفيذ إجراء آخر أو آخر.
- الميراث في جاوة
- فئات وأساليب مجردة في جافا
ما هي المشاكل التي يحلها المصنع المجرد؟
يساعدنا المصنع المجرد، مثل جميع أنماط المصنع، على ضمان إنشاء الكائنات الجديدة بشكل صحيح. نستخدمها لإدارة "إنتاج" عائلات مختلفة من الكائنات المترابطة. عائلات مختلفة من الأشياء المترابطة... ماذا يعني ذلك؟ لا تقلق: في الممارسة العملية، كل شيء أبسط مما قد يبدو. في البداية، ماذا يمكن أن تكون عائلة الأشياء المترابطة؟ لنفترض أننا نعمل على تطوير استراتيجية عسكرية تتضمن عدة أنواع من الوحدات:- مشاة
- سلاح الفرسان
- الرماة
دعونا نواصل أتمتة المقهى الخاص بنا
في الدرس الأخير درسنا نمط طريقة المصنع. استخدمناها لتوسيع أعمالنا في مجال القهوة وفتح عدة مواقع جديدة. واليوم سنواصل تحديث أعمالنا. باستخدام نمط المصنع المجرد، سنضع الأساس لتطبيق سطح مكتب جديد لطلب القهوة عبر الإنترنت. عند كتابة تطبيق سطح المكتب، يجب أن نفكر دائمًا في الدعم عبر الأنظمة الأساسية. يجب أن يعمل تطبيقنا على كل من نظامي التشغيل macOS وWindows (حرق المعلومات: دعم Linux متروك لك لتنفيذه كواجب منزلي). كيف سيبدو طلبنا؟ بسيط جدًا: سيكون نموذجًا يتكون من حقل نص وحقل اختيار وزر. إذا كانت لديك خبرة في استخدام أنظمة تشغيل مختلفة، فمن المؤكد أنك لاحظت أن الأزرار الموجودة على Windows يتم عرضها بشكل مختلف عن تلك الموجودة على جهاز Mac. كما هو الحال مع كل شيء آخر... حسنًا، فلنبدأ. وكما أدركت بالفعل، ستتكون مجموعات المنتجات من عناصر الواجهة الرسومية:- أزرار
- حقول النص
- حقول الاختيار
onClick
أو onValueChanged
أو onInputChanged
. بمعنى آخر، يمكننا تحديد الطرق التي تسمح لنا بالتعامل مع الأحداث المختلفة (الضغط على زر، إدخال النص، تحديد قيمة في مربع التحديد). كل هذا تم حذفه عمداً هنا حتى لا نثقل على المثال ولنجعله أكثر وضوحاً ونحن ندرس نمط المصنع. دعونا نحدد الواجهات المجردة لمنتجاتنا:
public interface Button {}
public interface Select {}
public interface TextField {}
لكل نظام تشغيل، يجب علينا إنشاء عناصر واجهة بأسلوب نظام التشغيل. سنقوم بكتابة التعليمات البرمجية لنظامي التشغيل Windows وMacOS. لنقم بإنشاء تطبيقات لنظام التشغيل Windows:
public class WindowsButton implements Button {
}
public class WindowsSelect implements Select {
}
public class WindowsTextField implements TextField {
}
الآن نفعل الشيء نفسه بالنسبة لنظام التشغيل MacOS:
public class MacButton implements Button {
}
public class MacSelect implements Select {
}
public class MacTextField implements TextField {
}
ممتاز. يمكننا الآن الانتقال إلى مصنعنا التجريدي، والذي سيقوم بإنشاء جميع أنواع المنتجات التجريدية المتاحة:
public interface GUIFactory {
Button createButton();
TextField createTextField();
Select createSelect();
}
رائع. كما ترون، لم نقم بأي شيء معقد بعد. كل ما يلي هو أيضا بسيط. ومن خلال القياس مع المنتجات، نقوم بإنشاء تطبيقات المصنع المختلفة لكل نظام تشغيل. لنبدأ مع ويندوز:
public class WindowsGUIFactory implements GUIFactory {
public WindowsGUIFactory() {
System.out.println("Creating GUIFactory for Windows OS");
}
public Button createButton() {
System.out.println("Creating Button for Windows OS");
return new WindowsButton();
}
public TextField createTextField() {
System.out.println("Creating TextField for Windows OS");
return new WindowsTextField();
}
public Select createSelect() {
System.out.println("Creating Select for Windows OS");
return new WindowsSelect();
}
}
لقد أضفنا بعض مخرجات وحدة التحكم داخل الأساليب والمنشئ لتوضيح ما يحدث بشكل أكبر. الآن لنظام التشغيل MacOS:
public class MacGUIFactory implements GUIFactory {
public MacGUIFactory() {
System.out.println("Creating GUIFactory for macOS");
}
@Override
public Button createButton() {
System.out.println("Creating Button for macOS");
return new MacButton();
}
@Override
public TextField createTextField() {
System.out.println("Creating TextField for macOS");
return new MacTextField();
}
@Override
public Select createSelect() {
System.out.println("Creating Select for macOS");
return new MacSelect();
}
}
لاحظ أن كل توقيع أسلوب يشير إلى أن الأسلوب يُرجع نوعًا مجردًا. لكن داخل الأساليب، نقوم بإنشاء تطبيقات محددة للمنتجات. هذا هو المكان الوحيد الذي نتحكم فيه في إنشاء حالات محددة. الآن حان الوقت لكتابة فصل دراسي للنموذج. هذه فئة Java حقولها عبارة عن عناصر واجهة:
public class CoffeeOrderForm {
private final TextField customerNameTextField;
private final Select coffeeTypeSelect;
private final Button orderButton;
public CoffeeOrderForm(GUIFactory factory) {
System.out.println("Creating coffee order form");
customerNameTextField = factory.createTextField();
coffeeTypeSelect = factory.createSelect();
orderButton = factory.createButton();
}
}
يتم تمرير مصنع مجردة يقوم بإنشاء عناصر الواجهة إلى منشئ النموذج. سنقوم بتمرير تنفيذ المصنع اللازم إلى المُنشئ لإنشاء عناصر واجهة لنظام تشغيل معين.
public class Application {
private CoffeeOrderForm coffeeOrderForm;
public void drawCoffeeOrderForm() {
// Determine the name of the operating system through System.getProperty()
String osName = System.getProperty("os.name").toLowerCase();
GUIFactory guiFactory;
if (osName.startsWith("win")) { // For Windows
guiFactory = new WindowsGUIFactory();
} else if (osName.startsWith("mac")) { // For Mac
guiFactory = new MacGUIFactory();
} else {
System.out.println("Unknown OS. Unable to draw form :(");
return;
}
coffeeOrderForm = new CoffeeOrderForm(guiFactory);
}
public static void main(String[] args) {
Application application = new Application();
application.drawCoffeeOrderForm();
}
}
إذا قمنا بتشغيل التطبيق على نظام التشغيل Windows، فسنحصل على الإخراج التالي:
Creating GUIFactory for Windows OS
Creating coffee order form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
على نظام Mac، سيكون الإخراج كما يلي:
Creating GUIFactory for macOS
Creating coffee order form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
على لينكس:
Unknown OS. Unable to draw form :(
والآن نلخص. لقد كتبنا الهيكل العظمي لتطبيق قائم على واجهة المستخدم الرسومية حيث يتم إنشاء عناصر الواجهة خصيصًا لنظام التشغيل ذي الصلة. سنكرر بإيجاز ما قمنا بإنشائه:
- عائلة منتجات تتكون من حقل إدخال وحقل اختيار وزر.
- تطبيقات مختلفة لعائلة المنتجات لنظامي التشغيل Windows وmacOS.
- مصنع مجرد يحدد واجهة لإنشاء منتجاتنا.
- تطبيقان لمصنعنا، كل منهما مسؤول عن إنشاء مجموعة محددة من المنتجات.
- نموذج (فئة Java) حقوله عبارة عن عناصر واجهة مجردة تمت تهيئتها بالقيم الضرورية في المُنشئ باستخدام مصنع مجردة.
- فئة التطبيق داخل هذه الفئة، نقوم بإنشاء نموذج، ونمرر تنفيذ المصنع المطلوب إلى مُنشئه.
مصنع مجردة: كيفية الاستخدام
المصنع المجرد هو نمط تصميمي لإدارة إنشاء عائلات منتجات مختلفة دون الارتباط بفئات منتجات محددة. عند استخدام هذا النمط يجب عليك:- تحديد عائلات المنتجات. لنفترض أن لدينا اثنين منهم:
SpecificProductA1
,SpecificProductB1
SpecificProductA2
,SpecificProductB2
- لكل منتج ضمن العائلة، حدد فئة مجردة (واجهة). وفي حالتنا لدينا:
ProductA
ProductB
- ضمن كل عائلة منتجات، يجب على كل منتج تنفيذ الواجهة المحددة في الخطوة 2.
- قم بإنشاء مصنع تجريدي، مع تحديد طرق إنشاء كل منتج في الخطوة 2. في حالتنا، ستكون هذه الطرق كما يلي:
ProductA createProductA();
ProductB createProductB();
- إنشاء تطبيقات مصنع مجردة بحيث يتحكم كل تطبيق في إنشاء منتجات عائلة واحدة. للقيام بذلك، داخل كل تطبيق للمصنع المجرد، تحتاج إلى تنفيذ جميع طرق الإنشاء حتى تتمكن من إنشاء وإرجاع تطبيقات منتج محددة.
// Define common product interfaces
public interface ProductA {}
public interface ProductB {}
// Create various implementations (families) of our products
public class SpecificProductA1 implements ProductA {}
public class SpecificProductB1 implements ProductB {}
public class SpecificProductA2 implements ProductA {}
public class SpecificProductB2 implements ProductB {}
// Create an abstract factory
public interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
// Implement the abstract factory in order to create products in family 1
public class SpecificFactory1 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new SpecificProductA1();
}
@Override
public ProductB createProductB() {
return new SpecificProductB1();
}
}
// Implement the abstract factory in order to create products in family 2
public class SpecificFactory2 implements AbstractFactory {
@Override
public ProductA createProductA() {
return new SpecificProductA2();
}
@Override
public ProductB createProductB() {
return new SpecificProductB2();
}
}
العمل في المنزل
لتعزيز المادة، يمكنك القيام بأمرين:- قم بتحسين تطبيق طلب القهوة بحيث يعمل أيضًا على نظام التشغيل Linux.
- قم بإنشاء مصنع تجريدي خاص بك لإنتاج الوحدات المشاركة في أي استراتيجية عسكرية. يمكن أن تكون هذه إما استراتيجية عسكرية تاريخية تتضمن جيوشًا حقيقية، أو استراتيجية خيالية مع العفاريت والتماثيل والجان. الشيء المهم هو اختيار شيء يثير اهتمامك. كن مبدعًا، واطبع الرسائل على وحدة التحكم، واستمتع بالتعرف على الأنماط!
GO TO FULL VERSION