CodeGym /وبلاگ جاوا /Random-FA /الگوهای طراحی: کارخانه انتزاعی
John Squirrels
مرحله
San Francisco

الگوهای طراحی: کارخانه انتزاعی

در گروه منتشر شد
سلام! امروز ما به مطالعه الگوهای طراحی ادامه خواهیم داد و در مورد الگوی کارخانه انتزاعی بحث خواهیم کرد . الگوهای طراحی: کارخانه انتزاعی - 1در اینجا چیزی است که ما در درس پوشش خواهیم داد:
  • ما بحث خواهیم کرد که یک کارخانه انتزاعی چیست و این الگو چه مشکلی را حل می کند
  • ما اسکلت یک برنامه چند پلتفرمی را برای سفارش قهوه از طریق رابط کاربری ایجاد خواهیم کرد
  • ما دستورالعمل‌هایی را در مورد نحوه استفاده از این الگو، از جمله مشاهده نمودار و کد، مطالعه خواهیم کرد
  • و به عنوان یک امتیاز، این درس شامل یک تخم مرغ عید پاک است که به شما کمک می کند یاد بگیرید چگونه از جاوا برای تعیین نام سیستم عامل استفاده کنید و بسته به نتیجه، یک عمل دیگر را انجام دهید.
برای درک کامل این الگو، باید در موضوعات زیر به خوبی تسلط داشته باشید:
  • وراثت در جاوا
  • کلاس ها و متدهای انتزاعی در جاوا

یک کارخانه انتزاعی چه مشکلاتی را حل می کند؟

یک کارخانه انتزاعی، مانند تمام الگوهای کارخانه، به ما کمک می کند تا اطمینان حاصل کنیم که اشیاء جدید به درستی ایجاد می شوند. ما از آن برای مدیریت "تولید" خانواده های مختلف اشیاء به هم پیوسته استفاده می کنیم. خانواده های مختلف اشیاء به هم پیوسته... یعنی چه؟ نگران نباشید: در عمل، همه چیز ساده تر از آن چیزی است که ممکن است به نظر برسد. برای شروع، یک خانواده از اشیاء به هم پیوسته چه می تواند باشد؟ فرض کنید ما در حال توسعه یک استراتژی نظامی هستیم که شامل چندین نوع واحد است:
  • پیاده نظام
  • سواره نظام
  • کمانداران
این نوع واحدها به هم مرتبط هستند، زیرا در یک ارتش خدمت می کنند. می توان گفت که دسته بندی های ذکر شده در بالا خانواده ای از اشیاء به هم پیوسته هستند. ما این را درک می کنیم. اما الگوی کارخانه انتزاعی برای ترتیب ایجاد خانواده های مختلف اشیاء به هم پیوسته استفاده می شود. اینجا هم هیچ چیز پیچیده ای نیست. بیایید با مثال استراتژی نظامی ادامه دهیم. به طور کلی، واحدهای نظامی متعلق به چندین گروه مختلف متخاصم هستند. بسته به اینکه طرف چه کسی باشد، واحدهای نظامی می توانند به طور قابل توجهی از نظر ظاهری متفاوت باشند. سربازان پیاده، سوارکاران و کمانداران ارتش روم با سربازان پیاده، سوارکاران و کمانداران وایکینگ یکی نیستند. در استراتژی نظامی، سربازان ارتش های مختلف خانواده های مختلفی از اشیاء به هم پیوسته هستند. خنده دار خواهد بود اگر اشتباه یک برنامه نویس باعث شود که سربازی با یونیفرم فرانسوی دوران ناپلئون که در حال آماده باش بود در حال راه رفتن در میان صفوف پیاده نظام رومی باشد. الگوی طراحی کارخانه انتزاعی دقیقاً برای حل این مشکل مورد نیاز است. نه، مشکل خجالتی نیست که می تواند از سفر در زمان به وجود بیاید، بلکه مشکل ایجاد گروه های مختلف اشیاء به هم پیوسته است. یک کارخانه انتزاعی یک رابط برای ایجاد تمام محصولات موجود (خانواده ای از اشیاء) فراهم می کند. یک کارخانه انتزاعی معمولاً چندین پیاده سازی دارد. هر کدام از آنها وظیفه ایجاد محصولات یکی از خانواده ها را بر عهده دارند. استراتژی نظامی ما شامل یک کارخانه انتزاعی است که سربازان پیاده، کمانداران و سواره نظام انتزاعی ایجاد می کند و همچنین اجرای این کارخانه. به عنوان مثال، کارخانه ای که لژیونرهای رومی ایجاد می کند و کارخانه ای که سربازان کارتاژی را ایجاد می کند. انتزاع مهمترین اصل راهنمای این الگو است. مشتریان کارخانه تنها از طریق رابط های انتزاعی با کارخانه و محصولات آن کار می کنند. در نتیجه، لازم نیست به این فکر کنید که کدام سربازها در حال حاضر ساخته می شوند. در عوض، این مسئولیت را به برخی از اجرای ملموس کارخانه انتزاعی واگذار می کنید.

بیایید به خودکارسازی کافی شاپ خود ادامه دهیم

در درس آخر الگوی روش کارخانه را مطالعه کردیم. ما از آن برای گسترش کسب و کار قهوه و افتتاح چندین مکان جدید استفاده کردیم. امروز ما به مدرن سازی کسب و کار خود ادامه خواهیم داد. با استفاده از الگوی کارخانه ای انتزاعی، پایه و اساس یک برنامه دسکتاپ جدید را برای سفارش آنلاین قهوه خواهیم گذاشت. هنگام نوشتن یک برنامه دسکتاپ، همیشه باید به پشتیبانی چند پلتفرمی فکر کنیم. برنامه ما باید هم روی macOS و هم روی ویندوز کار کند (اسپویلر: پشتیبانی از لینوکس به عنوان تکلیف برای شما باقی مانده است). برنامه ما چگونه خواهد بود؟ بسیار ساده: فرمی متشکل از یک فیلد متنی، یک فیلد انتخاب و یک دکمه خواهد بود. اگر تجربه استفاده از سیستم عامل های مختلف را دارید، مطمئناً متوجه شده اید که دکمه ها در ویندوز به طور متفاوتی نسبت به مک ارائه می شوند. مثل هر چیز دیگری... خب، بیایید شروع کنیم. همانطور که احتمالا قبلاً متوجه شده اید، خانواده محصول از عناصر رابط گرافیکی تشکیل شده است:
  • دکمه ها
  • فیلدهای متنی
  • زمینه های انتخاب
سلب مسئولیت: در هر رابط، می‌توانیم روش‌هایی مانند onClick، onValueChangedو یا را تعریف کنیم onInputChanged. به عبارت دیگر، می‌توانیم روش‌هایی را تعریف کنیم که به ما امکان می‌دهند رویدادهای مختلف را مدیریت کنیم (فشردن یک دکمه، وارد کردن متن، انتخاب یک مقدار در کادر انتخاب). همه اینها به عمد در اینجا حذف شده است تا مثال اضافه نشود و با مطالعه الگوی کارخانه روشن تر شود. بیایید رابط های انتزاعی را برای محصولات خود تعریف کنیم:
public interface Button {}
public interface Select {}
public interface TextField {}
برای هر سیستم عامل، ما باید عناصر رابط را به سبک سیستم عامل ایجاد کنیم. ما در حال نوشتن کد برای Windows و MacOS هستیم. بیایید پیاده سازی هایی برای ویندوز ایجاد کنیم:
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();
    }
}
توجه داشته باشید که هر امضای متد نشان می دهد که متد یک نوع انتزاعی را برمی گرداند. اما در داخل روش ها، ما در حال ایجاد پیاده سازی های خاص از محصولات هستیم. این تنها جایی است که ما ایجاد نمونه های خاص را کنترل می کنیم. حالا نوبت نوشتن کلاس برای فرم است. این یک کلاس جاوا است که فیلدهای آن عناصر رابط هستند:
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();
    }
}
اگر برنامه را روی ویندوز اجرا کنیم، خروجی زیر را دریافت می کنیم:

Creating GUIFactory for Windows OS
Creating coffee order form
Creating TextField for Windows OS
Creating Select for Windows OS
Creating Button for Windows OS
در مک، خروجی به صورت زیر خواهد بود:

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 :( 
و اکنون خلاصه می کنیم. ما اسکلت یک برنامه کاربردی مبتنی بر رابط کاربری گرافیکی را نوشتیم که در آن عناصر رابط به طور خاص برای سیستم عامل مربوطه ایجاد شده اند. ما به طور خلاصه آنچه را که ایجاد کرده ایم تکرار می کنیم:
  • یک خانواده محصول متشکل از یک فیلد ورودی، یک قسمت انتخاب و یک دکمه.
  • پیاده سازی های مختلف خانواده محصول برای ویندوز و macOS.
  • یک کارخانه انتزاعی که یک رابط برای ایجاد محصولات ما تعریف می کند.
  • دو پیاده سازی از کارخانه ما، که هر کدام مسئول ایجاد یک خانواده خاص از محصولات هستند.
  • یک فرم (یک کلاس جاوا) که فیلدهای آن عناصر واسط انتزاعی هستند که با مقادیر لازم در سازنده با استفاده از یک کارخانه انتزاعی مقداردهی اولیه می شوند.
  • کلاس کاربردی در داخل این کلاس، یک فرم ایجاد می کنیم و پیاده سازی کارخانه مورد نظر را به سازنده آن ارسال می کنیم.
نتیجه این است که ما الگوی کارخانه انتزاعی را اجرا کردیم.

کارخانه انتزاعی: نحوه استفاده

یک کارخانه انتزاعی یک الگوی طراحی برای مدیریت ایجاد خانواده های مختلف محصول بدون گره خوردن به کلاس های محصول بتن است. هنگام استفاده از این الگو، باید:
  1. خانواده های محصول را تعریف کنید. فرض کنید دو تا از آنها داریم:
    • SpecificProductA1،SpecificProductB1
    • SpecificProductA2،SpecificProductB2
  2. برای هر محصول در خانواده، یک کلاس انتزاعی (رابط) تعریف کنید. در مورد ما، ما داریم:
    • ProductA
    • ProductB
  3. در هر خانواده محصول، هر محصول باید رابط تعریف شده در مرحله 2 را پیاده سازی کند.
  4. یک کارخانه انتزاعی ایجاد کنید، با روش‌هایی برای ایجاد هر محصول که در مرحله 2 تعریف شده است. در مورد ما، این روش‌ها عبارتند از:
    • ProductA createProductA();
    • ProductB createProductB();
  5. پیاده سازی های انتزاعی کارخانه ای ایجاد کنید تا هر پیاده سازی ایجاد محصولات یک خانواده را کنترل کند. برای انجام این کار، در داخل هر پیاده سازی کارخانه انتزاعی، باید تمام متدهای Creations را پیاده سازی کنید تا پیاده سازی های محصول خاصی را ایجاد و برگردانند.
نمودار 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();
    }
}

مشق شب

برای تقویت مواد، می توانید 2 کار انجام دهید:
  1. برنامه سفارش قهوه را اصلاح کنید تا در لینوکس نیز کار کند.
  2. کارخانه انتزاعی خود را برای تولید واحدهای درگیر در هر استراتژی نظامی ایجاد کنید. این می تواند یک استراتژی نظامی تاریخی با ارتش های واقعی باشد یا یک استراتژی فانتزی با اورک ها، گنوم ها و الف ها. مهم این است که چیزی را انتخاب کنید که به آن علاقه دارید. خلاق باشید، پیام ها را روی کنسول چاپ کنید و از یادگیری الگوها لذت ببرید!
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION