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

أنماط التصميم: طريقة المصنع

نشرت في المجموعة
أهلاً! سنواصل اليوم دراسة أنماط التصميم وسنناقش نمط طريقة المصنع. أنماط التصميم: طريقة المصنع - 1 سوف تكتشف ما هو وما هي المهام التي يناسبها هذا النمط. سننظر في نمط التصميم هذا عمليًا وندرس هيكله. للتأكد من أن كل شيء واضح، عليك أن تفهم المواضيع التالية:
  1. الميراث في جاوة.
  2. الأساليب والطبقات المجردة في جافا

ما هي المشكلة التي تحلها طريقة المصنع؟

تحتوي جميع أنماط تصميم المصانع على نوعين من المشاركين: المبدعون (المصانع نفسها) والمنتجات (الأشياء التي أنشأتها المصانع). تخيل الموقف التالي: لدينا مصنع ينتج سيارات تحمل علامة CodeGym. يعرف كيفية إنشاء نماذج للسيارات بأنواع مختلفة من الأجسام:
  • سيارات السيدان
  • محطة العربات
  • كوبيه
لقد ازدهرت أعمالنا كثيرًا حتى أننا في أحد الأيام الجميلة استحوذنا على شركة تصنيع سيارات أخرى – OneAuto. كوننا أصحاب أعمال عقلانيين، لا نريد أن نخسر أيًا من عملاء OneAuto، ولذلك نواجه مهمة إعادة هيكلة الإنتاج حتى نتمكن من إنتاج:
  • سيارات السيدان CodeGym
  • عربات محطة CodeGym
  • كوبيهات CodeGym
  • سيارات السيدان OneAuto
  • عربات محطة OneAuto
  • وان أوتو كوبيه
كما ترون، بدلاً من مجموعة واحدة من المنتجات، أصبح لدينا الآن مجموعتان، ويختلفان في تفاصيل معينة. يُستخدم نمط تصميم طريقة المصنع عندما نحتاج إلى إنشاء مجموعات مختلفة من المنتجات، كل منها له بعض السمات المحددة. سننظر في المبدأ التوجيهي لهذا النمط عمليًا، وننتقل تدريجيًا من البسيط إلى المعقد، باستخدام مثال المقهى الخاص بنا، والذي أنشأناه في أحد الدروس السابقة .

قليلا عن نمط المصنع

اسمحوا لي أن أذكركم أننا قمنا سابقًا ببناء مقهى افتراضي صغير. بمساعدة مصنع بسيط، تعلمنا كيفية صنع أنواع مختلفة من القهوة. اليوم سوف نقوم بإعادة صياغة هذا المثال. دعونا نتذكر كيف كان شكل المقهى الخاص بنا بمصنعه البسيط. كان لدينا فئة القهوة:
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 {}
لقد أنشأنا التعداد لتسهيل تقديم الطلبات:
public enum CoffeeType {
    ESPRESSO,
    AMERICANO,
    CAFFE_LATTE,
    CAPPUCCINO
}
بدا مصنع القهوة نفسه كما يلي:
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 Cappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new CaffeLatte();
                break;
        }

        return coffee;
    }
}
وأخيرًا، أصبح المقهى نفسه بهذا الشكل:
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;
    }
}

تحديث مصنع بسيط

المقهى الخاص بنا يعمل بشكل جيد للغاية. لدرجة أننا نفكر في التوسع. نريد فتح بعض المواقع الجديدة. نحن جريئون ومغامرون، لذلك لن نفتح المقاهي المملة. نريد أن يكون لكل متجر لمسة خاصة. وفقًا لذلك، في البداية، سنفتح موقعين: أحدهما إيطالي والآخر أمريكي. لن تؤثر هذه التغييرات على التصميم الداخلي فحسب، بل ستؤثر أيضًا على المشروبات المقدمة:
  • في المقهى الإيطالي، سوف نستخدم ماركات القهوة الإيطالية حصريًا، مع طحن وتحميص خاص.
  • الموقع الأمريكي سيكون به كميات أكبر، وسنقدم المارشميلو مع كل طلب.
الشيء الوحيد الذي لم يتغير هو نموذج أعمالنا، الذي أثبت أنه ممتاز. من حيث الكود، هذا ما يحدث. كان لدينا 4 فئات تتوافق مع منتجاتنا:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
ولكن الآن سيكون لدينا 8:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}

public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
وبما أننا نريد الحفاظ على نموذج العمل الحالي، فإننا نريد orderCoffee(CoffeeType type)أن تخضع الطريقة لأقل عدد ممكن من التغييرات. نلقي نظرة على ذلك:
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;
}
ما هي الخيارات التي لدينا؟ حسنًا، نحن نعرف بالفعل كيفية كتابة مصنع، أليس كذلك؟ إن أبسط ما يتبادر إلى الذهن على الفور هو كتابة مصنعين متشابهين، ثم تمرير التنفيذ المطلوب إلى منشئ المقهى الخاص بنا. ومن خلال القيام بذلك، لن تتغير فئة المقهى. أولاً، نحتاج إلى إنشاء فئة مصنع جديدة، وجعلها ترث مصنعنا البسيط، ثم تجاوز الطريقة createCoffee(CoffeeType type). لنكتب مصانع صنع القهوة على الطريقة الإيطالية والقهوة على الطريقة الأمريكية:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {

    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}

public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }

}
يمكننا الآن تمرير تنفيذ المصنع المطلوب إلى CoffeeShop. دعونا نرى كيف سيبدو رمز طلب القهوة من المقاهي المختلفة. على سبيل المثال، الكابتشينو على الطريقة الإيطالية والطريقة الأمريكية:
public class Main {
    public static void main(String[] args) {
        /*
            Order an Italian-style cappuccino:
            1. Create a factory for making Italian coffee
            2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
        CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
        italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);


         /*
            Order an American-style cappuccino
            1. Create a factory for making American coffee
            2. Create a new coffee shop, passing the American coffee factory to it through the constructor
            3. Order our coffee
         */
        SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
        CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
        americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
    }
}
لقد أنشأنا مقهيين مختلفين، وقمنا بتمرير المصنع المطلوب إلى كل منهما. من ناحية، لقد حققنا هدفنا، ولكن من ناحية أخرى... هذا لا يرضي رواد الأعمال بطريقة ما... فلنكتشف ما هو الخطأ. أولاً: كثرة المصانع. ماذا؟ الآن، لكل موقع جديد، من المفترض أن ننشئ مصنعًا خاصًا به، بالإضافة إلى ذلك، نتأكد من نقل المصنع ذي الصلة إلى المنشئ عند إنشاء مقهى؟ ثانيا، لا يزال مصنعا بسيطا. تم تحديثه قليلاً فقط. لكننا هنا لنتعلم نمطًا جديدًا. ثالثا، أليس من الممكن اتباع نهج مختلف؟ سيكون أمرا رائعا لو تمكنا من وضع جميع المسائل المتعلقة بإعداد القهوة في الفصل CoffeeShopمن خلال ربط عمليات إعداد القهوة وطلبات الخدمة، مع الحفاظ في الوقت نفسه على مرونة كافية لصنع أنماط مختلفة من القهوة. الجواب هو نعم، نستطيع. وهذا ما يسمى نمط تصميم طريقة المصنع.

من مصنع بسيط إلى طريقة المصنع

لحل المهمة بأكبر قدر ممكن من الكفاءة:
  1. نعيد createCoffee(CoffeeType type)الطريقة إلى CoffeeShopالفصل.
  2. سوف نجعل هذه الطريقة مجردة.
  3. CoffeeShopسوف يصبح الفصل نفسه مجردًا .
  4. CoffeeShopسيكون للفصل فصول الأطفال .
نعم يا صديقي. المقهى الإيطالي ليس أكثر من سليل الطبقة CoffeeShopالتي تطبق الطريقة createCoffee(CoffeeType type)وفقًا لأفضل تقاليد صانعي القهوة الإيطاليين. الآن، خطوة واحدة في كل مرة. الخطوة 1. قم بعمل Coffeeملخص للفصل. لدينا عائلتين كاملتين من المنتجات المختلفة. ومع ذلك، فإن القهوة الإيطالية والأمريكية لها سلف مشترك - الطبقة Coffee. سيكون من المناسب جعلها مجردة:
public abstract class Coffee {
    public void makeCoffee(){
        // Brew the coffee
    }
    public void pourIntoCup(){
        // Pour into a cup
    }
}
الخطوة 2. اصنع CoffeeShopالملخص باستخدام createCoffee(CoffeeType type)الطريقة المجردة
public abstract class CoffeeShop {

    public Coffee orderCoffee(CoffeeType type) {
        Coffee coffee = createCoffee(type);

        coffee.makeCoffee();
        coffee.pourIntoCup();

        System.out.println("Here's your coffee! Thanks! Come again!");
        return coffee;
    }

    protected abstract Coffee createCoffee(CoffeeType type);
}
الخطوة 3. قم بإنشاء مقهى إيطالي، وهو سليل المقهى المجرد. نقوم بتنفيذ createCoffee(CoffeeType type)الطريقة فيه مع مراعاة خصوصيات المستلمين الإيطاليين.
public class ItalianCoffeeShop extends CoffeeShop {

    @Override
    public Coffee createCoffee (CoffeeType type) {
        Coffee coffee = null;
        switch (type) {
            case AMERICANO:
                coffee = new ItalianStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new ItalianStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new ItalianStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new ItalianStyleCaffeLatte();
                break;
        }
        return coffee;
    }
}
الخطوة 4. نفعل الشيء نفسه بالنسبة للمقهى ذو الطراز الأمريكي
public class AmericanCoffeeShop extends CoffeeShop {
    @Override
    public Coffee createCoffee(CoffeeType type) {
        Coffee coffee = null;

        switch (type) {
            case AMERICANO:
                coffee = new AmericanStyleAmericano();
                break;
            case ESPRESSO:
                coffee = new AmericanStyleEspresso();
                break;
            case CAPPUCCINO:
                coffee = new AmericanStyleCappuccino();
                break;
            case CAFFE_LATTE:
                coffee = new AmericanStyleCaffeLatte();
                break;
        }

        return coffee;
    }
}
الخطوة 5. تحقق من شكل اللاتيه الأمريكي والإيطالي:
public class Main {
    public static void main(String[] args) {
        CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
        italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);

        CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
        americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
    }
}
تهانينا. لقد قمنا للتو بتنفيذ نمط تصميم طريقة المصنع باستخدام المقهى الخاص بنا كمثال.

المبدأ الكامن وراء أساليب المصنع

الآن دعونا نفكر بمزيد من التفصيل في ما حصلنا عليه. ويوضح الرسم البياني أدناه الفئات الناتجة. الكتل الخضراء هي فئات المنشئين، والكتل الزرقاء هي فئات المنتجات. أنماط التصميم: طريقة المصنع - 2ما هي الاستنتاجات التي يمكن أن نتوصل إليها؟
  1. جميع المنتجات هي تطبيقات للفئة المجردة Coffee.
  2. جميع المبدعين هم تطبيقات للفئة المجردة CoffeeShop.
  3. نرى تسلسلين هرميين متوازيين للفئات:
    • التسلسل الهرمي للمنتجات. نرى أحفادًا إيطاليين وأحفادًا أمريكيين
    • التسلسل الهرمي للمبدعين. نرى أحفادًا إيطاليين وأحفادًا أمريكيين
  4. لا تحتوي الفئة CoffeeShopالفائقة على معلومات حول المنتج المحدد ( Coffee) الذي سيتم إنشاؤه.
  5. تقوم الطبقة CoffeeShopالمتفوقة بتفويض إنشاء منتج معين إلى أحفادها.
  6. CoffeeShopيطبق كل سليل للفئة createCoffee()طريقة المصنع وفقًا لميزاته المحددة. بمعنى آخر، تقوم تطبيقات فئات المنتجين بإعداد منتجات محددة بناءً على تفاصيل فئة المنتجين.
أنت الآن جاهز لتعريف نمط طريقة المصنع . يحدد نمط طريقة المصنع واجهة لإنشاء كائن، ولكنه يسمح للفئات الفرعية بتحديد فئة الكائن الذي تم إنشاؤه. وبالتالي، تقوم طريقة المصنع بتفويض إنشاء مثيل إلى الفئات الفرعية. بشكل عام، تذكر التعريف ليس بنفس أهمية فهم كيفية عمل كل شيء.

هيكل طريقة المصنع

أنماط التصميم: طريقة المصنع - 3يوضح الرسم البياني أعلاه الهيكل العام لنمط طريقة المصنع. ما هو المهم هنا؟
  1. تطبق فئة Creator جميع الأساليب التي تتفاعل مع المنتجات، باستثناء طريقة المصنع.
  2. factoryMethod()يجب تنفيذ الطريقة المجردة من قبل جميع أحفاد Creatorالفصل.
  3. ConcreteCreatorيطبق الفصل الطريقة factoryMethod()التي تقوم بإنشاء المنتج مباشرة.
  4. هذه الفئة مسؤولة عن إنشاء منتجات محددة. هذا هو الفصل الدراسي الوحيد الذي لديه معلومات حول إنشاء هذه المنتجات.
  5. يجب أن تطبق جميع المنتجات واجهة مشتركة، أي يجب أن تكون متحدرة من فئة منتج مشتركة. يعد ذلك ضروريًا حتى تتمكن الفئات التي تستخدم المنتجات من العمل عليها كتجريدات، بدلاً من تطبيقات محددة.

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

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