JavaRush /مدونة جافا /Random-AR /أنماط التصميم: AbstractFactory

أنماط التصميم: AbstractFactory

نشرت في المجموعة
مرحبًا! واليوم سنواصل دراسة أنماط التصميم والحديث عن المصنع التجريدي . أنماط التصميم: AbstractFactory - 1ماذا سنفعل خلال المحاضرة:
  • دعونا نناقش ما هو المصنع المجرد وما هي المشكلة التي يحلها هذا النمط؛
  • سنقوم بإنشاء إطار عمل لتطبيق متعدد المنصات لطلب القهوة باستخدام واجهة مستخدم؛
  • دعونا ندرس تعليمات استخدام هذا النمط مع رسم تخطيطي وكود؛
  • على سبيل المكافأة، هناك بيضة عيد الفصح مخبأة في المحاضرة، والتي بفضلها ستتعلم تحديد اسم نظام التشغيل باستخدام Java، واعتمادًا على النتيجة، قم بتنفيذ هذا الإجراء أو ذاك.
لفهم هذا النمط بشكل كامل، يجب أن يكون لديك فهم جيد للمواضيع التالية:
  • الميراث في جاوة.
  • فئات وأساليب مجردة في جافا.

ما هي المشاكل التي يحلها نمط المصنع المجرد؟

يساعدنا المصنع المجرد، مثل جميع أنماط المصنع، على تنظيم إنشاء كائنات جديدة بشكل صحيح. بمساعدتها، نقوم بإدارة "إصدار" عائلات مختلفة من الكائنات المترابطة. عائلات مختلفة من الأشياء المترابطة...ما هي؟ لا تقلق: في الممارسة العملية، كل شيء أبسط مما قد يبدو. لنبدأ بما قد يكون عائلة من الكائنات ذات الصلة؟ لنفترض أننا نعمل معك على تطوير استراتيجية، وفيها عدة وحدات قتالية:
  • مشاة؛
  • سلاح الفرسان؛
  • الرماة.
ترتبط هذه الأنواع من الوحدات القتالية ببعضها البعض، لأنها تخدم في نفس الجيش. يمكننا القول أن الفئات المذكورة أعلاه هي مجموعة من الكائنات المترابطة. لقد تم حل هذا الأمر. لكن نمط المصنع المجرد يستخدم لتنظيم إنشاء عائلات مختلفة من الكائنات المترابطة. لا يوجد شيء معقد هنا أيضًا. دعونا نواصل المثال مع الاستراتيجية. عادة ما يكون لديهم عدة جوانب متعارضة مختلفة. قد تختلف الوحدات القتالية التابعة للجانبين بشكل كبير في المظهر. جنود المشاة والفرسان والرماة في الجيش الروماني ليسوا مثل جنود المشاة والفرسان ورماة الفايكنج. في إطار الإستراتيجية، جنود الجيوش المختلفة هم عائلات مختلفة من الأشياء المترابطة. سيكون من المضحك أن يتجول جندي يرتدي الزي الفرنسي من زمن نابليون، ويحمل بندقيته على أهبة الاستعداد، بين المشاة الرومانيين، بسبب خطأ مبرمج. لحل مثل هذه المشكلة، هناك حاجة إلى نمط تصميم المصنع المجرد. لا، ليست مشاكل السفر عبر الزمن محرجة، ولكن إنشاء مجموعات مختلفة من الأشياء المترابطة. يوفر المصنع المجرد واجهة لإنشاء كافة المنتجات الموجودة (الكائنات العائلية). عادة ما يكون للمصنع المجرد تطبيقات متعددة. كل واحد منهم مسؤول عن إنشاء منتجات لأحد الأشكال. كجزء من الإستراتيجية، سيكون لدينا مصنع تجريدي يقوم بإنشاء مشاة مجردة ورماة وسلاح فرسان، بالإضافة إلى تطبيقات هذا المصنع. مصنع يصنع جنود الفيلق الروماني، وعلى سبيل المثال، مصنع يصنع المحاربين القرطاجيين. التجريد هو المبدأ الأكثر أهمية في هذا النمط. يعمل عملاء المصنع معها ومع المنتجات فقط من خلال واجهات مجردة. لذلك، لا يتعين علينا أن نفكر في نوع المحاربين الذين نقوم بإنشائهم حاليًا، ولكن نقل هذه المسؤولية إلى بعض التنفيذ المحدد للمصنع المجرد.

نواصل أتمتة المقهى

في المحاضرة الأخيرة، قمنا بدراسة نمط طريقة المصنع، والذي تمكنا من خلاله من توسيع أعمال القهوة وفتح العديد من نقاط بيع القهوة الجديدة. واليوم سنواصل عملنا لتحديث أعمالنا. باستخدام نمط المصنع المجرد، سنضع الأساس لتطبيق سطح مكتب جديد لطلب القهوة عبر الإنترنت. عندما نكتب تطبيقًا لسطح المكتب، يجب أن نفكر دائمًا في الأنظمة الأساسية المشتركة. يجب أن يعمل تطبيقنا على كل من نظامي التشغيل macOS وWindows (حرق المعلومات: سيتم ترك Linux لك كواجب منزلي). كيف سيبدو طلبنا؟ بسيط جدًا: سيكون هذا نموذجًا يتكون من حقل نص وحقل تحديد وزر. إذا كانت لديك خبرة في استخدام أنظمة تشغيل مختلفة، فمن المؤكد أنك لاحظت أن الأزرار في Windows يتم عرضها بشكل مختلف عنها في Mac. مثل كل شيء آخر... لذا، دعونا نبدأ. في دور عائلات المنتجات، كما قد تكون فهمت بالفعل، سيكون لدينا عناصر واجهة رسومية:
  • أزرار؛
  • حقول النص؛
  • الحقول للاختيار.
تنصل. داخل كل واجهة يمكننا تحديد طرق مثل onClickأو . أولئك. الأساليب التي ستسمح لنا بالتعامل مع الأحداث المختلفة (النقر فوق زر، وإدخال النص، وتحديد قيمة في مربع التحديد). تم حذف كل هذا عمدًا حتى لا يتم التحميل الزائد على المثال ولجعله أكثر وضوحًا لدراسة نمط المصنع. دعونا نحدد الواجهات المجردة لمنتجاتنا: onValueChangedonInputChanged

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 gui factory 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 gui factory 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 OrderCoffeeForm {
    private final TextField customerNameTextField;
    private final Select coffeTypeSelect;
    private final Button orderButton;

    public OrderCoffeeForm(GUIFactory factory) {
        System.out.println("Creating order coffee form");
        customerNameTextField = factory.createTextField();
        coffeTypeSelect = factory.createSelect();
        orderButton = factory.createButton();
    }
}
يتم تمرير مصنع مجردة إلى منشئ النموذج، الذي يقوم بإنشاء عناصر الواجهة. سنقوم بتمرير تنفيذ المصنع المطلوب إلى المنشئ حتى نتمكن من إنشاء عناصر واجهة لنظام تشغيل معين.

public class Application {
    private OrderCoffeeForm orderCoffeeForm;

    public void drawOrderCoffeeForm() {
        // Определим Name операционной системы, получив meaning системной проперти через System.getProperty
        String osName = System.getProperty("os.name").toLowerCase();
        GUIFactory guiFactory;

        if (osName.startsWith("win")) { // Для windows
            guiFactory = new WindowsGUIFactory();
        } else if (osName.startsWith("mac")) { // Для mac
            guiFactory = new MacGUIFactory();
        } else {
            System.out.println("Unknown OS, can't draw form :( ");
            return;
        }
        orderCoffeeForm = new OrderCoffeeForm(guiFactory);
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.drawOrderCoffeeForm();
    }
}
إذا قمنا بتشغيل التطبيق على نظام التشغيل Windows، فسنحصل على الإخراج التالي:

Creating gui factory for Windows OS
Creating order coffee form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
على نظام Mac سيكون الإخراج كما يلي:

Creating gui factory for macOS
Creating order coffee form
Creating TextField for macOS
Creating Select for macOS
Creating Button for macOS
على لينكس:

Unknown OS, can't draw form :( 
حسنًا، أنا وأنت نخلص إلى النتيجة التالية. لقد كتبنا إطارًا لتطبيق واجهة المستخدم الرسومية الذي ينشئ بالضبط عناصر الواجهة المناسبة لنظام تشغيل معين. دعونا نكرر بإيجاز ما أنشأناه:
  • عائلة المنتج: حقل الإدخال، حقل الاختيار والزر.
  • تطبيقات مختلفة لمجموعة المنتجات هذه لنظامي التشغيل Windows وmacOS.
  • مصنع تجريدي، حددنا من خلاله واجهة إنشاء منتجاتنا.
  • تطبيقان لمصنعنا، كل منهما مسؤول عن إنشاء مجموعة محددة من المنتجات.
  • نموذج، فئة Java حقولها عبارة عن عناصر واجهة مجردة تتم تهيئتها في المُنشئ بالقيم المطلوبة باستخدام مصنع مجردة.
  • فئة التطبيق. بداخله، نقوم بإنشاء نموذج ننقل من خلاله التنفيذ المطلوب لمصنعنا إلى المنشئ.
الإجمالي: لقد قمنا بتنفيذ نمط المصنع المجرد.

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

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

    // Определим общие интерфейсы продуктов
    public interface ProductA {}
    public interface ProductB {}

    // Создадим различные реализации (семейства) наших продуктов
    public class SpecificProductA1 implements ProductA {}
    public class SpecificProductB1 implements ProductB {}

    public class SpecificProductA2 implements ProductA {}
    public class SpecificProductB2 implements ProductB {}

    // Создадим абстрактную фабрику
    public interface AbstractFactory {
        ProductA createProductA();
        ProductB createProductB();
    }

    // Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
    public class SpecificFactory1 implements AbstractFactory {

        @Override
        public ProductA createProductA() {
            return new SpecificProductA1();
        }

        @Override
        public ProductB createProductB() {
            return new SpecificProductB1();
        }
    }

    // Создадим реализацию абстрактной фабрики для создания продуктов семейства 1
    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