Patterns. The Abstract Factory pattern. Solving the problem of computer components

The Abstract Factory pattern (Abstract class factory). Solving the problem of computer components

This topic provides an example of solving a computer design problem using the Abstract Factory pattern. The solution is implemented in C++ (console application).


Contents


1. Task. Class requirements

Implement the Abstract Factory pattern to build a computer from components in accordance with Figure 1.

The Abstract Factory pattern. Solving the problem of building a computer

Figure 1. Solving the problem of building a computer using the Abstract Factory pattern. Class diagram

The program must use the following classes and their components.

 

  1. Abstract class IPCFactory. Serves as an interface to the OfficePcFactory and HomePcFactory classes.

In the class, implement abstract methods CreateBox(), CreateProcessor(), CreateMainBoard(), which respectively return a reference (pointers) to the types Box, Processor, MainBoard.

  1. The OfficePcFactory and HomePcFactory classes are inherited from the IPCFactory class. These classes implement the abstract methods CreateBox(), CreateProcessor(), CreateMainBoard().
  1. Abstract classes Box, Processor, MainBoard, which serve as interfaces for the classes BlackBox, SilverBox, ProcessorIntel, ProcessorAMD, MainBoardIntel, MainBoardAMD.

The following elements are created in each of the classes Box, Processor, MainBoard:

  • internal hidden (private) field info of type string, describing information about the system unit, processor or motherboard;
  • access methods Get(), Set() for the info field;
  • Print() method – displays information about the contents of the info field.
  1. The SilverBox and BlackBox classes describe a system block that is gray and black, respectively. Both classes implement the Box interface.

Each class must implement at least one constructor that will call the constructor of the base class Box.

  1. The ProcessorIntel, ProcessorAMD classes implement specific processors. The classes are inherited from the abstract Processor class. The classes must implement a constructor that calls the constructor of the Processor base class.
  1. The MainBoardIntel and MainBoardAMD classes implement the MainBoard interface. Each class must have a constructor that calls the constructor of the MainBoard base class.
  1. The PcConfigurator class is responsible for configuring a PC type object with a given family (office configuration or home configuration).

The class must implement the following elements:

  • internal field pcFactory – pointer to the abstract class IPcFactory;
  • constructor without parameters – initializes pcFactory with a zero value;
  • access methods GetPcFactory() and SetPcFactory(IPCFactory*);
  • GetPC(int numConfiguration) method. Based on the configuration number (1-2), creates a computer (PC class) and returns a reference (pointer) to it. When creating a computer, the corresponding factory is accessed using the pcFactory field.
  1. The PC class is the result obtained from the GetPC() function of the PcConfigurator class. The class must implement the following elements:
  • internal fields box, processor, mainBoard, which are pointers to the abstract classes Box, Processor, MainBoard;
  • constructor without parameters – initializes internal fields with nullptr values;
  • PC(Box*, Processor*, MainBoard*) constructor – initializes internal fields with the values of pointers to real objects of the classes Box, Processor, MainBoard, respectively);
  • get/set type access methods: GetBox(), SetBox(Box*), GetProcessor(), SetProcessor(Processor*), GetMainBoard(), SetMainBoard(MainBoard*);
  • Print() method – displays information about the current configuration.

 

 2. Text of the program in C++

 

#include <iostream>
using namespace std;

// -----------------------------------------------
// Abstract components of a computer
// System block - abstract class
class Box abstract
{
private:
  string info; // information describing the system unit

public:
  Box(string _info = "Box") : info(_info)
  { }

  string Get() { return info; }
  void Set(string info) { this->info = info; }

  void Print(string msg)
  {
    cout << msg << " => " << info << endl;
  }
};

// Processor - abstract class
class Processor abstract
{
private:
  string info; // Processor description

public:
  Processor(string info = "Processor") : info(info)
  { }

  string Get() { return info; }
  void Set(string info)
  {
    this->info = info;
  }

  void Print(string msg)
  {
    cout << msg << " => " << info << endl;
  }
};

// Motherboard
class MainBoard abstract
{
private:
  string info;

public:
  MainBoard(string info = "MainBoard") : info(info)
  { }

  string Get() { return info; }
  void Set(string info) { this->info = info; }

  void Print(string msg)
  {
    cout << msg << " => " << info << endl;
  }
};

// ---------------------------------------------
// Classes of real devices.
// Gray system unit.
class SilverBox : public Box
{
public:
  SilverBox(string _info = "SilverBox") : Box(_info)
  { }
};

// The system unit is black
class BlackBox : public Box
{
public:
  BlackBox(string _info = "BlackBox") : Box(_info)
  { }
};

// Processor from Intel
class ProcessorIntel : public Processor
{
public:
  ProcessorIntel(string _info = "Processor Intel") :
    Processor(_info)
  { }
};

class ProcessorAMD : public Processor
{
public:
  ProcessorAMD(string _info = "Processor AMD") :
    Processor(_info)
  { }
};

class MainBoardIntel : public MainBoard
{
public:
  MainBoardIntel(string _info = "MainBoard Intel") :
    MainBoard(_info)
  { }
};

class MainBoardAMD : public MainBoard
{
public:
  MainBoardAMD(string _info = "MainBoard AMD") :
    MainBoard(_info)
  { }
};

// A class describing a computer and its components
class PC
{
private:
  Box* box;
  Processor* processor;
  MainBoard* mainBoard;

public:
  PC()
  {
    box = nullptr;
    processor = nullptr;
    mainBoard = nullptr;
  }

  PC(Box* box, Processor* processor, MainBoard* mainBoard)
  {
    this->box = box;
    this->processor = processor;
    this->mainBoard = mainBoard;
  }

  // Methods Get(), Set()
  Box* GetBox() { return box; }
  void SetBox(Box* _box) { box = _box; }
  Processor* GetProcessor() { return processor; }
  void SetProcessor(Processor* _processor) { processor = _processor; }
  MainBoard* GetMainBoard() { return mainBoard; }
  void SetMainBoard(MainBoard* _mainBoard) { mainBoard = _mainBoard; }

  // Display the current computer configuration
  void Print(string msg)
  {
    cout << msg << endl;
    if (box)
      box->Print("Box:");
    if (processor)
      processor->Print("Processor: ");
    if (mainBoard)
      mainBoard->Print("MainBoard: ");
    cout << "------------------------" << endl;
  }
};

// The interface for creating the configuration
// of the computer system unit is the factory interface
class IPCFactory abstract
{
public:
  virtual Box* CreateBox() = 0; // pure virtual function
  virtual Processor* CreateProcessor() = 0;
  virtual MainBoard* CreateMainBoard() abstract;
};

// Specific configurations.
// "Home" computer configuration:
// - system block - gray (SilverBox);
// - processor Intel - (ProcessorIntel);
// - motherboard Intel - (MainBoardIntel).
class HomePcFactory : public IPCFactory
{
public:
  // create a system block
  Box* CreateBox() override
  {
    return new SilverBox();
  }

  // create a processor
  Processor* CreateProcessor() override
  {
    return new ProcessorIntel();
  }

  MainBoard* CreateMainBoard() override
  {
    return new MainBoardIntel();
  }
};

// Office configuration
// - system block - black (BlackBox);
// - processor AMD - (Processor AMD);
// - motherboard - AMD - (MainBoard AMD).
class OfficePcFactory : public IPCFactory
{
public:
  // Create a system block
  Box* CreateBox() override
  {
    return new BlackBox();
  }

  // processor AMD
  Processor* CreateProcessor() override
  {
    return new ProcessorAMD();
  }

  // motherboard AMD
  MainBoard* CreateMainBoard() override
  {
    return new MainBoardAMD();
  }
};

// PcConfigurator class - is responsible for configuring a PC object with a given family
class PcConfigurator
{
  IPCFactory* pcFactory;

public:
  PcConfigurator()
  {
    pcFactory = nullptr;
  }

  IPCFactory* GetPCFactory()
  {
    return pcFactory;
  }

  void SetPCFactory(IPCFactory* pcCurrentFactory)
  {
    pcFactory = pcCurrentFactory;
  }

  // Get a computer based on configuration number
  // 1 - office configuration
  // 2 - home configuration
  PC* GetPC(int numConfiguration)
  {
    Box* box = nullptr;
    Processor* processor = nullptr;
    MainBoard* mainBoard = nullptr;

    if (numConfiguration == 1)
    {
      // office configuration
      pcFactory = new OfficePcFactory();
      box = (BlackBox*)pcFactory->CreateBox();
      processor = (ProcessorIntel*)pcFactory->CreateProcessor();
      mainBoard = (MainBoardIntel*)pcFactory->CreateMainBoard();
    }
    else
    {
      // home configuration
      pcFactory = new HomePcFactory();
      box = (SilverBox*)pcFactory->CreateBox();
      processor = (ProcessorAMD*)pcFactory->CreateProcessor();
      mainBoard = (MainBoardAMD*)pcFactory->CreateMainBoard();
    }

    return new PC(box, processor, mainBoard);
  }
};

void main()
{
  // 1. Enter the number of the configuration you want to receive
  int numConfiguration;
  cout << "numConfiguration = ";
  cin >> numConfiguration;

  // 2. Create a configurator
  PcConfigurator* configurator = new PcConfigurator();

  // 3. Get a computer by configuration number
  PC* computer = configurator->GetPC(numConfiguration);

  // 4. Display information about the received configuration
  computer->Print("Computer");

  // 5. Free memory
  Box* box = computer->GetBox();
  Processor* processor = computer->GetProcessor();
  MainBoard* mainBoard = computer->GetMainBoard();

  if (box)
    delete box;
  if (processor)
    delete processor;
  if (mainBoard)
    delete mainBoard;

  if (configurator)
    delete configurator;

  if (computer)
    delete computer;
}

 


Related topics