الگوی کارخانه انتزاعی، در الگوهای نرمافزاری روشی برای جمعبندی گروهی از کارخانههای مجازی است که ساختار مشابهی دارند ولی از کلاسهای مختلفی تشکیل شدهاند .[۱]
در حالت عادی، برنامه زیرشاخه یک ساختار یکپارچه از کارخانه انتزاعی را میسازد و سپس از واسط کاربری میخواهد که شیءهای مختلفی در آن تم (دارای شباهت در تعدادی از ویژگیها) بسازد. برنامه زیر شاخه نمیداند (یا اهمیت نمیدهد) که چه شیءای را از کتابخانه گرفته است. چون تنها از شی ساخته شده استفاده میکند. [۱]این الگو جزئیات اجرا و استفاده از گروهی از اشیاء را،از نحوهپیادهسازی آنها جدا میکند. چرا که ساخت اشیاء در کارخانه صورت میگیرد.[۲]
به طور مثال کلاس کتابخانه انتزاعی DocumentCreator که رابطی برای ساخت تعدادی از کتابخانهها (ازجمله createLetter و createResume) را فراهم میکند. این سامانه میتواند به هر تعداد از نسخههای کتابخانههای مشتق شده از کلاس DocumentCreator را داشته باشد. مثل FancyDocumentCreator یا ModernDocumentCreator هر کدام با یک پیادهسازی متفاوت از createLetter و createResume شیهای مربوط را تولید کنند. و هر کدام از یک کلاس انتزاعی ثابتی مانند Letter یا Resume ساخته میشوند. برنامه زیرشاخه یک ساخته از DocumentCreator را دریافت میکند که به آن کارخانه انتزاعی گفته میشود. اشیاء ساخته شده همگی توسط یک DocumentCreator ساخته میشوند و ساختار مشابهی خواهند داشت. برنامه زیرشاخه تنها نیاز است بداند که چگونه یک کلاس از نوع Letter یا Resume را که از کارخانه میگیرد استفاده کند.
کارخانه محل کلاسهای متشابه داخل کد که اشیاء از آنها ساخته میشوند میباشد. هدف پیادهسازی الگو جداسازی ساخت اشیاء از استفاده آنها و ساخت خانوادههایی از اشیاء مرتبط بدون نیاز به وابستگی به نوع کلاس آنهاست.
استفاده از این الگو تغییر پیادهسازیهای متفاوت را بدون تغییر برنامههایی که از این پیادهسازیها استفاده میکنند را ممکن کرده است. هرچند، استفاده از این الگو، مانند الگوهای متشابه، ممکن است باعث پیچیدگی و کار اضافه در نوشتن کد اولیه شود. همچنین جداسازی و انتزاعی کردن در سطحهای بالا ممکن است موجب امکان اشکالزدایی و مراقبت از سامانهها را سختتر بکند.
به طور کلی الگوی Abstract Factory برای ساخت برنامههای قابل توسعه و قابل تغییر مفید است. این الگو به برنامهنویسان امکان میدهد تا برنامههای پیچیده را با استفاده از شیهای ساختاری سادهتر و با استفاده از استانداردهای مشترک طراحی کنند.
برای مثال، فرض کنید که یک برنامه نیاز به ساخت شیهای گوناگونی دارد که هر کدام نیاز به پردازشهای مختلفی دارند. با استفاده از الگوی Abstract Factory، میتوان یک کلاس فابریک ایجاد کرد که برای هر نوع شی مورد نیاز، یک شی جدید ایجاد کند و پردازشهای مختلف را برای آنها انجام دهد. به عنوان مثال، یک الگوی Abstract Factory برای ساخت شیهای گوناگونی میتواند به کار گرفته شود.
تعریف
ماهیت کارخانه انتزاعی را میتوان این طور تعریف کرد که "رابطی برای ساخت خانوادهای از اشیاء مرتبط یا وابسته بدون نیاز به مشخص کردن نوع کلاس آنها.[۳]
استفاده
کارخانه نوع شیءای که قرار است ساخته بشود را تعیین میکند. هرچند که تنها یک شیء از آن را بازمیگرداند.
این باعث جلوگیری از ساخت شیء توسط برنامه زیرشاخه میشود. برنامه زیر شاخه تنها از کارخانه میخواهد تا یک شیء از مدل خواسته شده را برای آن بسازد.[۴]
از آنجایی که کارخانه تنها یک نشانهگر به شیء ساخته شده را بازمیگرداند برنامه زیرشاخه نمیداند که این شیء از کدام کلاس ساخته شده است. پس نوع شی لازم نیست برای برنامه مشتری تعریف شود.
در کل این بدین معنی است که:
مشتری هیچ دانشی دربارهٔ این که چه مدلی و چه روابطی در شیء به کار رفته است ندارد و تنها یک نسخه ساخته شده از کلاس انتزاعی دریافت میکند و تنها از طریق رابط انتزاعی با آن ارتباط دارد.[۵]
اضافه کردن انواع جدید کلاس با تنظیم مشتری به استفاده از کارخانه دیگری انجام میشود و این بسیار راحتتر از آن است که علاوه بر آنکه کلاس جدید برای مشتری تعریف شود، قسمتهای مختلف کد مشتری برای سازگاری با کلاس جدید از نوع نوشته شود. اگر تمامی کارخانهها در یک سینگلتون ذخیره شوند کافیست داخل کد از طریق سینگلتون به کارخانه مورد نظر دسترسی پیدا کنیم و این گونه استفاده از کارخانهها بسیار آسانتر خواهد بود.[۵]
ساختار
نمودار کلاسها
دستور createButton در رابط GUIFactory یک شی از نوع button دریافت میکند و ایدهای ندارد که چه پیادهسازی از GUIFactory دریافت کرده است.
باید یک کلید در سیستم عاملهای ویندوز یا مک ایجاد کند. دقت کنید که برنامه هیچ ایدهای ندارد که چه نوع GUIFactory و Buttonای به اون میدهند.
method paint()
interface GUIFactory is
method createButton()
output: a button
class WinFactory implementing GUIFactory is
method createButton() is
output: a Windows button
Return a new WinButton
class OSXFactory implementing GUIFactory is
method createButton() is
output: an OS X button
Return a new OSXButton
class WinButton implementing Button is
method paint() is
Render a button in a Windows style
class OSXButton implementing Button is
method paint() is
Render a button in a Mac OS X style
class Application is
constructor Application(factory) is
input: the GUIFactory factory used to create buttons
Button button := factory.createButton()
button.paint()
Read the configuration file
If the OS specified in the configuration file is Windows, then
Construct a WinFactory
Construct an Application with WinFactory
else
Construct an OSXFactory
Construct an Application with OSXFactory
C# مثال
interfaceIButton{voidPaint();}interfaceIGUIFactory{IButtonCreateButton();}classWinFactory:IGUIFactory{publicIButtonCreateButton(){returnnewWinButton();}}classOSXFactory:IGUIFactory{publicIButtonCreateButton(){returnnewOSXButton();}}classWinButton:IButton{publicvoidPaint(){//Render a button in a Windows style}}classOSXButton:IButton{publicvoidPaint(){//Render a button in a Mac OS X style}}classProgram{staticvoidMain(){varappearance=Settings.Appearance;IGUIFactoryfactory;switch(appearance){caseAppearance.Win:factory=newWinFactory();break;caseAppearance.OSX:factory=newOSXFactory();break;default:thrownewSystem.NotImplementedException();}varbutton=factory.CreateButton();button.Paint();}}
publicinterfaceIButton{voidpaint();}publicinterfaceIGUIFactory{publicIButtoncreateButton();}publicclassWinFactoryimplementsIGUIFactory{@OverridepublicIButtoncreateButton(){returnnewWinButton();}}publicclassOSXFactoryimplementsIGUIFactory{@OverridepublicIButtoncreateButton(){returnnewOSXButton();}}publicclassWinButtonimplementsIButton{@Overridepublicvoidpaint(){System.out.println("WinButton");}}publicclassOSXButtonimplementsIButton{@Overridepublicvoidpaint(){System.out.println("OSX button");}}publicclassMain{publicstaticvoidmain(String[]args)throwsException{IGUIFactoryfactory=null;Stringappearance=randomAppearance();//current operating systemif(appearance.equals("osx")){factory=newOSXFactory();}elseif(appearance.equals("windows")){factory=newWinFactory();}else{thrownewException("No such operating system");}IButtonbutton=factory.createButton();button.paint();}/** * This is just for the sake of testing this program, and doesn't have to do * with Abstract Factory pattern. * @return */publicstaticStringrandomAppearance(){String[]appearanceArr=newString[3];appearanceArr[0]="osx";appearanceArr[1]="windows";appearanceArr[2]="error";java.util.Randomrand=newjava.util.Random();intrandNum=rand.nextInt(3);returnappearanceArr[randNum];}}
مثال کریستال
abstract class Button
abstract def paint
end
class LinuxButton <Button
def paint
"Render a button in a Linux style"
end
end
class WindowsButton <Button
def paint
"Render a button in a Windows style"
end
end
class MacOSButton <Button
def paint
"Render a button in a MacOS style"
end
end
abstract class GUIFactory
abstract def create_button : Button
end
class LinuxFactory <GUIFactory
def create_button
return LinuxButton.new
end
end
class WindowsFactory <GUIFactory
def create_button
return WindowsButton.new
end
end
class MacOSFactory <GUIFactory
def create_button
return MacOSButton.new
end
end
# Run program
appearance = "linux"
case appearance
when "linux"
factory = LinuxFactory.new
when "osx"
factory = MacOSFactory.new
when "win"
factory = WindowsFactory.new
end
if factory
button = factory.create_button
result = button.paint
puts result
end
↑Gamma, Erich; Richard Helm; Ralph Johnson; John M. Vlissides (2009-10-23). "Design Patterns: Abstract Factory". informIT. Archived from the original on 27 January 2017. Retrieved 2012-05-16. Object Creational: Abstract Factory: Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.{{cite web}}: نگهداری یادکرد:ربات:وضعیت نامعلوم پیوند اصلی (link)
↑Veeneman, David (2009-10-23). "Object Design for the Perplexed". The Code Project. Archived from the original on 21 February 2011. Retrieved 2012-05-16. The factory insulates the client from changes to the product or how it is created, and it can provide this insulation across objects derived from very different abstract interfaces.{{cite web}}: نگهداری یادکرد:ربات:وضعیت نامعلوم پیوند اصلی (link)