Welcome, guest! Login / Register - Why register?
Psst.. new poll here.
Psst.. new forums here.
Microsoft is blocking us again (TY IP Reputation!) so just use oauth login instead. :)

Paste

Pasted as C++ by Somebody ( 15 years ago )
#include <iostream>
#include <limits>
#include <cmath>
/* "Конвейер обработки данных"
  источник --> стадия1 --> ... 
           --> стадияN --> потребитель
  передаются "объекты данных"
  Интерфейсы:
    "данные" -- IData
    "источник" -- ISource
    "потребитель" -- IConsumer

  стадия i -- источник для стадии i+1
           -- потребитель для стадии i-1
           -- реализует (наследует) одновременно
              ISource и IConsumer
*/
// интерфейсы
struct IData // интерфейс "данные"
{
  virtual ~IData() {}
  // создать копию в динамической памяти
  virtual IData* clone() const = 0;
  // сравнить на равенство
  virtual bool operator==(const IData &right;) const = 0;
  bool operator!=(const IData &right;) const
  {
    return !(*this == right);//!this->operator==(right)
  }
  // вывести содержимое в поток в текстовой форме
  virtual void write(std::ostream &os;) const = 0;
};

struct IConsumer // интерфейс "потребитель"
{
  virtual ~IConsumer() {}
  // потребить данные
  virtual void consume(IData *data) = 0;
};

struct ISource // интерфейс "источник"
{
  virtual ~ISource() {}
  // подключить потребителя, возвращает предыдущего
  virtual IConsumer* attach(IConsumer*) = 0;
  // сгенерировать данные и передать потребителю
  virtual void run() = 0;
};

// реализует только attach
class AbstractSource: public ISource
{
protected:
  IConsumer *consumer;
public:
  AbstractSource() // сначала consumer = 0
    : consumer(nullptr) {} // замена NULL

  IConsumer* attach(IConsumer *newConsumer)
  {
    IConsumer *oldConsumer = consumer;
    consumer = newConsumer;
    return oldConsumer;
  }
};

// потомки с функциональностью

struct Double: IData // wrapper (to wrap)
{
  double value;
  Double(double val = 0.0) // конструктор
    : value(val) {}        // value = 0 по умолчанию

  IData* clone() const
  {
    return new Double(value);
  }

  bool operator==(const IData &right;) const
  {
    if (auto p = dynamic_cast<const Double*>(&right;))
      return p->value == value;
    return false;
  }

  void write(std::ostream &os;) const
  {
    os << value << std::endl;
  }
};

struct Cout: IConsumer // пишет в cout
{
  void consume(IData *data)
  {
    data->write(std::cout);
    delete data;
  }
};

// читает double с cin, оборачивает в Double
struct DoublesFromCin: AbstractSource
{
  void run()
  {
    double value // set to "not a number" value
      = std::numeric_limits<double>::quiet_NaN();
    std::cin >> value;
    if (std::cin.eof())
      return;
    else if (std::cin.fail())
    {
      std::cin.clear();
      std::cin.ignore();
    }
    else if (consumer) // не нулевой => есть потребитель
      consumer->consume(new Double(value));
  }
};

class MyFormula
  : public AbstractSource, public IConsumer
{
  double fvalue;
public:
  void consume(IData *data)
  {
    if (auto p = dynamic_cast<Double*>(data))
      fvalue = std::log(1.0 + std::sin(p->value));
    delete data;
    run();
  }

  void run()
  {
    if (consumer) // не нулевой => есть потребитель
      consumer->consume(new Double(fvalue));
  }
};


int main()
{
  // сборка конвейера
  DoublesFromCin convCin;
  MyFormula convStage1;
  Cout convCout;
  convStage1.attach(&convCout;);
  convCin.attach(&convStage1;); // присоединить потребителя
  
  // прогонка конвейера
  for (; !std::cin.eof(); )
    convCin.run();
}

 

Revise this Paste

Your Name: Code Language: