简体   繁体   中英

what's the advantage of using factory method pattern over simple factory?

I am reading about factory method pattern and simple factory. turns out As I can understand, simple factory is enough and I don't see the use case of factory method pattern. Please read this link, https://www.binpress.com/factory-design-pattern/ , and I'll ask my questions.

1) in simple factory , it says it's bad because it violates the open/closed principle. I understand that but in factory method pattern what it did still violates the open/closed principle.

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

If there'll be a new tory for New York, we need to add it here.

2) after reading the link, before it actually reached the better solution, it used this following code. :

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;
    }
}

Then it says,

The developers finish the new code quickly and hand it over to the US factories. After two weeks, the phone starts ringing in the developers' office because the New York factory was having production issues. It turns out that the NyToysFactory class has been modified by developers at the remote branch because the staff doesn't want to do packaging and labeling work. They've modified produceToy() by removing its label() and package() functions.

It seems like Simple Factory won't work in this scenario. We don't want branches in US to be able to modify produceToy() functions. ProduceToy() should consist of a set of standard procedures and the branches should only be responsible for creating location specific toys. What if they can create an abstract class? And the abstract class they create will have a concrete produceToy()method which will implement a set of standard operating procedurea that all branches have to follow. Inside produceToy(), it calls its own abstract method createToy() to obtain a toy class. This way createToy() is able to encapsulate object creation and, since it's abstract, it delegates the creation to its subclasses.

Question is: a)What does it mean by saying handing over it to US factories? b) or We don't want branches in US to be able to modify produceToy() functions. they can still modify produceToy function, what difference does it make at all if they can't or can change it? I just don't understand why simple factory was bad for the following example at all.

No need to read about abstract factory at that link

T HIS CODE / PROBLEM does not illuminate the Abstract Factory or Factory Method. Deciding which class to instantiate by switching on a parameter is indeed an anti-pattern encouraging open-closed principle violation.

Abstract Factory

The Abstract Factory is all about enforcing a family of related classes:

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

Passing a USToyFactory where a ToyFactory is expected enforces the creation of US toys (USToyBear and USToyElephant) – this is the power of Abstract Factory.

Notice the products , bears, elephants, etc., are known AoT (ahead of time).

Factory Method

The Factory Method is all about deferring instantiation to subclasses.

abstract class Dashboard
+ createWidget(): Widget

abstract class Widget
+ config()

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

class StatsWidget extends Widget

Calling createWidget() returns a Widget, but which concrete Widget to return must be deferred to subclasses (StatsDashboard returns a StatsWidget).

Notice the creation methods are declared up the inheritance tree, but they are fulfilled down the inheritance tree.

❧ A reader with a keen eye will see that Abstract Factory methods resemble Factory Methods, coincidence? – no. This is where Factory Method's name is derived (they fulfill concrete class instantiation).

The confusion regarding “US factories” is valid; this is poor word choice. The author hints this code may be passed around to factory workers which is totally irrelevant and confusing pertaining to the factory patterns.


To resolve the switch above, you'll need to realize the obvious: each condition handler is related in some way. In this case, they are all toys.

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;
}

Using polymorphism, we can satisfy the open-closed principle by creating a set of sibling classes:

abstract class Toy
+ operate()

Car extends Toy

Helicopter extends Toy

some_toy.operate();

Adding to the switch cases is nothing more than creating another sibling class.

I hope this helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM