mardi 23 juin 2015

Settings based instantiation of subclass objects with different parameters

I have probably basic problem that i cannot find a solution for. Let me give an example.

I am writing an application that uses RFID reader. There are different readers from different vendors each with different interface but all of them basicaly do the same - provide RFID code, so for me it is a good candidate to create base class RFIDReader and make logic not aware of different types:

class RFIDReader {
    virtual string getRFIDCode();
}

Subclasses will look like this:

class RFIDReader_RS485 : public RFIDReader{
    RFIDReader_RS485(string port, int address, int number_of_antennas);

    ...
}

class RFIDReader_Serial : public RFIDReader{
    RFIDReader_Serial(string port, int baudrate);

    ...
}

class RFIDReader_CAN : public RFIDReader{
    RFIDReader_CAN();

    ...
}

I use .ini file for configuration so ini settings for each of cases would look like this

//rs485
[RFIDReader]
type=rs485
port="/dev/tty1"
address=3
number_of_antennas=2

//serial
[RFIDReader]
type=serial
port="/dev/tty1"
baudrate=9600

//can
[RFIDReader]
type=can

Now, since I want my application to be not aware of what type of reader it uses I would like to create Factory Method to just return pointer to RFIDReader object. My question is - how i can pass the arguments to factory where all of RFID concrete class has different parameters. The only solution i found and looks clumsy for me is passing map as arguments:

RFIDReader *createRFIDReader(string type, map<string,string> arguments){
    if(type == "rs485"){
        int address = //conversion from arguments["address"]
        int number_of_antennas = //conversion from arguments["number of antennas"]
        return new RFIDReader_RS485(arguments["port"], address, number_of_antennas]);
    }
    if(type == "serial"){
        int boudrate = //conversion from arguments["baudrate"]
        return new RFIDReader_Serial(arguments["port"], baudrate);
    }
    if(type == "can"){
        return new RFIDReader_CAN();
    }
}

Is there any way to do it in more elegant way? Maybe Factory method is totaly wrong way to go?

Aucun commentaire:

Enregistrer un commentaire