У чому полягає основна відмінність фабричних та абстрактних заводських моделей?
createThing()
), а абстрактний завод використовує композицію (непрямість, наприклад, горизонтальність getFactory().createThing()
)
У чому полягає основна відмінність фабричних та абстрактних заводських моделей?
createThing()
), а абстрактний завод використовує композицію (непрямість, наприклад, горизонтальність getFactory().createThing()
)
Відповіді:
З малюнком Factory, ви робите примірників реалізацій ( Apple
, Banana
, Cherry
і т.д.) конкретного інтерфейсу - скажімо, IFruit
.
За допомогою абстрактного фабричного шаблону ви надаєте спосіб кожному забезпечити власну фабрику. Це дозволяє вашому складу бути або IFruitFactory
або IJuiceFactory
, не вимагаючи від вашого складу нічого знати про фрукти чи соки.
IFruit
- вона створює речі, які реалізує IFruit
. Звичайно, не потрібно створювати екземпляри речей, що реалізують певний інтерфейс, але це, мабуть, запах коду, якщо у вас є Фабрика, яка виробляє речі, які абсолютно не пов'язані один з одним.
Джерело цієї інформації взято з: http://java.dzone.com/news/intro-design-patterns-ab Abstract
Методи абстрактної фабрики реалізовані як фабричні методи. Як абстрактний заводський візерунок, так і заводський метод методу відокремлює клієнтську систему від реальних класів впровадження через абстрактні типи та заводи. Фабричний метод створює об'єкти у спадок, де Абстрактна фабрика створює об'єкти через композицію.
Абстрактний заводський візерунок складається з абстрактного фабричного, бетонного фактурного, абстрактного продукту, конкретного продукту та клієнта.
Абстрактний заводський візерунок може бути реалізований за допомогою заводського методу, шаблону прототипу або одинарного малюнка. Об'єкт ConcreteFactory може бути реалізований як Singleton, оскільки потрібен лише один екземпляр об'єкта ConcreteFactory.
Заводський метод шаблону - це спрощена версія абстрактного фабричного шаблону. Фабричний шаблон моделі відповідає за створення продуктів, що належать до однієї родини, тоді як абстрактний заводський зразок стосується кількох сімейств продуктів.
Фабричний метод використовує інтерфейси та абстрактні класи, щоб від'єднати клієнта від класу генератора та отриманих продуктів. Анотація Factory має генератор, який є контейнером для декількох заводських методів, а також інтерфейси, що відокремлюють клієнта від генератора та продуктів.
Використовуйте шаблон заводських методів, коли є необхідність від'єднати клієнта від певного продукту, який він використовує. Використовуйте заводський метод, щоб звільнити клієнта від відповідальності за створення та налаштування примірників продукту.
Використовуйте абстрактний заводський шаблон, коли клієнти повинні бути відірвані від класів продуктів. Особливо корисно для налаштування та модифікації програми. Анотація «Заводська модель» також може застосовувати обмеження щодо того, які класи повинні використовуватися з іншими. Зробити нові бетонні заводи може бути багато роботи.
Ця специфікація для дисків для приготування різних видів макаронних виробів у виробнику макаронних виробів - це «Фабрика абстрактних», а кожен конкретний диск - «Фабрика». всі заводи (диски для виготовлення макаронних виробів) успадковують свої властивості від абстрактної Фабрики. Кожен окремий диск містить інформацію про те, як створити пасту, а виробник пасти - ні.
Обладнання для штампування відповідає «Фабриці абстрактних», оскільки це інтерфейс для операцій, що створюють абстрактні об’єкти продукту. Штампи відповідають Бетонному заводу, оскільки вони створюють бетонний виріб. Кожна категорія деталей (капюшон, двері тощо) відповідає абстрактному твору. Конкретні деталі (тобто, бічні двері для водія на 99 кемрі) відповідають конкретним виробам.
Компанія іграшок відповідає Творцю, оскільки вона може використовувати фабрику для створення предметів товару. Підрозділ іграшкової компанії, яка виробляє конкретний тип іграшки (коня чи машини), відповідає ConcreteCreator.
Фабрична схема: Фабрика виробляє реалізацію IProduct
Абстрактний заводський зразок: фабрика-фабрика виробляє IFactories, яка, в свою чергу, виробляє IProducts :)
[Оновлення відповідно до коментарів]
Те, що я писав раніше, є невірним відповідно до Вікіпедії . Абстрактна фабрика - це просто фабричний інтерфейс. З його допомогою ви можете перемикати фабрики під час виконання, щоб дозволити різні заводи в різних контекстах. Прикладами можуть бути різні фабрики для різних ОС, постачальників SQL, драйверів програмного забезпечення тощо.
Забезпечте інтерфейс для створення сімей пов’язаних або залежних об'єктів, не вказуючи їх конкретні класи.
Абстрактний заводський візерунок дуже схожий на заводський метод. Одна відмінність між ними полягає в тому, що за абстрактним заводським зразком клас делегує відповідальність за інстанціювання об'єкта іншому об'єкту за допомогою композиції, тоді як шаблон методу Factory використовує успадкування і покладається на підклас для обробки потрібного об'єкта.
Власне, делегований об'єкт часто використовує заводські методи для виконання інстанції!
Фабричні візерунки - приклади креативних моделей
Творчі візерунки абстрагують процес інстанціїзації об'єкта. Вони приховують, як створюються об'єкти, і допомагають зробити загальну систему незалежною від того, як створюються та складаються її об'єкти.
Шаблони творчих процесів класу зосереджуються на використанні спадщини для визначення об'єкта, який підлягає інстанції Фабричний метод
Об'єктні креативні візерунки фокусуються на делегуванні інстанції на інший об'єкт абстрактного заводу
Довідка: Фабрика проти абстрактної фабрики
Фабричний метод: у вас є фабрика, яка створює об'єкти, що походять з певного базового класу
Анотація заводу: у вас є завод, який створює інші фабрики , а ці фабрики, в свою чергу, створюють об'єкти, отримані з базових класів. Ви робите це, тому що часто не просто хочеться створити єдиний об'єкт (як при Фабричному методі), а потрібно створити колекцію пов'язаних об'єктів.
Основна різниця:
Фабрика: створює об'єкти, не піддаючи клієнту логіку ідентифікації.
Фабричний метод : Визначте інтерфейс для створення об’єкта, але нехай підкласи вирішують, який клас інстанціювати. Фабричний метод дозволяє відкладати екземпляр класу для підкласів
Анотація заводу : надає інтерфейс для створення сімей пов’язаних або залежних об'єктів без зазначення їх конкретних класів.
Шаблон AbstractFactory використовує композицію для делегування відповідальності за створення об'єкта іншому класу, тоді як шаблон методу Factory використовує успадкування та для створення об'єкта покладається на похідний клас або підклас
З статей про дизайн дизайну :
Діаграма класу заводу :
Приклад: StaticFactory
public class ShapeFactory {
//use getShape method to get object of type shape
public static Shape getShape(String shapeType){
if(shapeType == null){
return null;
}
if(shapeType.equalsIgnoreCase("CIRCLE")){
return new Circle();
} else if(shapeType.equalsIgnoreCase("RECTANGLE")){
return new Rectangle();
} else if(shapeType.equalsIgnoreCase("SQUARE")){
return new Square();
}
return null;
}
}
Нестатичний завод, що реалізує приклад FactoryMethod, доступний у цій публікації:
Шаблони дизайну: Фабрика проти заводського методу проти абстрактного заводу
Коли користуватися: Клієнту просто потрібен клас і не байдуже, яку конкретну реалізацію він отримує.
Дігарам класу заводських методів :
Коли користуватися: Клієнт не знає, які конкретні класи потрібно буде створити під час виконання, але просто хоче отримати клас, який зробить цю роботу.
Анотація заводської діаграми класу від dzone
Коли використовувати: Коли вашій системі потрібно створити декілька сімейств продуктів або ви хочете надати бібліотеку продуктів, не піддаючи деталей реалізації.
Приклади вихідного коду у вищезазначених статтях дуже добре розуміти поняття.
Пов'язане запитання SE з прикладом коду:
Фабричний візерунок. Коли використовувати заводські методи?
Відмінності:
Інші корисні статті:
factory_method з створення джерела
Abstract_factory від створення джерела
абстрактно-фабрика-дизайн-візерунок від journaldev
Приклад / сценарій для абстрактних заводів
Я живу там, де у дощовий сезон йде дощ, взимку снігу, влітку жарко і сонячно. Мені потрібен різний вид одягу, щоб захистити себе від стихій. Для цього я заходжу в магазин біля свого будинку і прошу одяг / предмети, щоб захистити себе. Власник магазину дає мені відповідний предмет відповідно до середовища та глибини кишені. Елементи, які він мені дає, мають однаковий рівень якості та цінового діапазону. Оскільки він знає мої стандарти, йому це легко зробити. Але коли багатий хлопець з усієї вулиці висуває ті самі вимоги, він отримує дорогий, фірмовий предмет. Одне помітне - всі предмети, які він мені дає, доповнюють один одного за рівнем якості, стандарту та вартості. Можна сказати, що вони йдуть один з одним. Те саме стосується предметів, які отримує цей багатий хлопець.
Отож, дивлячись на вищезгаданий сценарій, я зараз оцінюю ефективність роботи магазину. Я можу замінити цього крамника на абстрактний магазин. Предмети, які ми отримуємо з абстрактними предметами, і я, і багаті, як перспективні клієнти. Все, що нам потрібно - це товар / товар, який відповідає нашим потребам.
Тепер я легко бачу себе, розглядаючи Інтернет-магазин, який надає набір послуг своїм численним клієнтам. Кожен клієнт належить до однієї з трьох груп. Коли користувач преміум-групи відкриває сайт, він отримує чудовий інтерфейс користувача, високоіндивідуальну панель реклами, більше опцій у меню тощо. Цей самий набір функцій представлений користувачеві із золота, але функціональність у меню менше, реклама в основному сприйнятлива, і трохи менш егрономічний інтерфейс користувача. Останнє - це мій тип користувача, користувач «вільної групи». Мені просто подано достатньо, щоб я не образився. Користувальницький інтерфейс - це мінімальний мінімум, реклама настільки відсторонена, що я не знаю, що в ньому входить, нарешті, меню лише вийшло.
Якщо я отримаю можливість створити щось на зразок цього веб-сайту, я б точно розглядав абстрактний заводський зразок.
Абстрактні продукти: Панель реклами, меню, художник інтерфейсу.
Абстрактна фабрика: Досвід користувачів веб-магазину
Створити завод: Преміальний досвід користувачів, Золотий досвід користувачів, Загальний досвід користувачів.
Можливо, багато людей почуватимуться здивованими, але це питання неправильне . Якщо ви чуєте це питання під час інтерв'ю, вам потрібно допомогти інтерв'юеру зрозуміти, де знаходиться плутанина.
Почнемо з того, що не існує конкретного малюнка, який називається просто «Фабричний». Існує шаблон, який називається "Абстрактний завод", і є шаблон, який називається "Фабричний метод".
Отже, що означає "Фабрика"? одне з наступних (все можна вважати правильним, залежно від обсягу посилання):
І, на жаль , багато людей використовують "Фабрику" для позначення іншого виду фабрики, що створює фабрику або фабрики (або їх інтерфейси). Виходячи з їх теорії:
Продукт реалізує IProduct, який створений Factory, який реалізує IFactory, який створюється AbstractFactory.
Щоб зрозуміти, наскільки це нерозумно, продовжимо наше рівняння:
AbstractFactory реалізує IAbpositeFactory, який створюється ... AbstractAb абстрактFactory ???
Сподіваюся, ви бачите сенс. Не плутайтесь і, будь ласка, не вигадуйте речі, які не існують з причини.
-
PS : Фабрика продуктів - AbstractFactory, а «Фабрика абстрактних фабрик» - це ще один приклад абстрактної фабрики.
//Abstract factory - Provides interface to create factory of related products
interface PizzaIngredientsFactory{
public Dough createDough(); //Will return you family of Dough
public Clam createClam(); //Will return you family of Clam
public Sauce createSauce(); //Will return you family of Sauce
}
class NYPizzaIngredientsFactory implements PizzaIngredientsFactory{
@Override
public Dough createDough(){
//create the concrete dough instance that NY uses
return doughInstance;
}
//override other methods
}
Визначення підручника вже надані іншими відповідями. Я думав, що я також надам приклад.
Так ось PizzaIngredientsFactory
це абстрактна фабрика , як він надає методи для створення сімейства родинних продуктів.
Зауважте, що кожен метод на заводі «Анотація» сам по собі є Фабричним методом . Подібний createDough()
сам по собі є заводським методом, конкретні реалізації якого забезпечуватимуться підкласами типу NYPizzaIngredientsFactory
. Таким чином, використовуючи це, кожне інше місце може створити екземпляри конкретних інгредієнтів, які належать до їх розташування.
Надає екземпляр конкретної реалізації
У прикладі:
- createDough()
- забезпечує конкретну реалізацію тіста. Тож це заводський метод
Забезпечує інтерфейс для створення сімейства пов'язаних об'єктів
У прикладі:
- PizzaIngredientsFactory
це абстрактна фабрика , оскільки це дозволяє створити пов'язаний набір об'єктів , таких як Dough
, Clams
, Sauce
. Для створення кожної родини об'єктів передбачений заводський метод.
Приклад із шаблонів дизайну Head First
У мене є деякі моменти, щоб зробити свій внесок у відповідь Джона наступним чином:
З «Factory Method» (тому що тільки «Фабрика» неоднозначно), ви робите реалізації ( Lemon
, Orange
і т.д.) конкретного інтерфейсу - скажімо, IFruit
. Цю Фабрику можна було б назвати CitricFruitFactory
.
Але тепер ви хочете створити ще один вид фруктів, які CitricFruitFactory не в змозі створити. Можливо, код CitricFruitFactory
не має сенсу, якщо ви створюєте Strawberry
в ньому (полуниця - це не лимонний фрукт!).
Таким чином , ви можете створити новий завод під назвою , RedFruitFactory
яка виробляє Strawberry
, Raspberry
і т.д.
Як сказав Джон Фемінелла:
"За допомогою абстрактного фабричного шаблону ви створюєте реалізацію певного фабричного інтерфейсу - наприклад, IFruitFactory
кожен з них знає, як створювати різні види фруктів".
Що впровадження IFruitFactory
є CitricFruitFactory
і RedFruitFactory
!
Мої джерела: StackOverflow
, tutorialspoint.com
, programmers.stackexchange.com
і CodeProject.com
.
Factory Method
(також називається Factory
) призначений для роз'єднання клієнта Interface
реалізації. Для зразка у нас є Shape
інтерфейс з двома Circle
та Square
реалізаціями. Ми визначили заводський клас з фабричним методом з таким параметром детермінатора, як Type
і нова пов'язана реалізація Shape
інтерфейсу.
Abstract Factory
містить кілька заводських методів або заводський інтерфейс кількох заводських реалізацій. Для наступного вище зразка у нас є Color
інтерфейс з двома Red
та Yellow
реалізаціями. Ми визначили ShapeColorFactory
інтерфейс з двома RedCircleFactory
та YellowSquareFactory
. Наступний код для пояснення цієї концепції:
interface ShapeColorFactory
{
public Shape getShape();
public Color getColor();
}
class RedCircleFactory implements ShapeColorFactory
{
@Override
public Shape getShape() {
return new Circle();
}
@Override
public Color getColor() {
return new Red();
}
}
class YellowSquareFactory implements ShapeColorFactory
{
@Override
public Shape getShape() {
return new Square();
}
@Override
public Color getColor() {
return new Yellow();
}
}
Тут різниця між FactoryMethod
і AbstractFactory
. Factory Method
як просто повернути конкретний клас інтерфейсу, але Abstract Factory
повернути factory of factory
. Іншими словами, Abstract Factory
повертайте різні поєднання серії інтерфейсів.
Сподіваюся, моє пояснення корисне.
Основна різниця цих заводів полягає в тому, що ви хочете робити з фабриками і коли ви хочете їх використовувати.
Іноді, коли ви робите МОК (інверсія управління, наприклад, впорскування конструктора), ви знаєте, що ви можете створювати тверді предмети. Як було сказано в прикладі вище фруктів, якщо ви готові створювати предмети з фруктів, ви можете використовувати просту заводську схему .
Але багато разів не хочеться створювати тверді об’єкти, вони з’являться пізніше в програмному потоці. Але конфігурація говорить вам про те, яку фабрику ви хочете використовувати на старті, замість створення об'єктів ви можете передати фабрики, що походять із загального фабричного класу, до конструктора в МОК.
Отже, я думаю, що це стосується і терміну експлуатації об'єкта, і його створення.
І ті, Factory Method
і інші Abstract Factory
клієнти не відокремлюються від конкретних типів. Обидва створюють об'єкти, але Factory
метод використовує спадкування, тоді як Abstract Factory
використовують композицію.
Factory Method
Успадковуються в підкласах для створення конкретних об'єктів (продукти) , тоді як Abstract Factory
забезпечити інтерфейс для створення сімейства родинних продуктів і підкласу цього інтерфейсу визначає , як створити супутню продукцію.
Потім ці підкласи при інстанціюванні передаються в класи продуктів, де вони використовуються як абстрактний тип. Пов'язані продукти у програмі Abstract Factory
часто реалізуються за допомогою Factory Method
.
Розширення відповіді Джона Фемінелла:
Apple
, Banana
, Cherry
Інвентар FruitFactory
та що є метод , званий , Create
який несе відповідальність створення компанії Apple або банана або вишні. Ви закінчили, зі своїм Factory
методом.
Тепер, ви хочете, щоб Create
спеціальний салат з ваших фруктів, і там виходить ваша абстрактна фабрика . Абстрактна фабрика знає, як створити свій спеціальний салат із яблук, бананів та вишні.
public class Apple implements Fruit, FruitFactory {
public Fruit Create() {
// Apple creation logic goes here
}
}
public class Banana implements Fruit, FruitFactory {
public Fruit Create() {
// Banana creation logic goes here
}
}
public class Cherry implements Fruit, FruitFactory {
public Fruit Create() {
// Cherry creation logic goes here
}
}
public class SpecialSalad implements Salad, SaladFactory {
public static Salad Create(FruitFactory[] fruits) {
// loop through the factory and create the fruits.
// then you're ready to cut and slice your fruits
// to create your special salad.
}
}
За визначенням ми можемо перетягнути два відмінності:
Фабрика: Інтерфейс використовується для створення об'єкта, але підклас визначає, який клас інстанціювати. Створення об’єкта робиться тоді, коли це потрібно.
Абстрактна фабрика: абстрактний заводський зразок діє як суперфабрика, яка створює інші заводи. У шаблоні абстрактних заводів інтерфейс відповідає за створення набору пов’язаних об'єктів або залежних об'єктів без конкретизації їх конкретних класів.
Отже, у наведених вище визначеннях ми можемо наголосити на певній різниці. тобто заводський зразок відповідає за створення об'єктів, а абстрактний завод відповідає за створення набору суміжних об'єктів; очевидно, як через інтерфейс.
Заводський зразок:
public interface IFactory{
void VehicleType(string n);
}
public class Scooter : IFactory{
public void VehicleType(string n){
Console.WriteLine("Vehicle type: " + n);
}
}
public class Bike : IFactory{
public void VehicleType(string n) {
Console.WriteLine("Vehicle type: " + n);
}
}
public interface IVehicleFactory{
IFactory GetVehicleType(string Vehicle);
}
public class ConcreteVehicleFactory : IVehicleFactory{
public IFactory GetVehicleType(string Vehicle){
switch (Vehicle){
case "Scooter":
return new Scooter();
case "Bike":
return new Bike();
default:
return new Scooter();
}
}
class Program{
static void Main(string[] args){
IVehicleFactory factory = new ConcreteVehicleFactory();
IFactory scooter = factory.GetVehicleType("Scooter");
scooter.VehicleType("Scooter");
IFactory bike = factory.GetVehicleType("Bike");
bike.VehicleType("Bike");
Console.ReadKey();
}
}
Абстрактний заводський візерунок:
interface IVehicleFactory{
IBike GetBike();
IScooter GetScooter();
}
class HondaFactory : IVehicleFactory{
public IBike GetBike(){
return new FZS();
}
public IScooter GetScooter(){
return new FZscooter();
}
}
class HeroFactory: IVehicleFactory{
public IBike GetBike(){
return new Pulsur();
}
public IScooter GetScooter(){
return new PulsurScooter();
}
}
interface IBike
{
string Name();
}
interface IScooter
{
string Name();
}
class FZS:IBike{
public string Name(){
return "FZS";
}
}
class Pulsur:IBike{
public string Name(){
return "Pulsur";
}
}
class FZscooter:IScooter {
public string Name(){
return "FZscooter";
}
}
class PulsurScooter:IScooter{
public string Name(){
return "PulsurScooter";
}
}
enum MANUFACTURERS
{
HONDA,
HERO
}
class VehicleTypeCheck{
IBike bike;
IScooter scooter;
IVehicleFactory factory;
MANUFACTURERS manu;
public VehicleTypeCheck(MANUFACTURERS m){
manu = m;
}
public void CheckProducts()
{
switch (manu){
case MANUFACTURERS.HONDA:
factory = new HondaFactory();
break;
case MANUFACTURERS.HERO:
factory = new HeroFactory();
break;
}
Console.WriteLine("Bike: " + factory.GetBike().Name() + "\nScooter: " + factory.GetScooter().Name());
}
}
class Program
{
static void Main(string[] args)
{
VehicleTypeCheck chk = new VehicleTypeCheck(MANUFACTURERS.HONDA);
chk.CheckProducts();
chk= new VehicleTypeCheck(MANUFACTURERS.HERO);
chk.CheckProducts();
Console.Read();
}
}
Перевірте тут: http://www.allapplabs.com/java_design_patterns/ab абстракт_factory_pattern.htm Здається, що метод Factory використовує певний клас (не абстрактний) як базовий клас, тоді як абстрактна фабрика використовує для цього абстрактний клас. Також якщо використовувати інтерфейс замість абстрактного класу, результатом буде інша реалізація шаблону абстрактних заводів.
: D
Abstract Factory - це шаблон для створення інтерфейсів різного типу. Припустимо, у вас є проект, який вимагає розбору різних типів CSV-файлів, що містять кількість, ціну та специфічну інформацію, наприклад, деякі містять дані про фрукти, інші про шоколадні цукерки, а потім після розбору вам потрібно оновити цю інформацію у відповідній базі даних, щоб тепер ви могли мати одна абстрактна фабрика повертає вам фабрику парсерів і модифікаторів, а потім ця фабрика розбору може повернути вам об'єкт парсерів шоколаду, об'єкт парсерів фруктів тощо тощо. Фабрика модифікаторів аналогічно може повернути об'єкт модифікатора шоколаду, об'єкт модифікатора фруктів тощо.
Я думаю, що ми можемо зрозуміти різницю між цими двома, побачивши приклад Java8:
interface Something{}
interface OneWhoCanProvideSomething {
Something getSomething();
}
interface OneWhoCanProvideCreatorsOfSomething{
OneWhoCanProvideSomething getCreator();
}
public class AbstractFactoryExample {
public static void main(String[] args) {
//I need something
//Let's create one
Something something = new Something() {};
//Or ask someone (FACTORY pattern)
OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeA = () -> null;
OneWhoCanProvideSomething oneWhoCanProvideSomethingOfTypeB = () -> null;
//Or ask someone who knows soemone who can create something (ABSTRACT FACTORY pattern)
OneWhoCanProvideCreatorsOfSomething oneWhoCanProvideCreatorsOfSomething = () -> null;
//Same thing, but you don't need to write you own interfaces
Supplier<Something> supplierOfSomething = () -> null;
Supplier<Supplier<Something>> supplierOfSupplier = () -> null;
}
}
Тепер питання в тому, який спосіб створення слід використовувати і чому: Перший спосіб (без шаблону, просто звичайний конструктор): створення самостійно - це не дуже гарна ідея, ви повинні виконати всю роботу, і ваш клієнтський код прив’язаний до конкретна реалізація.
Другий спосіб (використовуючи заводський зразок): надає вам перевагу, що ви можете пройти будь-який тип реалізації, який може забезпечити різний тип чогось на основі певної умови (можливо, параметр, переданий методу Creative).
Третій спосіб (використовуючи абстрактний заводський візерунок): це дає більше гнучкості. Ви можете знайти різні типи творців чогось на основі певної умови (можливо, пройшов параметр).
Зауважте, що ви завжди можете піти з фабричного шаблону, комбінуючи дві умови разом (що дещо збільшує складність коду та з'єднання), я думаю, тому ми рідко бачимо випадки використання реального життя з абстрактним фабричним малюнком.