Napisałem taki kod:
#include "stdafx.h"
#include <iostream>
#include <memory>
#include <string>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cassert>
class IOutput
{
public:
virtual ~IOutput() {}
virtual void write(const char *str) = 0;
};
class Display : public IOutput
{
public:
void write(const char *str) override {std::cout << str << std::endl; };
};
class ISerial
{
public:
virtual ~ISerial() {};
virtual void read() = 0;
virtual int select() = 0;
};
class Serial : public ISerial
{
public:
Serial() { srand(static_cast<unsigned int>(time(NULL))); }
void read() override { std::cout << "Serial reading data" << std::endl; }
int select() override { return rand() % 2; }
};
class Manager : public std::enable_shared_from_this<Manager> {
private:
std::unique_ptr<ISerial> iserial_;
std::unique_ptr<IOutput> idisplay_;
void doStaff1(void)
{
idisplay_->write("Do some staff 1.");
}
void doStaff2(void)
{
idisplay_->write("Do some staff 2.");
}
void doStaff3(void)
{
idisplay_->write("Do some staff 3.");
}
void doStaff4(void)
{
idisplay_->write("Do some staff 1.");
}
public:
Manager(std::unique_ptr<ISerial> iserial, std::unique_ptr<IOutput> idisplay) : iserial_(std::move(iserial)), idisplay_(std::move(idisplay)) {}
void doJob();
void doComplex1()
{
doStaff3();
doStaff4();
}
void doComplex2()
{
doStaff4();
doStaff3();
}
};
class IWorker
{
private:
protected:
std::shared_ptr<Manager> manager_;
public:
IWorker(std::shared_ptr<Manager>manager) : manager_(manager) {}
virtual ~IWorker() {}
virtual void doIt() = 0;
virtual const char* getName() = 0;
static std::unique_ptr<IWorker> create(unsigned int type, std::shared_ptr<Manager>manager);
};
class Subworker1 : public IWorker
{
public:
Subworker1(std::shared_ptr<Manager> manager) : IWorker(manager) {}
void doIt() override { manager_->doComplex1(); }
const char* getName() override { return "Subworker 1"; }
};
class Subworker2 : public IWorker
{
public:
Subworker2(std::shared_ptr<Manager> manager) : IWorker(manager) {}
void doIt() override { manager_->doComplex2();}
const char* getName() override { return "Subworker 2"; }
};
std::unique_ptr<IWorker> IWorker::create(unsigned int type, std::shared_ptr<Manager>manager)
{
std::unique_ptr<IWorker> result;
switch(type)
{
case 0:
result = std::unique_ptr<IWorker>(new Subworker1(manager));
break;
case 1:
result = std::unique_ptr<IWorker>(new Subworker2(manager));
break;
}
return result;
}
void Manager::doJob()
{
doStaff1();
doStaff2();
// Wybieram podwykonawcę (który będzie używał narzędzi menagara). Przed wykonaniem doStaff1, doStaff2 nie wiem kogo będę potrzebował.
std::unique_ptr<IWorker> worker = IWorker::create(iserial_->select(), shared_from_this());
worker->doIt();
idisplay_->write(worker->getName());
}
int main(int argc, char * argv[])
{
std::shared_ptr<Manager> man = std::shared_ptr<Manager>(new Manager(std::unique_ptr<ISerial>(new Serial), std::unique_ptr<IOutput>(new Display)));
man->doJob();
return 0;
}
A teraz napiszę co chciałem zrobić:
- Obiekt klasy
Manager
ma zarządzać interfejsami; - W momencie utworzenia obiektu
Manager
nie wiemy jaki podwykonawca będzie nam potrzebny, ale potrzebny będzie max 1; - Liczba dostępnych rodzajów podwykonawców może ulec zmianie;
- Podwykonawcy wykonają prace metodami menagera;
- Chcę to osiągnąć przy możliwie najmniejszej liczbie klas;
Czyli podsumowując. Tworzę obiekt menagera, który po odebraniu informacji decyduje kogo zatrudnić, bo nie wie jak wykonywać pracę (ale dysponuje narzędziami).