سلام! امروز ما به مطالعه الگوهای طراحی ادامه خواهیم داد و در مورد الگوی کارخانه انتزاعی بحث خواهیم کرد .
در اینجا چیزی است که ما در درس پوشش خواهیم داد:
اکنون ما کد را مطابق این دستورالعمل ها می نویسیم:

- ما بحث خواهیم کرد که یک کارخانه انتزاعی چیست و این الگو چه مشکلی را حل می کند
- ما اسکلت یک برنامه چند پلتفرمی را برای سفارش قهوه از طریق رابط کاربری ایجاد خواهیم کرد
- ما دستورالعملهایی را در مورد نحوه استفاده از این الگو، از جمله مشاهده نمودار و کد، مطالعه خواهیم کرد
- و به عنوان یک امتیاز، این درس شامل یک تخم مرغ عید پاک است که به شما کمک می کند یاد بگیرید چگونه از جاوا برای تعیین نام سیستم عامل استفاده کنید و بسته به نتیجه، یک عمل دیگر را انجام دهید.
- وراثت در جاوا
- کلاس ها و متدهای انتزاعی در جاوا
یک کارخانه انتزاعی چه مشکلاتی را حل می کند؟
یک کارخانه انتزاعی، مانند تمام الگوهای کارخانه، به ما کمک می کند تا اطمینان حاصل کنیم که اشیاء جدید به درستی ایجاد می شوند. ما از آن برای مدیریت "تولید" خانواده های مختلف اشیاء به هم پیوسته استفاده می کنیم. خانواده های مختلف اشیاء به هم پیوسته... یعنی چه؟ نگران نباشید: در عمل، همه چیز ساده تر از آن چیزی است که ممکن است به نظر برسد. برای شروع، یک خانواده از اشیاء به هم پیوسته چه می تواند باشد؟ فرض کنید ما در حال توسعه یک استراتژی نظامی هستیم که شامل چندین نوع واحد است:- پیاده نظام
- سواره نظام
- کمانداران
بیایید به خودکارسازی کافی شاپ خود ادامه دهیم
در درس آخر الگوی روش کارخانه را مطالعه کردیم. ما از آن برای گسترش کسب و کار قهوه و افتتاح چندین مکان جدید استفاده کردیم. امروز ما به مدرن سازی کسب و کار خود ادامه خواهیم داد. با استفاده از الگوی کارخانه ای انتزاعی، پایه و اساس یک برنامه دسکتاپ جدید را برای سفارش آنلاین قهوه خواهیم گذاشت. هنگام نوشتن یک برنامه دسکتاپ، همیشه باید به پشتیبانی چند پلتفرمی فکر کنیم. برنامه ما باید هم روی 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.
- یک کارخانه انتزاعی که یک رابط برای ایجاد محصولات ما تعریف می کند.
- دو پیاده سازی از کارخانه ما، که هر کدام مسئول ایجاد یک خانواده خاص از محصولات هستند.
- یک فرم (یک کلاس جاوا) که فیلدهای آن عناصر واسط انتزاعی هستند که با مقادیر لازم در سازنده با استفاده از یک کارخانه انتزاعی مقداردهی اولیه می شوند.
- کلاس کاربردی در داخل این کلاس، یک فرم ایجاد می کنیم و پیاده سازی کارخانه مورد نظر را به سازنده آن ارسال می کنیم.
کارخانه انتزاعی: نحوه استفاده
یک کارخانه انتزاعی یک الگوی طراحی برای مدیریت ایجاد خانواده های مختلف محصول بدون گره خوردن به کلاس های محصول بتن است. هنگام استفاده از این الگو، باید:- خانواده های محصول را تعریف کنید. فرض کنید دو تا از آنها داریم:
SpecificProductA1
،SpecificProductB1
SpecificProductA2
،SpecificProductB2
- برای هر محصول در خانواده، یک کلاس انتزاعی (رابط) تعریف کنید. در مورد ما، ما داریم:
ProductA
ProductB
- در هر خانواده محصول، هر محصول باید رابط تعریف شده در مرحله 2 را پیاده سازی کند.
- یک کارخانه انتزاعی ایجاد کنید، با روشهایی برای ایجاد هر محصول که در مرحله 2 تعریف شده است. در مورد ما، این روشها عبارتند از:
ProductA createProductA();
ProductB createProductB();
- پیاده سازی های انتزاعی کارخانه ای ایجاد کنید تا هر پیاده سازی ایجاد محصولات یک خانواده را کنترل کند. برای انجام این کار، در داخل هر پیاده سازی کارخانه انتزاعی، باید تمام متدهای Creations را پیاده سازی کنید تا پیاده سازی های محصول خاصی را ایجاد و برگردانند.

// 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 کار انجام دهید:- برنامه سفارش قهوه را اصلاح کنید تا در لینوکس نیز کار کند.
- کارخانه انتزاعی خود را برای تولید واحدهای درگیر در هر استراتژی نظامی ایجاد کنید. این می تواند یک استراتژی نظامی تاریخی با ارتش های واقعی باشد یا یک استراتژی فانتزی با اورک ها، گنوم ها و الف ها. مهم این است که چیزی را انتخاب کنید که به آن علاقه دارید. خلاق باشید، پیام ها را روی کنسول چاپ کنید و از یادگیری الگوها لذت ببرید!
GO TO FULL VERSION