Método de fábrica C++

Jay Shaw 12 octubre 2023
  1. Método de fábrica en C++
  2. Clase de constructor simple en C++
  3. Use el método de fábrica para la clase de constructor en C++
  4. Clases concretas y métodos abstractos de fábrica en C++
Método de fábrica C++

El método de fábrica es un patrón de diseño de creación de objetos en C++ que se usa para crear objetos mientras se oculta su composición para que el usuario pueda usar la interfaz sin ver ninguna llamada de método.

Método de fábrica en C++

Las fábricas son constructores virtuales que permiten a un programador diseñar programas que permitan al usuario interactuar con una interfaz de programa limpia. Esto significa ocultar la creación de objetos dentro de la clase principal.

Si un programa tiene dos clases, una clase principal y una subclase de usuario, el uso del constructor hará que las dos clases sean altamente dependientes entre sí. Cualquier cambio inducido dentro de la clase principal dará lugar a cambios posteriores en las subclases.

La característica de Factories es la capacidad de indicar los objetos al comienzo del programa y abre la capacidad de agregar nuevos objetos, ya que todos los cambios necesarios se aplicarán solo dentro de la clase de biblioteca y no en ningún otro lugar.

Clase de constructor simple en C++

Código:

#include <iostream>
using namespace std;

// LIBRARY/PARENT(Wire_Sizes) CLASS WITH Two_mm and Four_mm sub-classes
class Wire_Sizes {
 public:
  virtual void Diameter() = 0;
};
class Two_mm : public Wire_Sizes {
 public:
  void Diameter() { cout << "This wire is 2mm in diameter" << endl; }
};
class Four_mm : public Wire_Sizes {
 public:
  void Diameter() { cout << "This wire is 4mm in diameter" << endl; }
};

// CLIENT(User) CLASS
// One thing to note here is that object creation takes place inside the User
// class, which can affect the whole program if changes are to be made to the
// parent class - like adding a new category of wire diameter.

// In this client class, adding a new type will mean adding a new category to
// the existing if-else ladder.
class User {
 public:
  User(int type) {
    // Client explicitly creates classes according to type
    if (type == 1)
      pDiameter = new Two_mm();
    else if (type == 2)
      pDiameter = new Four_mm();
    else
      pDiameter = NULL;
  }
  ~User() {
    if (pDiameter) {
      delete[] pDiameter;
      pDiameter = NULL;
    }
  }
  Wire_Sizes *getDiameter() { return pDiameter; }

 private:
  Wire_Sizes *pDiameter;
};

// MAIN FUNCTION
int main() {
  User *pClient = new User(2);
  Wire_Sizes *pDiameter = pClient->getDiameter();
  pDiameter->Diameter();
  return 0;
}

Producción :

This wire is 4mm in diameter

Ejecutar demostración en vivo

Wire_Sizes es la biblioteca o la clase principal con dos subclases, Two_mm y Four_mm, donde el método Diameter() está sobrecargado y devuelve una declaración de impresión cuando se llama al método.

En la clase Usuario, el tipo de parámetro toma el valor pasado de la función main() y crea una clase de objeto que coincide con el tipo de retorno. El ~User()(destructor) destruye los recursos asignados y borra el puntero.

La función main() crea el objeto *pClient mientras le pasa el valor 2. Este valor se pasará a la clase Usuario (cliente), que creará un objeto de tipo 2 y luego llamará al método correspondiente de tipo 2 de la clase Wire_Sizes (padre).

Esto hace que el programa dependa en gran medida de sus subclases y hace que el código sea intensivo. Las fábricas se utilizan para resolver este problema.

Use el método de fábrica para la clase de constructor en C++

Código:

#include <iostream>
using namespace std;

// The three derived classes, Size_two_mm, Size_three_mm, and Size_four_mm,
// contains the printDiameter() method, which is overloaded in all the
// subclasses
enum Size { Size_two_mm, Size_three_mm, Size_four_mm };
class Wire_Sizes {
 public:
  virtual void printDiameter() = 0;
  static Wire_Sizes* Create(Size type);
};
class Twomm : public Wire_Sizes {
 public:
  void printDiameter() { cout << "This wire is 2mm in diameter" << endl; }
};
class Threemm : public Wire_Sizes {
 public:
  void printDiameter() { cout << "This wire is 3mm in diameter" << endl; }
};
class Fourmm : public Wire_Sizes {
 public:
  void printDiameter() { cout << "This wire is 4mm in diameter" << endl; }
};

Wire_Sizes* Wire_Sizes::Create(Size type) {
  if (type == Size_two_mm)
    return new Twomm();
  else if (type == Size_three_mm)
    return new Threemm();
  else if (type == Size_four_mm)
    return new Fourmm();
  else
    return NULL;
}

class user {
 public:
  user() {
    Size type = Size_three_mm;
    pDiameter = Wire_Sizes::Create(type);
  }
  ~user() {
    if (pDiameter) {
      delete[] pDiameter;
      pDiameter = NULL;
    }
  }
  Wire_Sizes* getDiameter() { return pDiameter; }

 private:
  Wire_Sizes* pDiameter;
};

int main() {
  user* pClient = new user();
  Wire_Sizes* pDiameter = pClient->getDiameter();
  pDiameter->printDiameter();
  return 0;
}

Producción :

This wire is 3mm in diameter

Ejecutar demostración en vivo

Dentro de los datos de la enumeración Tamaño, escriba inicialmente tres objetos utilizados en el programa.

La condición if-else está escrita dentro de un nuevo constructor Create() justo después de la clase Wire_Sizes (biblioteca). Agregar un nuevo objeto es más fácil que cambiar la clase de cliente.

El constructor toma un valor usando el parámetro tipo y lo compara dentro de la escalera if-else. Se llama a la función correspondiente para una coincidencia positiva, y se devuelve NULL en caso de una coincidencia negativa.

La clase usuario no crea objetos explícitamente sino que pasa el tipo al método de fábrica Crear(). El objeto Tamaño_tres_mm se pasa a tipo y la clase constructora Crear() se asigna a pDiámetro usando el operador de asignación.

El ~user()(destructor) destruye el recurso asignado al final de la clase y asigna NULL a la variable pDiameter. Dentro del constructor getDiameter, se devuelve la variable pDiameter.

El método main() crea el objeto de la clase usuario *pClient y este objeto se denomina método pDiameter(). El método getDiameter() devuelve la variable pDiameter, que tiene el valor almacenado dentro del tipo.

La sintaxis Wire_Sizes * pDiameter = pClient->getDiameter(); pasar los valores del método getDiameter() a pDiameter que almacena NULL y se llama al método printDiameter().

Clases concretas y métodos abstractos de fábrica en C++

Cuando se declara un método o clase, se le conoce como clase abstracta por su incapacidad para devolver algo, y cuando se define ese método o clase, se le conoce como concreto. Las clases concretas se pueden instanciar y llamar según los requisitos dentro de una fábrica.

Código:

#include <iostream>
using namespace std;

// BASE CLASS
class Concrete_Example {
 public:
  virtual ~Concrete_Example() {}
  virtual std::string Operation() const = 0;
};
class ExampleProduct1 : public Concrete_Example {
 public:
  std::string Operation() const override {
    return "{Product 1 is instantiated}";
  }
};

class ExampleProduct2 : public Concrete_Example {
 public:
  std::string Operation() const override {
    return "{Product 2 is instantiated}";
  }
};

// CREATOR CLASS
class Create {
 public:
  virtual ~Create(){};
  virtual Concrete_Example* FactoryMethod() const = 0;
  std::string SomeOperation() const {
    Concrete_Example* concrete_Example = this->FactoryMethod();
    std::string result = "Client Code" + concrete_Example->Operation();
    delete concrete_Example;
    return result;
  }
};

class ExampleCreator1 : public Create {
 public:
  Concrete_Example* FactoryMethod() const override {
    return new ExampleProduct1();
  }
};

class ExampleCreator2 : public Create {
 public:
  Concrete_Example* FactoryMethod() const override {
    return new ExampleProduct2();
  }
};

// USER CLASS
void User(const Create& create) {
  std::cout << "User Method is called\n" << create.SomeOperation() << std::endl;
}

// MAIN FUNCTION
int main() {
  std::cout << "App: Launched with the ConcreteCreator1.\n";
  Create* create = new ExampleCreator1();
  User(*create);
  std::cout << std::endl;
  std::cout << "App: Launched with the ConcreteCreator2.\n";
  Create* create2 = new ExampleCreator2();
  User(*create2);

  delete create;
  delete create2;
  return 0;
}

Producción :

App: Launched with the ConcreteCreator1.
User Method is called
Client Code{Product 1 is instantiated}

App: Launched with the ConcreteCreator2.
User Method is called
Client Code{Product 2 is instantiated}

Ejecutar demostración en vivo

En este ejemplo, se crearán dos clases concretas dentro de una clase de fábrica y se observará cómo la fábrica llama a las clases. La clase Concrete_Example (base) proporciona muchas implementaciones para el producto y su interfaz.

La clase Concrete_Example tiene dos subclases: ExampleProduct1 y ExampleProduct2, que contienen los productos que la clase usuario quiere llamar. La siguiente es la clase Crear (creador) con una implementación específica: declarar el método de fábrica pasará un objeto de una clase de producto a la clase usuario.

Las subclases se crean para devolver el objeto e implementar los métodos para ese propósito. Aunque se crea el nombre de la clase, no se crean nuevos objetos en esta clase o sus subclases.

El objetivo principal de la clase Crear es devolver los productos del método de fábrica. Las subclases pueden anular el método y agregar una nueva implementación al producto.

Dentro del método SomeOperation, se crea un objeto del método de fábrica Concrete_Example, y el objeto se utiliza para implementar cambios en el producto. Se puede observar que las subclases infligen cambios en el producto anulando el método de fábrica.

El código de cliente que se usa aquí usa la instancia de la clase crear y sus subclases para llamar a los métodos, lo que lo hace independiente de la creación de objetos. Siguiendo la configuración o el entorno, la aplicación elige un tipo de creador.

La función principal usa classCreate para formar un objeto de la subclase ExampleCreator1(). Ambos métodos creadores se llaman en este programa utilizando objetos creados a partir de la clase Crear, y después de la implementación, todos los objetos creados se destruyen.

Artículo relacionado - C++ Method