Patrón de diseño de fábrica de aprendizaje [cerrado] -- php campo con design-patterns camp codereview Relacionados El problema

Learning factory design pattern [closed]


0
vote

problema

Español
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas.

¿Quieres mejorar esta pregunta? Actualizar la pregunta por lo que es on-topic para el intercambio de pila de revisión de código.

CERRADO hace 6 meses .

Mejorar esta pregunta

Estoy haciendo el ejemplo común del patrón de diseño de fábrica que crea una fábrica de automóviles y devuelve una instancia de un automóvil. Encontré un ejemplo aquí https://refactoring.guru/design-patterns/factory/factory -Method / PHP / Ejemplo y decidió hacer mi propia fábrica. Mi pregunta es ¿Por qué necesito un creador para cada automóvil?

  <?php   interface Car {     public function drive(); }    
  <?php require_once('Car.php');  class Audi implements Car {     public function drive()     {         return "driving an Audi";     } }   
  <?php require_once('Car.php');  class Mercedes implements Car {      public function drive()     {        return "driving an Mercedes";     } }   
  <?php   abstract class CarFactory {     abstract public function factoryMethod(): Car;      public function someOperation(): string     {         // Call the factory method to create a Product object.         $product = $this->factoryMethod();         // Now, use the product.         $result = "I want to drive something..... " .             $product->drive();          return $result;     } }   
  <?php require_once('CarFactory.php'); require_once('Car.php'); require_once('Audi.php');  class AudiCreator extends CarFactory {      public function factoryMethod(): Car     {         return new Audi();     } }   
  <?php require_once('CarFactory.php'); require_once('Car.php'); require_once('Mercedes.php');  class MercedesCreator extends CarFactory {      public function factoryMethod(): Car     {        return new Mercedes();     } }   
  <?php  require_once('car/AudiCreator.php'); require_once('car/MercedesCreator.php');  function clientCode(CarFactory $carFactory) {     // ...     echo "Client: "         . $carFactory->someOperation();     // ... }  echo "The client . <br>"; clientCode(new AudiCreator()); echo "  "; echo  "<br>"; echo  "<br>";  clientCode(new MercedesCreator());   
Original en ingles

I'm making the very common example of Factory design pattern which creates a factory of cars and return an instance of a car. I found a example here https://refactoring.guru/design-patterns/factory-method/php/example and decided to make my own factory. My question is why do I need a Creator for each car?

<?php   interface Car {     public function drive(); }  
<?php require_once('Car.php');  class Audi implements Car {     public function drive()     {         return "driving an Audi";     } } 
<?php require_once('Car.php');  class Mercedes implements Car {      public function drive()     {        return "driving an Mercedes";     } } 
<?php   abstract class CarFactory {     abstract public function factoryMethod(): Car;      public function someOperation(): string     {         // Call the factory method to create a Product object.         $product = $this->factoryMethod();         // Now, use the product.         $result = "I want to drive something..... " .             $product->drive();          return $result;     } } 
<?php require_once('CarFactory.php'); require_once('Car.php'); require_once('Audi.php');  class AudiCreator extends CarFactory {      public function factoryMethod(): Car     {         return new Audi();     } } 
<?php require_once('CarFactory.php'); require_once('Car.php'); require_once('Mercedes.php');  class MercedesCreator extends CarFactory {      public function factoryMethod(): Car     {        return new Mercedes();     } } 
<?php  require_once('car/AudiCreator.php'); require_once('car/MercedesCreator.php');  function clientCode(CarFactory $carFactory) {     // ...     echo "Client: "         . $carFactory->someOperation();     // ... }  echo "The client . <br>"; clientCode(new AudiCreator()); echo "\r\n"; echo  "<br>"; echo  "<br>";  clientCode(new MercedesCreator()); 
     
   
   

Lista de respuestas

3
 
vote
vote
La mejor respuesta
 

Creo que estás pensando en esto hacia atrás. El punto no es que necesite definir subclases especiales para usar el método de fábrica. Más bien, cuando necesita definir subclases especiales que contengan su propia funcionalidad compleja, use el método de fábrica.

de la pandilla de cuatro :

Utilice el patrón de método de fábrica cuando una clase no puede anticipar la clase de objetos que debe crear, [o] quiere que sus subclases especifiquen las clases que crea [...].

Creo que parte del problema es que su propio ejemplo es un poco confuso. Las interfaces son más para definir cosas, los objetos diferentes pueden . A menudo, escuchará a las personas que describan una interfaz como una especie de contrato, ya que se requiere ningún objeto que implemente una interfaz para implementar cada función de esa interfaz. Un Car se definiría más lógicamente como una clase porque un Audi y un BMW son un tipo de . Por otro lado, podría tener sentido definir una interfaz 9988776665544331 , implementado por un extracto Vehicle clase.

  interface Drivable {     public function drive(); }   

Puede definir clases de base abstracta para cada una de las clases de objetos de base genéricos que implementan esta interfaz.

  abstract class Vehicle implements Drivable {     abstract public function drive(); }   

Una vez que lo haga, puede implementar la funcionalidad para cada objeto.

  abstract class Car extends Vehicle {     abstract public function drive(); }  class Audi extends Car {     public function drive()     {         //...     } }  abstract class Aircraft extends Vehicle {     abstract public function drive(); }  class Airbus extends Aircraft {     public function drive()     {         // ...     } }   

Mantenerse con la naturaleza literal de su ejemplo, piense en lo diferente que es una fábrica de aeronaves y una fábrica de automóviles. Ambos son fábricas que hacen vehículos, seguramente, (por lo que sus fábricas respectivas podrían, y probablemente se derivarán de la misma base abstracta VehicleFactory clase) Pero el proceso de construcción de un avión es tan diferente de la de construir un automóvil que usted tiene para definir subclases especiales de fábrica para cada uno de ellos.

Acepcionemos más específicos, avístelemos por qué y cuándo usaría una fábrica. Supongamos que estás escribiendo un juego donde un jugador puede comprar un automóvil. ¿Cómo sabes qué automóvil desea crear una instancia hasta que el usuario lo seleccione?

Un simple script podría hacer algo así.

  $car = null;  switch ($choice) {     case 'BMW': {         $car = new BMW();     } break;      case 'Audi': {         $car = new Audi();     } break;      ... }  $car->drive();   

Este es todo el patrón de fábrica. La diferencia es que una clase real de fábrica le brinda varios beneficios que este simple script no.

En primer lugar, considere una clase 99887766655443388 que replica la funcionalidad de la secuencia de comandos anteriores.

  class CarFactory {     public static function create($car) : Car     {         switch ($car)         {             case 'BMW': return new BMW();             case 'Audi': return new Audi();             // ...         }     } }  $car = CarFactory::create($choice); $car->drive();   

Justo al lado del bate, no necesita 99887766555443310 como el valor de Sentinel para "El usuario aún no ha elegido un automóvil". El auto aún no existe, por lo que la variable de automóvil aún no existe.

segundo, un script no puede heredar o derivarse de nada; simplemente es. En contraste, si quisiera que su jugador también pueda comprar un 998877666554433111 , o cualquier tipo de transporte derivado de la clase 99887766655443312 , puede definir una base Drivable3 Clase de la cual puede implementar su Drivable4 y Drivable5 Clases.

  Drivable6  

Esperemos que esto le dé una idea de por qué el patrón de fábrica es útil. El resultado es que su clase de fábrica base define la interfaz por la cual los usuarios solicitarán un objeto, y las subclases de fábrica se encargarán de la definición real de cómo sucede. Además, definiendo el tipo de devolución de cada fábrica en términos de un objeto base (es decir, el 99887766555443317 devuelve un 99887766655443318 ) nos permite elegir la subclase real de ese objeto que En realidad, se crea en tiempo de ejecución (los usuarios pueden elegir un 99887776655443319 o un 99887766555443320 , ambos son Vehicle1 , todos los cuales son Vehicle2 , todos los cuales son Vehicle3 ).

 

I think you're thinking of this backwards. The point isn't that you need to define special subclasses to use the factory method. Rather, when you need to define special subclasses containing their own complex functionality, then you use the factory method.

From the Gang of Four:

Use the Factory Method pattern when a class can't anticipate the class of objects it must create, [or it] wants its subclasses to specify the classes it creates [...].

I think part of the problem is that your own example is a bit confusing. Interfaces are more for defining things different objects can do. You'll often hear people describe an interface as a sort of contract, because any object that implements an interface is required to implement every function of that interface. A Car would be more logically defined as a class because an Audi and a BMW are a type of car. On the other hand, it might make sense to define a Drivable interface, implemented by an abstract Vehicle class.

interface Drivable {     public function drive(); } 

You could then define abstract base classes for each of the generic base object classes that implement this interface.

abstract class Vehicle implements Drivable {     abstract public function drive(); } 

Once you do that, then you can implement functionality for each object.

abstract class Car extends Vehicle {     abstract public function drive(); }  class Audi extends Car {     public function drive()     {         //...     } }  abstract class Aircraft extends Vehicle {     abstract public function drive(); }  class Airbus extends Aircraft {     public function drive()     {         // ...     } } 

Keeping with the literal nature of your example, think about how different an aircraft factory and a car factory are. They're both factories that make vehicles, sure, (which is why their respective factories could -and probably would- be derived from the same base abstract VehicleFactory class) but the process of building an aircraft is so different from that of building a car that you have to define special factory subclasses for each of them.

Getting more specific, let's focus on why and when you would use a factory. Suppose you're writing a game where a player can purchase a car. How do you know which car to instantiate until the user picks it?

A simple script might do something like this.

$car = null;  switch ($choice) {     case 'BMW': {         $car = new BMW();     } break;      case 'Audi': {         $car = new Audi();     } break;      ... }  $car->drive(); 

This is all the factory pattern is. The difference is that an actual factory class gives you several benefits that this simple script doesn't.

First of all, consider a CarFactory class that replicates the above script's functionality.

class CarFactory {     public static function create($car) : Car     {         switch ($car)         {             case 'BMW': return new BMW();             case 'Audi': return new Audi();             // ...         }     } }  $car = CarFactory::create($choice); $car->drive(); 

Right off the bat, you don't need null as the sentinel value for "the user hasn't picked a car yet." The car doesn't exist yet, so the car variable doesn't exist yet.

Second, a script can't inherit or be derived from anything; it just is. In contrast, if you wanted your player to also be able to purchase an Aircraft, or any kind of transport derived from the Vehicle class, you can define a base VehicleFactory class from which you can implement your CarFactory and AircraftFactory classes.

interface Build {     public static function build($choice); }  abstract class VehicleFactory implements Build {     abstract public static function build($choice) : Vehicle; }  class AircraftFactory extends VehicleFactory {     public static function build($aircraft) : Aircraft     {         switch ($aircraft)         {             case 'Airbus': return new Airbus();             case 'Boeing': return new Boeing();             // ...         }     } }  class CarFactory extends VehicleFactory {     public static function build($car) : Car     {         switch ($car)         {             case 'BMW': return new BMW();             case 'Audi': return new Audi();             // ...         }     } }  $aircraft = AircraftFactory::build($choice); $aircraft->drive();  $car = CarFactory::build($choice); $car->drive(); 

Hopefully this gives you an idea of why the factory pattern is useful. The upshot is that your base factory class defines the interface by which users will request an object be created, and the factory subclasses take care of the actual definition for how it happens. In addition, defining each factory's return type in terms of a base object (i.e..., the CarFactory returns a Car) allows us to choose the actual subclass of that object that actually gets created at runtime (users can pick a BMW or an Audi, both of which are Cars, all of which are Vehicles, all of which are Drivable).

 
 
   
   

Relacionados problema

5  Controlador MVC en Java Swing Apps - Singleton o estático público  ( Mvc controller in java swing apps singleton or public static ) 
Este artículo me ha dejado un poco confundido. Al explicar un método sobre cómo diseñar MVC en las aplicaciones de Java Swing, el autor define la clase de...

2  Implementación de SCPI para el control de instrumentos de prueba  ( Implementation of scpi for control of test instruments ) 
trabajo con equipos de prueba electrónicos. Me gusta poder automatizar las pruebas utilizando sus interfaces de control remoto. He construido un patrón, algun...

11  Patrones compuestos y de visitantes para la funcionalidad de la encuesta basada en árboles en C #  ( Composite and visitor patterns for tree based survey functionality in c ) 
He escrito alguna funcionalidad de encuesta para un proyecto. Básicamente, un formulario de encuesta genérico que se puede componer de secciones y preguntas. ...

0  Sistema de gestión de la biblioteca en C ++  ( Library management system in c ) 
Estoy haciendo un proyecto de principiante C ++ y es simplemente un sistema de administración de la biblioteca donde contratará un estudiante, devolver un lib...

2  Patrón abstracto de fábrica para implementar adtetworks en múltiples plataformas [cerradas]  ( Abstract factory pattern for implementing adnetworks on multiple platforms ) 
cerrado. Esta pregunta es off-topic . Actualmente no está aceptando respuestas. ¿Quieres ...

3  Semilla una base de datos  ( Seed a database ) 
Estoy buscando consejos / mejores prácticas para evitar hacer un conjunto profundo anidado de IF / 99887766555443333 en Rails. La intención es sembrar una...

5  Implementar un programador de empleo que toma en una función f y un entero n, y llama F después de N milisegundos  ( Implement a job scheduler which takes in a function f and an integer n and call ) 
public static void main(String args[]) { solution(new Command() { @Override public void execute() { { ...

9  Ejecución de funciones y declarando banderas con una batería larga de las condiciones  ( Executing functions and declaring flags with a long battery of if conditions ) 
Solo estoy preguntando porque casi toda la base de código que he heredado aquí, en C # y PHP, se ve así: if (varOne == flag) { run_some_sql(); set_...

0  Comentarios sobre la implementación lógica de la galería de imágenes basadas en PYQT4 utilizando QTableView  ( Feedback on logic implementation of pyqt4 based image gallery using qtableview ) 
He realizado una solicitud para mostrar imágenes en forma de galería, desde la terminal, si está parado en la misma ubicación, entonces abrirá esas imágenes e...

4  ¿Qué patrón elegir para pasar alertas del método de servicio Volver al usuario?  ( Which pattern to choose for passing alerts from service method back to user ) 
Considerando la muestra de código a continuación, ¿qué enfoque del diseño del método de servicio se consideraría mejor práctica y por qué? ¿ONO UTILIZADO EN ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos