1

I have an Engine class that has core logic, however there is a chance this class will be replaced by a third party engine with similar functionalities, so I want minimum impact to rest of the application.

I have another class called Adapter that allows simple interface with the Engine class and also provides some value-added functionality on top of the Engine class.

I then have another class called OrderProcessor that I want to expose to rest of the application that has a much simpler interface.

I want Engine and Adapter hidden from rest of the application and OrderProcesseor as the only interface for rest of the application.

How do I go about designing this and which access modifier to use where? Is there a design pattern that does it?

This is what I have but I don't think it's right.

//This is the core functionality. Might have to replace this class with a third //party implementation
//Want to hide it as much as possible
class Engine
{
private:
    char* ip;
    char* port;

protected:
    Engine();

    bool Connect();
    bool DisConnect();
    bool SendOrder(Message msg);
    bool CancelOrder (CancelMessage cxl);
    Message ReceiveOrder();
};


//This is an interface to the engine and provides value added functions
//Don't want this known to anyone except the OrderPRocessor
class Adapter : public Engine
{
private:
    int TotalAmount;
    double DollarAmount;

protected:
    bool Start(char*ip, char* port); //this will call Engine's connect() and do other things
    bool Stop (); //this will call Engine's Disconnect
    int TotalInventory();
    double TotalSales();
    double TotalCommission();    
};


//This class is the main interface to the rest of the application for order 
//processing related functionality.
class OrderProcessor 
{
public:
    OrderProcessor();
    ~OrderProcessor();
    Stats SendStats();
    ManageInventory();

private:
    Adapter adapter;
};
lorro
  • 4,949
  • 15
  • 25
bsobaid
  • 915
  • 1
  • 16
  • 30
  • Might be useful [Is the pImpl idiom really used in practice?](http://stackoverflow.com/questions/8972588/is-the-pimpl-idiom-really-used-in-practice) – lcs Feb 06 '17 at 19:46
  • `ip` should be `const char *` at least. Port, probably, int. –  Feb 06 '17 at 20:36

1 Answers1

1

Make Engine and Adapter private nested classes of OrderProcessor:

class OrderProcessor 
{
public:
    OrderProcessor();
    ~OrderProcessor();

    Stats SendStats();
    ManageInventory();

private:
    class Engine
    {
        // ...
    };

    class Adapter : public Engine
    {
        // ...
    };

    Adapter adapter;
};

If you want to more granular access limits, make 'key tags':

class OrderProcessor
{
public:
    class OpenSesame
    {
        friend ClassThatCanAccessTreasure;
    private:
        OpenSezame() {}; // = default is not sufficient
    };

    int AccessTreasure(int arg1, int arg2, OpenSesame key = {});
};

Note that in the above scheme you don't need to pass key, because it's defaulted. Since the default value is instantiated in caller context, only friends of OpenSesame can call AccessTreasure. This defaulting scheme works as long as you don't have varargs/parameter pack; if you do, you need to pass it before those and pass it manually.

lorro
  • 4,949
  • 15
  • 25