P
P
Phoen1xx2019-10-22 17:11:24
PHP
Phoen1xx, 2019-10-22 17:11:24

What is the difference between 'factory method' and 'simple factory'?

Hello, I would like to know what is the difference between these two patterns. Judging by the code examples written from the examples from the java site :

<?php
abstract class IMobile{}
class Nokia extends IMobile{}
class IPhone extends IMobile{}

Simple factory:
<?php
class MobileFactory{
   public function getMobile( $type ){
      if( $type === 'nokia' ){
         return new Nokia();
      } else if( $type === 'iphone' ) {
         return new IPhone();
      }
   }
}

factory method:
<?php
abstract class IMobileFactory{
   abstract public function getMobile();
}
class NokiaFactory extends IMobileFactory{
   public function getMobile(){
      return new Nokia();
   }
}
class IPhoneFactory extends IMobileFactory{
   public function getMobile(){
      return new IPhone();
   }
}

It turns out that the difference between these two patterns is only in their call?
<?php
(new MobileFactory())->getMobile('nokia');
(new NokiaFactory())->getMobile();

There can't be two different patterns, and the only difference between them is just a call

Answer the question

In order to leave comments, you need to log in

3 answer(s)
A
Adamos, 2019-10-22
@Adamos

In your example, the only purpose of the factory class is to create subclasses within a single method.
And classes with a factory method can do their own thing PLUS they can return themselves in a uniform way for all of them. Moreover, this same getMobile method can at the same time participate in other methods of the same class when it needed to create a clone, for example.
The biggest difference, in fact, will not even be in the code of these classes or factories, but in the code that uses this or that pattern from the outside. With a factory, you have to create all the heirs in one place and be aware of them. With a factory method, they can come from anywhere, and all you need to know about them is that they implement the same factory method.
Patterns are not about classes, but about the interaction between them and the reduction of cohesion.

R
rundle, 2019-10-23
@rundle

Hello.
The website example is wrong. It doesn't show the expressiveness of a factory method as opposed to a factory. I have modified the example below.
A simple factory is not a design pattern, it's more of a programming idiom. A simple factory provides an interface for creating a single product. The difference of a factory method is to create a set of classes that create instances - concrete classes extend a class with a factory method.
One of the principles of design is to isolate what changes and separate from what remains constant. All patterns provide, to some extent, the ability to change some part of the system independently of other parts.
For example, we opened a phone shop in Moscow and St. Petersburg, and the BeelineStore class has common methods for all phones (the java code is sketchy). Samsung began to support 5G Internet, so we will make the tariff for these phones more expensive.

spoiler
abstract class IMobile {
  void prepare() {
    System.out.println("Подготовим документы по продаже от ООО Билайн");
  }
  void setInternetTariff() {
    System.out.println("Установим стандартный тариф Билайна для интернета");
  }
  void box() {
    System.out.println("Упакуем в желтый пакетик");
  }
}

class BeelineSamsung extends IMobile {
  void setInternetTariff() {
    System.out.println("Установим отдельный тариф для 5G интернета");
  }
}

class BeelineIPhone extends IMobile {}

class BeelineStore {
  public IMobile orderPhone(String type) {
    IMobile phone = null;

    if (type.equals("samsung")) {
      phone = new BeelineSamsung();
    } else if (type.equals("iphone")) {
      phone = new BeelineIPhone();
    }

    phone.prepare();
    phone.setInternetTariff(); 
    phone.box();

    return phone;
  }
}

// использование
// var mobileStore = new BeelineStore();
// mobileStore.orderPhone("samsung"); <- клиентский код

However, when changing, deleting or adding new types of phones, we would open our BeelineStore class and extend it with new concrete types. And if we add phone models, then the condition tree will become more complicated. If some aspects of the system change, while others remain unchanged, it's time to start encapsulating.
spoiler
class MobileFactory {
  public IMobile getMobile(String type) {
    if (type.equals("samsung")) {
      return new BeelineSamsung();
    } else if (type.equals("iphone")) {
      return new BeelineIPhone();
    }

    return null;
  }
}

class BeelineStore {
  MobileFactory factory;

  public BeelineStore(MobileFactory factory) {
    this.factory = factory;
  }

  public IMobile orderPhone(String type) {
    IMobile phone;

    phone = factory.getMobile(type);

    phone.prepare(); 
    phone.setInternetTariff();
    phone.box();

    return phone;
  }
}
// использование 
// var mobileFactory = new MobileFactory();
// mobileStore = new BeelineStore(mobileFactory);
// mobileStore.orderPhone("samsung"); <- замечу, клиентский код не изменился

Okay - we took out the process of creating phones - this is the factory. And here we are expanding, things have gone well in our company and we are opening branches in the Urals. Tariffs in the Urals will be cheaper, both standard and for 5G Internet. And also in Moscow and St. Petersburg, a program is being launched to exchange old phones for new ones. This is where the factory method comes in handy.
spoiler
abstract class BeelineStore { // класс становится абстрактным
  protected abstract IMobile getMobile(String type); // возвращается метод getMobile

  public IMobile orderPhone(String type) {
    IMobile phone = getMobile(type);

    phone.prepare(); 
    phone.setInternetTariff();
    phone.box(); 

    return phone;
  }
}

class CenterBeelineSamsung extends IMobile {
  void setInternetTariff() {
    System.out.println("Отдельный тариф для 5G интернета в центре России");
  }
}

class CenterBeelineIPhone extends IMobile {}

class СenterBeelineStore extends BeelineStore {
  public IMobile getMobile(String type) {
    if (type.equals("samsung")) {
      return new CenterBeelineSamsung();
    } else if (type.equals("iphone")) {
      return new CenterBeelineIPhone();
    }

    return null;
  }
  
  public void tradeIn(String phone) {
    System.out.println("Вы обменяли старый телефон на новый с доплатой");
  }
}

class UralBeelineSamsung extends IMobile {
  void setInternetTariff() {
    System.out.println("Отдельный тариф для 5G интернета на Урале");
  }
}

class UralBeelineIPhone extends IMobile {
  void setInternetTariff() {
    System.out.println("Отдельный тариф для стандартного интернета на Урале");
  }
}

class UralBeelineStore extends BeelineStore {
  public IMobile getMobile(String type) {
    if (type.equals("samsung")) {
      return new UralBeelineSamsung();
    } else if (type.equals("iphone")) {
      return new UralBeelineIPhone();
    }

    return null;
  }
}
// использование
// var centerBeelineStore = new СenterBeelineStore();
// centerBeelineStore.orderPhone("samsung");
// var uralBeelineStore = new UralBeelineStore();
// uralBeelineStore.orderPhone("samsung");

We were able to maintain the same ordering standards for all stores, and also added regional differences.
That is, the factory method is much more flexible. A simple factory is highly specialized, while a factory method leads to a framework where the implementation is chosen by subclasses.
A simple Factory encapsulates the creation of objects, but it lacks the flexibility of a factory method to change the products it creates.

X
xfg, 2019-10-22
@xfg

Factory method
The factory method relieves the client of the need to know about the process of creating specific objects. The client only depends on the factory method interface. The client using the factory method can create and work with any object that implements the IMobile interface.
Strictly speaking, there is no such pattern as a "simple factory" in GoF. But nevertheless, it came from somewhere and a similar piece of code was called a "simple factory", there is a mention of this in Wikipedia and that a complex process of creating an object can be encapsulated in this, for example, when it depends on the settings in the configuration file or on user input .
I don't see a pattern in a simple factory. I see noodles from branch statements. Instead, user input or config settings can be directly converted from branch statements into the name of the required factory method class and its object can be passed to the client, thus getting rid of spaghetti code in the form of a "simple factory".
It is impossible to say who invented the "simple factory" and why. What it says is spaghetti code. What is written in it can be solved in a more elegant way without a dump of branch statements.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question