1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| #include <cstdlib>
#include <ctime>
#include <iostream>
#include <typeinfo>
#include <unordered_map>
#include <sstream>
namespace std {
// Patch because MinGW doesn't know std::to_string()
// See http://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-g
template<typename T> std::string to_string(const T& n) {
std::ostringstream stm;
stm << n;
return stm.str();
}
}
//--- Service manager-----------------------------------------------
class Service {
// The purpose of this class is meant to have a common type for all service classes
// so that the ServiceManager can handle them
};
class ServiceHasher {
public:
unsigned long operator()(const std::type_info* info) const {
return (unsigned long) info;
}
};
class ServiceManager {
public:
template<class ServiceInterface>
void registerService(ServiceInterface* service) {
service_map[&typeid(ServiceInterface)] = service;
}
template<class ServiceInterface>
ServiceInterface& getService() {
return (ServiceInterface&) *service_map[&typeid(ServiceInterface)];
}
private:
std::unordered_map<const std::type_info*, Service*, ServiceHasher> service_map;
};
//--- Service interfaces--------------------------------------------
class PrinterService: public Service {
public:
virtual ~PrinterService() {
}
virtual void print(std::string) = 0;
};
class TemperatureService: public Service {
public:
virtual ~TemperatureService() {
}
virtual double getTemperature() = 0;
virtual std::string getUnit() = 0;
};
//--- Service implementations---------------------------------------
class StandardPrinter: public PrinterService {
public:
void print(std::string text) {
std::cout << text << std::endl;
}
};
class OutsideTemperature: public TemperatureService {
public:
double getTemperature(void) {
std::srand(std::time(0));
return (double) std::rand() + (double) std::rand() / 10;
}
std::string getUnit(void) {
return "°C";
}
};
//--- Application---------------------------------------------------
ServiceManager manager;
void init(void) {
// Create services
OutsideTemperature* temperature = new OutsideTemperature;
StandardPrinter* printer = new StandardPrinter;
// Register them
manager.registerService<TemperatureService>(temperature);
manager.registerService<PrinterService>(printer);
}
void run(void) {
TemperatureService& temperatureService = manager.getService<
TemperatureService>();
PrinterService& printerService = manager.getService<PrinterService>();
double temperature = temperatureService.getTemperature();
std::string unit = temperatureService.getUnit();
std::string message = std::to_string(temperature) + unit;
printerService.print(message);
}
int main(int argc, char **argv) {
init();
run();
} |