какво е предимството на използването на шаблон на фабричен метод пред простата фабрика?

Чета за шаблон на фабричен метод и проста фабрика. оказва се Както мога да разбера, простата фабрика е достатъчна и не виждам случая на използване на фабричния метод шаблон. Моля, прочетете тази връзка, https://www.binpress.com/factory-design-pattern/ и ще задам въпросите си.

1) в проста фабрика казва, че е лошо, защото нарушава принципа отворен/затворен. Разбирам това, но във фабричния модел на метода това, което направи, все още нарушава принципа отворен/затворен.

if ('car'==$toyName) {
            $toy = new NyCar();
        } else if ('helicopter'==$toyName) {
            $toy = new NyHelicopter();
        }

Ако ще има нова игра за Ню Йорк, трябва да я добавим тук.

2) след като прочете връзката, преди действително да достигне до по-доброто решение, използва следния код. :

class NySimpleFactory {
    public function createToy($toyName) {
        $toy = null;

        if ('car'==$toyName) {
            $toy = new NyCar();
        } else if ('helicopter'==$toyName) {
            $toy = new NyHelicopter();
        }

        return $toy;
    }
}

class NyToysFactory {

    public $simpleFactory;

    public function __construct(SimpleFactory $simpleFactory) {
        $this->simpleFactory = $simpleFactory;
    }

    public function produceToy($toyName) {
        $toy = null;
        $toy = $this->simpleFactory->createToy($toyName);
        $toy->prepare();
        $toy->package();
        $toy->label();
        return $toy;
    }
}

Тогава се казва,

Разработчиците завършват бързо новия код и го предават на фабриките в САЩ. След две седмици телефонът започва да звъни в офиса на разработчиците, защото фабриката в Ню Йорк е имала производствени проблеми. Оказва се, че класът NyToysFactory е модифициран от разработчиците в отдалечения клон, защото персоналът не иска да извършва работа по опаковане и етикетиране. Те модифицираха produceToy(), като премахнаха функциите label() и package().

Изглежда, че Simple Factory няма да работи в този сценарий. Не искаме клоновете в САЩ да могат да променят функциите produceToy(). ProduceToy() трябва да се състои от набор от стандартни процедури и клоновете трябва да отговарят само за създаването на специфични за местоположение играчки. Ами ако могат да създадат абстрактен клас? А абстрактният клас, който те създават, ще има конкретен метод produceToy(), който ще имплементира набор от стандартни оперативни процедури, които всички клонове трябва да следват. Вътре в produceToy(), той извиква свой собствен абстрактен метод createToy(), за да получи клас играчка. По този начин createToy() може да капсулира създаването на обект и тъй като е абстрактен, делегира създаването на своите подкласове.

Въпросът е: а) Какво означава предаването на заводите в САЩ? b) или Не искаме клоновете в САЩ да могат да променят функциите produceToy(). те все още могат да променят функцията produceToy, каква разлика има изобщо дали не могат или могат да я променят? Просто не разбирам защо простата фабрика изобщо беше лоша за следния пример.

Няма нужда да четете за абстрактната фабрика на тази връзка


person Nika Kurashvili    schedule 19.11.2018    source източник


Отговори (1)


ТНЕГОВИЯТ КОД/ПРОБЛЕМ не осветлява абстрактната фабрика или фабричния метод. Решаването кой клас да се инстанцира чрез включване на параметър наистина е анти-модел, насърчаващ нарушаването на принципа отворено-затворено.

Абстрактна фабрика

Абстрактната фабрика цели налагането на семейство от свързани класове:

abstract class ToyFactory
+ createBear(): ToyBear
+ createElephant(): ToyElephant

class USToyFactory extends ToyFactory
+ createBear(): ToyBear -> creates USToyBear
+ createElephant(): ToyElephant -> USToyElephant

abstract class ToyBear
+ playSound()

class USToyBear extends ToyBear
+ playSound()//play US National Anthem

Преминаването на USToyFactory, където се очаква ToyFactory, налага създаването на американски играчки (USToyBear и USToyElephant). Това е силата на Abstract Factory.

Забележете, че продуктите, мечките, слоновете и т.н. са известни AoT (преди време).

Фабричен метод

Фабричният метод е свързан с отлагането на инстанцирането до подкласове.

abstract class Dashboard
+ createWidget(): Widget

abstract class Widget
+ config()

class StatsDashboard extends Dashboard
+ createWidget: Widget -> return new StatsWidget()

class StatsWidget extends Widget

Извикването на createWidget() връща Widget, но коя конкретна Widget да се върне трябва да бъде отложена за подкласове (StatsDashboard връща StatsWidget).

Забележете, че методите за създаване са декларирани нагоре в дървото на наследяването, но се изпълняват надолу в дървото на наследяването.

❧ Читател с набито око ще види, че методите на абстрактната фабрика приличат на методите на фабриката, съвпадение? не. Това е мястото, където се извлича името на фабричните методи (те изпълняват конкретен клас).

Объркването по отношение на фабриките в САЩ е валидно; това е лош избор на думи. Авторът намеква, че този код може да бъде предаден на фабрични работници, което е напълно без значение и объркващо по отношение на фабричните модели.


За да разрешите превключването по-горе, ще трябва да осъзнаете очевидното: всеки манипулатор на условия е свързан по някакъв начин. В този случай всички те са играчки.

public function createToy($toyName) {
    $toy = null;

    if ('car'==$toyName) {
        $toy = new NyCar();//I'm a Toy
    } else if ('helicopter'==$toyName) {
        $toy = new NyHelicopter();//I'm a Toy
    }

    return $toy;
}

Използвайки полиморфизъм, можем да удовлетворим принципа отворено-затворено, като създадем набор от родствени класове:

abstract class Toy
+ operate()

Car extends Toy

Helicopter extends Toy

some_toy.operate();

Добавянето към случаите на превключване не е нищо повече от създаване на друг братски клас.

Надявам се това да помогне!

person Rafael    schedule 19.11.2018
comment
Благодаря Рафаел. Нека поговорим за разликата между фабричния метод и обикновения фабричен метод. Мога да правя всичко с проста фабрика, защо изобщо да използвам шаблон на фабричен метод? - person Nika Kurashvili; 19.11.2018
comment
Фабричният метод е за отлагане на инстанциране на подкласове. Това е важно, когато създавате интерфейси, които създават обекти, но не могат да предвидят кои обекти ще бъдат създадени. - person Rafael; 19.11.2018
comment
Можем ли да го обсъдим в личен чат или нещо подобно? Научих много за този модел, но все още някак си ме обърква. Въпросите, които имам, ще отнемат много време тук. Благодаря предварително - person Nika Kurashvili; 19.11.2018
comment
Така че, вместо да използваме switch (if/else) и да оставим createToy да избере подкласа, трябва да предадем подкласа като аргумент и просто да оставим createToy да го инстанцира? - person papiro; 19.11.2018
comment
@Rafael Ако фабричният метод разчита на DI вместо някакъв параметър, предаден на превключвател като в простата фабрика, как се използва като фабрика, която може да произвежда различни продукти по време на изпълнение? Фабричният метод не използва ли някога превключвател или някаква контролна логика, за да реши кой proudct или product creator да инстанцира? Ако това е заровено в DI контейнер, как бихте направили този контейнер да връща различни типове екземпляри за един и същ интерфейс? - person Ε Г И І И О; 15.05.2020
comment
@ΕГИИИО Премахнах израза DI, тъй като беше объркващ. Фабричният метод обаче знае кой продукт да създаде само като бъде извикан чрез еднократно изпращане. - person Rafael; 15.05.2020
comment
@ΕГИІИО Да, контролната логика ще се изисква от клиента, за да реши кой клас (с фабричен метод) да инстанцира, но тази контролна логика абсолютно не трябва да бъде в никакви фабрични методи. Това проваля целта на шаблона за проектиране. - person Rafael; 15.05.2020
comment
@Rafael Хм, така че, ако го разбрах правилно, когато внедрявате фабричния метод, някак все още се нуждаете от проста фабрика (или подобен код) на клиента, за да завъртите нещата. Попадали ли сте на примерен код, показващ това свързване? вероятно минус частта DI? Фабричният метод ме спъва всеки път. - person Ε Г И І И О; 15.05.2020
comment
@ЕГИИИО Точно така. Имайте предвид, че това е само пример за полиморфизъм и нищо повече. Това е просто обичаен случай на използване на полиморфизъм, достоен за име. Основната идея на полиморфизма е да запази кода общ, по този начин многократно използваем, така че клиентите да не знаят с какво работят. Това ни позволява да избутваме конкретни решения на клиентите, така че да завършим с общо ядро ​​и малка конкретна обвивка (което е негенеричният аспект на кода). - person Rafael; 16.05.2020
comment
@ΕГИІИО Вие наистина искате значително генерично ядро; това означава, че получавате много повторна употреба. Освен това общият код може да бъде извлечен в библиотека. Подлагам на съмнение код, който има дебела неизползваема обвивка, защото, нека си признаем, повечето кодове правят едно и също нещо (повече или по-малко) и рядко нещо е толкова разграничено. - person Rafael; 16.05.2020
comment
@ΕГИІИО Това каза, че това не означава, че всичко, което може да бъде родово, трябва да бъде родово. Това би увеличило ненужно сложността, т.е. прекомерното инженерство. Зависи от целта, домейна и случая на използване, например какво е вероятно да се промени с течение на времето и т.н., и т.н., ... Повечето абстракции е по-добре да се отложат до момента, в който са необходими, т.е. да се въвеждат органично, при поискване , а не с нетърпение. - person Rafael; 16.05.2020