سلام! امروز ما به مطالعه الگوهای طراحی ادامه خواهیم داد و در مورد الگوی روش کارخانه بحث خواهیم کرد.
متوجه خواهید شد که چیست و این الگو برای چه کارهایی مناسب است. این الگوی طراحی را در عمل در نظر می گیریم و ساختار آن را بررسی می کنیم. برای اطمینان از اینکه همه چیز واضح است، باید موضوعات زیر را درک کنید:
چه نتیجه ای می توانیم بگیریم؟
نمودار بالا ساختار کلی الگوی روش کارخانه را نشان می دهد. چه چیز دیگری در اینجا مهم است؟

- وراثت در جاوا
- روش ها و کلاس های انتزاعی در جاوا
روش کارخانه چه مشکلی را حل می کند؟
همه الگوهای طراحی کارخانه دو نوع شرکت کننده دارند: خالقان (خود کارخانه ها) و محصولات (اشیاء ایجاد شده توسط کارخانه ها). وضعیت زیر را تصور کنید: ما کارخانه ای داریم که خودروهایی با برند CodeGym تولید می کند. می داند که چگونه مدل هایی از خودروها را با انواع مختلف بدنه ایجاد کند:- سدان ها
- استیشن واگن ها
- کوپه ها
- سدان CodeGym
- استیشن واگن CodeGym
- کوپه های CodeGym
- سدان های OneAuto
- واگن های استیشن 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;
}
}
مدرن کردن یک کارخانه ساده
کافی شاپ ما خیلی خوب کار می کند. به حدی که به فکر گسترش هستیم. ما می خواهیم چند مکان جدید باز کنیم. ما جسور و مبتکر هستیم، بنابراین کافیشاپهای خستهکننده را انتخاب نمیکنیم. ما می خواهیم هر مغازه پیچ و تاب خاصی داشته باشد. بر این اساس، برای شروع، ما دو مکان را باز خواهیم کرد: یکی ایتالیایی و دیگری آمریکایی. این تغییرات نه تنها بر طراحی داخلی، بلکه بر نوشیدنی های ارائه شده نیز تأثیر می گذارد:- در کافی شاپ ایتالیایی منحصراً از برندهای قهوه ایتالیایی با آسیاب و برشته کردن ویژه استفاده خواهیم کرد.
- مکان آمریکایی بخش های بزرگ تری خواهد داشت و ما با هر سفارش مارشمالو سرو می کنیم.
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;
}
}
حال می توانیم پیاده سازی کارخانه ای مورد نظر را به کافی شاپ منتقل کنیم. بیایید ببینیم کد سفارش قهوه از کافی شاپ های مختلف چگونه خواهد بود. به عنوان مثال، کاپوچینو به سبک ایتالیایی و آمریکایی:
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
با پیوند دادن فرآیندهای ایجاد قهوه و سفارشات سرويس، همه مسائل مربوط به تهیه قهوه را در کلاس قرار دهیم و همزمان انعطاف کافی برای تهیه سبک های مختلف قهوه را حفظ کنیم. پاسخ این است که بله، ما می توانیم. به این الگوی طراحی روش کارخانه می گویند.
از یک کارخانه ساده تا یک روش کارخانه ای
برای حل کار تا حد امکان موثر:createCoffee(CoffeeType type)
متد را به کلاس برمی گردانیمCoffeeShop
.- ما این روش را انتزاعی خواهیم کرد.
- خود کلاس
CoffeeShop
انتزاعی می شود. - کلاس
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);
}
}
تبریک می گویم. ما فقط الگوی طراحی روش کارخانه را با استفاده از کافی شاپ خود به عنوان مثال اجرا کردیم.
اصل روش های کارخانه ای
حالا بیایید جزئیات بیشتری را در نظر بگیریم که چه چیزی به دست آوردیم. نمودار زیر کلاس های حاصل را نشان می دهد. بلوک های سبز کلاس های سازنده و بلوک های آبی کلاس های محصول هستند.
- همه محصولات پیاده سازی از کلاس انتزاعی هستند
Coffee
. - همه سازندگان پیاده سازی های کلاس انتزاعی هستند
CoffeeShop
. - ما دو سلسله مراتب طبقاتی موازی را می بینیم:
- سلسله مراتب محصولات ما نوادگان ایتالیایی و نوادگان آمریکایی را می بینیم
- سلسله مراتب پدیدآورندگان. ما نوادگان ایتالیایی و نوادگان آمریکایی را می بینیم
- سوپرکلاس
CoffeeShop
هیچ اطلاعاتی در مورد اینکه کدام محصول خاص (Coffee
) ایجاد خواهد شد ندارد. - ابر
CoffeeShop
کلاس ایجاد یک محصول خاص را به فرزندان خود محول می کند. - هر یک از نوادگان
CoffeeShop
کلاس یکcreateCoffee()
متد کارخانه ای را مطابق با ویژگی های خاص خود پیاده سازی می کند. به عبارت دیگر، پیادهسازیهای کلاسهای تولیدکننده، محصولات خاصی را بر اساس ویژگیهای طبقه تولیدکننده آماده میکنند.
ساختار یک روش کارخانه

- کلاس Creator تمام متدهایی را که با محصولات تعامل دارند پیاده سازی می کند، به جز روش کارخانه.
- متد انتزاعی
factoryMethod()
باید توسط همه نوادگان کلاس پیاده سازی شودCreator
. - کلاس متد را
ConcreteCreator
پیاده سازی می کندfactoryMethod()
که مستقیماً محصول را ایجاد می کند. - این کلاس وظیفه ایجاد محصولات خاص را بر عهده دارد. این تنها کلاس با اطلاعات در مورد ایجاد این محصولات است.
- همه محصولات باید یک رابط مشترک را پیاده سازی کنند، یعنی باید فرزندان یک کلاس محصول مشترک باشند. این امر ضروری است تا کلاسهایی که از محصولات استفاده میکنند بتوانند بر روی آنها بهعنوان انتزاع عمل کنند تا پیادهسازی خاص.
GO TO FULL VERSION