CodeGym /مدونة جافا /Random-AR /أنماط التصميم: مصنع تجريدي
John Squirrels
مستوى
San Francisco

أنماط التصميم: مصنع تجريدي

نشرت في المجموعة
أهلاً! سنواصل اليوم دراسة أنماط التصميم وسنناقش نمط المصنع المجرد . أنماط التصميم: المصنع التجريدي - 1وهذا ما سنغطيه في الدرس:
  • سنناقش ما هو المصنع المجرد وما هي المشكلة التي يحلها هذا النمط
  • سنقوم بإنشاء الهيكل العظمي لتطبيق متعدد المنصات لطلب القهوة من خلال واجهة المستخدم
  • سوف ندرس تعليمات حول كيفية استخدام هذا النمط، بما في ذلك النظر إلى الرسم التخطيطي والتعليمات البرمجية
  • وكمكافأة، يتضمن هذا الدرس بيضة عيد الفصح المخفية التي ستساعدك على تعلم كيفية استخدام 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) حقوله عبارة عن عناصر واجهة مجردة تمت تهيئتها بالقيم الضرورية في المُنشئ باستخدام مصنع مجردة.
  • فئة التطبيق داخل هذه الفئة، نقوم بإنشاء نموذج، ونمرر تنفيذ المصنع المطلوب إلى مُنشئه.
والنتيجة هي أننا قمنا بتنفيذ نمط المصنع المجرد.

مصنع مجردة: كيفية الاستخدام

المصنع المجرد هو نمط تصميمي لإدارة إنشاء عائلات منتجات مختلفة دون الارتباط بفئات منتجات محددة. عند استخدام هذا النمط يجب عليك:
  1. تحديد عائلات المنتجات. لنفترض أن لدينا اثنين منهم:
    • SpecificProductA1,SpecificProductB1
    • SpecificProductA2,SpecificProductB2
  2. لكل منتج ضمن العائلة، حدد فئة مجردة (واجهة). وفي حالتنا لدينا:
    • ProductA
    • ProductB
  3. ضمن كل عائلة منتجات، يجب على كل منتج تنفيذ الواجهة المحددة في الخطوة 2.
  4. قم بإنشاء مصنع تجريدي، مع تحديد طرق إنشاء كل منتج في الخطوة 2. في حالتنا، ستكون هذه الطرق كما يلي:
    • ProductA createProductA();
    • ProductB createProductB();
  5. إنشاء تطبيقات مصنع مجردة بحيث يتحكم كل تطبيق في إنشاء منتجات عائلة واحدة. للقيام بذلك، داخل كل تطبيق للمصنع المجرد، تحتاج إلى تنفيذ جميع طرق الإنشاء حتى تتمكن من إنشاء وإرجاع تطبيقات منتج محددة.
يوضح مخطط UML التالي التعليمات الموضحة أعلاه: أنماط التصميم: مصنع تجريدي - 3الآن سنكتب التعليمات البرمجية وفقًا لهذه التعليمات:
// 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();
    }
}

العمل في المنزل

لتعزيز المادة، يمكنك القيام بأمرين:
  1. قم بتحسين تطبيق طلب القهوة بحيث يعمل أيضًا على نظام التشغيل Linux.
  2. قم بإنشاء مصنع تجريدي خاص بك لإنتاج الوحدات المشاركة في أي استراتيجية عسكرية. يمكن أن تكون هذه إما استراتيجية عسكرية تاريخية تتضمن جيوشًا حقيقية، أو استراتيجية خيالية مع العفاريت والتماثيل والجان. الشيء المهم هو اختيار شيء يثير اهتمامك. كن مبدعًا، واطبع الرسائل على وحدة التحكم، واستمتع بالتعرف على الأنماط!
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION