How can I use an implementation of an interface, only including the .hpp of the interface?

1

Main.cpp

#include <iostream>
#include "IWrittingDevice.hpp"
#include "IFactory.hpp"

int main(int argc, char const *argv[])
{
    IFactory* factory = 0;
    IWrittingDevice* device = factory->create(0);
    device->Write();

    delete device;
    delete factory;

    return 0;
}

IWrittingDevice.hpp

#pragma once 
struct IWrittingDevice {
    virtual void Write() = 0;
};

Pen.hpp

#pragma once 
#include "IWrittingDevice.hpp"

struct Pen : IWrittingDevice
{
    Pen();
    virtual ~Pen();

    virtual void Write();
};

Pen.cpp

#include "Pen.hpp"
#include <iostream>

Pen::Pen() { std::cout << "Constructor...\n";}

Pen::~Pen() { std::cout << "Destructor...\n";}

void Pen::Write() {
    std::cout << "Pen is wirtting...\n";
}

Roller.hpp

#pragma once 
#include "IWrittingDevice.hpp"

struct Roller : IWrittingDevice {
    Roller();
    virtual ~Roller();

    virtual void Write();
};

Roller.cpp

#include "Roller.hpp"
#include <iostream>

Roller::Roller() { std::cout << "Constructor...\n";}

Roller::~Roller() { std::cout << "Destructor...\n";}

void Roller::Write() {
    std::cout << "Roller is writting...\n";
} 

IFactory.hpp

#pragma once 
#include "IWrittingDevice.hpp"

struct IFactory {
    virtual IWrittingDevice* create(int) = 0;
};

PenFactory.hpp

#pragma once 
#include "IFactory.hpp"
#include "Pen.hpp"

struct PenFactory : IFactory {
    virtual IWrittingDevice* create(int a = 0);
};

PenFactory.cpp

#include "PenFactory.hpp"

IWrittingDevice* PenFactory::create(int a ) {
    return new Pen();
}

RollerFactory.hpp

#pragma once 
#include "IFactory.hpp"
#include "Roller.hpp"

struct RollerFactory : IFactory {
    virtual IWrittingDevice* create(int b = 1);
};

RollerFactory.cpp

#include "RollerFactory.hpp"

IWrittingDevice* RollerFactory::create(int b ) {
    return new Roller();
}
    
asked by Emanuel Clur 30.08.2018 в 14:23
source

1 answer

1

You have a concept error.

The interface you have to see it as a contract. All the classes that implement an interface have, necessarily, to implement the methods indicated in this interface.

So, the interface itself does not know what to do with the arguments that receive the functions it declares. That is what the classes that inherit from this interface will be commissioned.

So, you can not create an interface directly, but what you create is an object that inherits from the interface you need.

Well, one of the main utilities of the interfaces is that they reduce the coupling between classes. You no longer need to know what specific object you are using, but you are guided solely and exclusively by the list of functions indicated by the turn interface ... but we have the problem that someone, somewhere, has to take charge of creating the object real that should be used at all times.

A solution to this problem is found in the so-called factories. A factory is used to encapsulate the creation of different objects (usually objects with common inheritance, either base class or interface). So, the interface itself must know what object it has to create at each moment ... but it returns it under the appearance of the interface, then the consumer of the factory will not have any idea (nor does he need it) about the nature of the object returned by the factory:

struct ILog
{
  virtual ~ILog() = default;
  virtual void Escribir(std::string const& datos) = 0;
};

struct LogAConsola : ILog
{
  void Escribir(std::string const& datos) override
  { std::cout << datos << '\n'; }
};

struct LogSilenciado: ILog
{
  void Escribir(std::string const& /* datos */) override
  { std::cout << "Log silenciado\n"; }
};

class FactoriaLog
{
public:
  static void SilenciarLog(bool valor)
  { silenciar_ = valor; }

  static std::unique_ptr<ILog> CrearLog()
  {
    if( silenciar_ )
      return std::make_unique<LogSilenciado>();
    else
      return std::make_unique<LogAConsola>();
  }

private:

  static bool silenciar_;
};

bool FactoriaLog::silenciar_ = false;

Okay, and how do we use this factory? easy:

int main()
{
  FactoriaLog::SilenciarLog(false);

  std::unique_ptr<ILog> log = FactoriaLog::CrearLog();
  log->Escribir("Hola");

  FactoriaLog::SilenciarLog(true);
  log = FactoriaLog::CrearLog();

  log->Escribir("Hola");
}

That's right, notice that the factory does not inherit from any interface. If the factory inherited from an interface because we need to change factories, we would have to create a kind of factory of factories ... the design would be complicated for a while.

    
answered by 30.08.2018 в 15:32