class ITransportProvider
{
public:
virtual ~ITransportProvider() { }
protected:
virtual void SendData() = 0;
// Concrete TransportProvider will call OnReceiveDataEvent
// virtual void RegisterHandlers(std::function<void()> onReceiveDataEvent);
}
class Device
{
public:
Device(shared_ptr<ITransportProvider> transport)
: m_Transport(transport)
{
// transport->RegisterHandlers(boost::bind(&Device::OnReceiveData, this));
}
void SendData()
{
m_Transport->SendData();
}
// Which design pattern to use to get concrete TransportProvider's OnReceiveData event?
//void OnReceiveData()
//{
//}
private:
shared_ptr<ITransportProvider> m_Transport;
};
I've always added a "RegisterHandlers" in my ITransportProvider and make Device call it in its c'tor.
I'd like to know if its correctness in the eyes of DI/IoC gurus and would love to hear all suggestions.
EDIT:
To clarify, I'm asking if there's a better way of decoupling TransportProvider from Device besides the above way which is via DI and the Observer pattern.
You have a reasonable design. Decoupling can be handled at many different levels in different ways with various trade-offs. Your design is good for the case where you know the sending and receiving are related, but there is no particular compile-time relationship between Device instances and Transport implementations. If there was a compile-time relationship, you might use policy-based design:
class TransportProviderA
{
public:
void SendData();
virtual void OnReceiveData() = 0;
}
template <typename TransportPolicy>
class Device : public TransportPolicy
{
public:
Device(const TransportPolicy &transport_policy)
: TransportPolicy(transport_policy)
{
}
// SendData provided by TransportPolicy
virtual void OnReceiveData(); // overrides TransportPolicy's template method.
};
Then use it like this:
Device<TransportPolicyA> my_device(TransportPolicyA());
Related
I have many interfaces for different listeners, the all look like this:
class ListenerA
{
public:
virtual void
onEventA(const EventA&) = 0;
};
class ListenerB
{
public:
virtual void
onEventB(const EventB&) = 0;
};
When testing, I always end up just collecting those events in a std::vector for analyzing them afterwards in a specific test suite. Those event collectors all look the same like this one for example:
class EventACollector : public ListenerA
{
public:
const auto&
events() const
{
return m_events;
}
private:
void
onEventA(const EventA& event) override
{
m_events.emplace_back(event);
}
std::vector<EventA> m_events;
};
Is there a way to template an EventTCollector, so that I do not have to write it every time? Given that the virtual function name does change for every listeners?
C++ does not have introspection, so you cannot find the virtual function in ListenerA. The other parts can go in a templated base class, but the override you'll need to define manually.
Modern C++ would use a std::function<void(EventA)> instead of a named interface, but that won't help you as a user of that old interface.
We are designing a new system where we have created interfaces for most of our classes so that we can create mocks (google mocks) for them for unit testing. As a result, all the functions are virtual but the issue is that I am often running into template virtual function issue due to this. I have seen some examples on how to do multi dispatch but they all seem to be using some variation of templates, it doesn't seem straightforward. So does it mean that my entire codebase will now end up with templates making it difficult to read/use and debug?
Or am I not designing good interfaces. Here is a simple example where I am writing an interface for a message queue.
Class IMessageQueue {
Public:
Virtual int send(const T & value); // I can't do this but this is exactly what I want to do, as send should be able to send any type
};
Class MessageQueue : public IMessageQueue {
Public:
Virtual int send(const T & value) { ... }
};
Class MockMQ : public IMessageQueue {
Public:
Virtual int send(const T & value) {
// mock implementation
}
};
How do I get around this problem? This is just one example but I run into lots of these type of issues due to interface based programming.
It depends if you need your IMessageQueue to dispatch specific unknown type or any type. That's not the same thing.
A specific unknown type can be managed by
template<typename T>
class IMessageQueue {
public:
virtual int send(const T& value);
}
So that you can have your IMessageQueue<MyMessage> and IMessageQueue<OtherMessage>.
If, instead, you need to be able to send any type with the same type of message queue then your option is to declare a specific interface common to all messages as in
class Message
{
protected:
Message() : { .. }
};
class MyMessage : public Message
{
..
};
class MessageQueue
{
public:
void send(const Message& message);
};
I have a source of some lines of text, each of which is a message, representing object of some type. I'm making a parser for these lines, which should take the text line as input and give the ready to use object as output. So I make the following hierarchy of classes:
class Message
{
public:
virtual ~Message(){};
};
class ObjectTypeA : public Message
{/*...*/};
class ObjectTypeB : public Message
{/*...*/};
class ObjectTypeC : public Message
{/*...*/};
and here's how it's used:
std::shared_ptr<Message> parseLine(std::string& line);
void doWork()
{
std::string line;
while(getLine(line))
{
std::shared_ptr<Message> object=parseLine(line);
if(dynamic_cast<ObjectTypeA*>(object.get()))
doSomethingA(*static_cast<ObjectTypeA*>(object.get()));
else if(dynamic_cast<ObjectTypeB*>(object.get()))
doCompletelyUnrelatedProcessing(*static_cast<ObjectTypeB*>(object.get()));
else if(dynamic_cast<ObjectTypeC*>(object.get()))
doSomethingEvenMoreDifferent(*static_cast<ObjectTypeC*>(object.get()));
}
}
Here the parser would be a library function, and the objects don't know in advance how they will be processed. So, I can't put the processing code to a virtual function of Message implementations.
But many of the answers in this question say that if one needs to check type of the object, it's a sign of bad design. But I can't seem to see what's bad here. Is there any better way to organize the solution?
First off, it's not always a sign of bad design. There are very few absolutes in "soft" things like "good" or "bad" design. Nevertheless, it does often indicate a different approach would be preferable, for one or more of these reasons: extensibility, ease of maintenance, familiarity, and similar.
In your particular case: One of the standard ways to make arbitrary class-specific processing possible without type switches or bloating/polluting the interface of the class is to use the Visitor pattern. You create a generic MessageVisitor interface, teach the Message subclasses to call into it, and implement it wherever you need to process them:
class MessageVisitor;
class Message
{
public:
virtual ~Message(){};
virtual void accept(MessageVisitor &visitor) = 0;
};
class ObjectTypeA : public Message
{
void accept(MessageVisitor &visitor) override
{ visitor.visit(*this); }
/*...*/
};
class ObjectTypeB : public Message
{
void accept(MessageVisitor &visitor) override
{ visitor.visit(*this); }
/*...*/
};
class ObjectTypeC : public Message
{
void accept(MessageVisitor &visitor) override
{ visitor.visit(*this); }
/*...*/
};
class MessageVisitor
{
public:
virtual void visit(ObjectTypeA &subject) {}
virtual void visit(ObjectTypeB &subject) {}
virtual void visit(ObjectTypeC &subject) {}
};
You would then use it like this:
void doWork()
{
struct DoWorkMessageVisitor : MessageVisitor
{
void visit(ObjectTypeA &subject) override { doSomethingA(subject); }
void visit(ObjectTypeB &subject) override { doSomethingB(subject); }
void visit(ObjectTypeC &subject) override { doSomethingC(subject); }
};
std::string line;
while(getLine(line))
{
std::shared_ptr<Message> object=parseLine(line);
DoWorkMessageVisitor v;
object->accept(v);
}
}
Feel free to customise this with const overloads etc. as necessary.
Note that accept cannot be implemented in the base class, because you need the correct type of *this in the invocation of visit. That is where the type switch has "moved".
An alternative is to make the visit functions in MessageVisitor pure virtual instead of empty. Then, if you need to add a new message type, it will automatically force you to update all places where such type-specific processing occurs.
You're really asking for opinions on whats good and bad design. Here's mine:
Yours is bad design, because you try to do something in another class that should be handled by the subclasses, because that's what polymorphism is for.
Your mother class should have a
virtual void do_stuff_that_is_specific_to_the_subclass(...) = 0;
method, which you'd implement in your subclasses.
Here the parser would be a library function, and the objects don't know in advance how they will be processed. So, I can't put the processing code to a virtual function of Message implementations.
Why not? You should simply have a
virtual void do_stuff_that_is_specific_to_the_subclass(parser&, ...) = 0;
method that uses the parser differently for each subclass. There's no reason that what you can do in your if/else clauses couldn't just be done in the subclasses, unless it breaks encapsulation, which I'd doubt, because the only reason you've got these objects is that you want to do specific things differently for different lines.
doSomethingA, doCompletelyUnrelatedProcessing and doSomethingEvenMoreDifferent could be just overrides of pure virtual function of Message class. In your case that would be much more effecient and better as a design solution.
I would like to ask a couple of questions of design patterns.
Lets take for example strategy design pattern:
class Printer{
public:
void print(Message){
}
};
class Message{
public:
void print();
};
class SingleMessage : public Message{
string s;
public:
void print();
};
class Messages : public Message{
vector<Message> v;
public:
void print();
};
According to UML of this pattern, Printer should have method print(Message). What I don't understand (and sorry if this is idiotic question) is do we need to call Message class print method or what? We need to print out message, but we can't create new Message object in class Printer, because then it would be composition. So what should we do then?
Also, maybe you can share some sort of tutorial in which design patterns would be explained (how to use them, when to use them, etc.)?
First off, the concept of composition is on a whole different level than design patterns. Most design patterns use composition – that’s totally fine.
Secondly, no, you don’t use composition here. You invoke the print function of the argument that’s passed to the printer:
class Printer{
public:
void print(Message& m) {
m.print();
}
};
I’ve gone ahead and fixed a bug: the argument needs to be passed by reference (or as a pointer), otherwise you lose the dynamic type. For that reason, the Message::print function also needs to be declared as virtual.
What I don't understand (and sorry if this is idiotic question) is do we need to call Message class print method or what?
Yes. The Message::print function should be abstract, and implemented (as a different strategy) in each class inheriting from Message.
We need to print out message, but we can't create new Message object in class Printer, because then it would be composition. So what should we do then?
You don't need to create a new instance in the printer (i.e. you don't need composition here). All you do here is choose the implementation strategy for printing by deciding what concrete implementation will be passed into the Printer::print function.
Also, maybe you can share some sort of tutorial in which design patterns would be explained (how to use them, when to use them, etc.)?
Normally design patterns are idiomatic solutions to re-occurring design problems. You can find details on wikipedia regarding when to use them. For example, this page says:
"In computer programming, the strategy pattern (also known as the
policy pattern) is a software design pattern, whereby an algorithm's
behaviour can be selected at runtime."
As a side note, this is not a very good example for the strategy pattern. A better one would have been to abstract what printing means, not what a message means:
class Message{
public:
void display(Printer& p) {
p.print(*this); // what printing strategy is applied to
// display the message depends on the
// concrete type of the parameter (on what
// Printer specialization you call
// the function with)
}
};
struct Printer{
virtual void print(Message& m);
};
struct BWPrinter: Printer {
virtual void print(Message& m);
};
struct ColorPrinter: Printer {
virtual void print(Message& m);
};
struct IOStreamPrinter: Printer {
IOStreamPrinter(std::iostream& s);
virtual void print(Message& m);
};
What you probably want to do is to provide a Printer as Strategy. You can spezialize a CoutPrinter FilePrinter or PrinterPrinter...
class Printer{
public:
virtual void print(const string& message) = 0;
};
class CoutPrinter{
public:
void print(const string& message) override {
std::cout << message << "\n";
}
};
You can then use this concept to print messages:
class Message{
public:
virtual print(Printer& printer) = 0;
};
class SingleMessage : public Message {
string s;
public:
void print(Printer& printer) override
{
printer.print(s)
}
};
class Messages {
vector<Message> messages;
std::unique_ptr<Printer> printer;
public:
/// Inject the concrete Printer strategy here
Messages(std::unique_ptr<Printer> printerStrategy) :
printer(move(printer))
{}
void print() {
for(auto& m : messages)
m.print(*printer);
}
};
You can know use constructor injection to select different printers for your Messages
int main()
{
Messages messages {std::make_unique<CoutPrinter>()};
messages.print(); // will print all messages to std::cout
}
Composite Pattern
In your example you derived Messages from Message. This is the Composite Pattern. You can combine both:
class Messages : public Messages {
vector<Message> messages;
public:
void print(Printer& printer) override {
for(auto& m : messages)
m.print(*printer);
}
};
int main()
{
Messages messages;
CoutPrinter printer;
messages.print(printer); // will print all messages to std::cout
}
I know 2 ways for desiging an event in C++:
1: Using callbacks:
typedef void (*callback_type)(void);
class my_class
{
public:
my_class(callback_type c)
{
m_callback = c;
}
void raise_event()
{
m_callback();
}
private:
callback_type m_callback;
};
2: Using virtual methods:
class my_class
{
public:
virtual void my_event() = 0;
void raise_event()
{
my_event();
}
};
class main_class : public my_class
{
public:
virtual void my_event()
{
// Handle EVENT.
}
};
Is there any other way or other idea for designing events?
and
What is the best pattern for designing events in ISO C++?
You should use Boost.Signals or Boost.Signals2.
To emulate those, you can use a collection of Boost.Function's/std::function's.
To emulate those, you use type erasure (so the virtual function route) for flexibility.
Note that none of that is too trivial, so you should really try to use an existing solution if possible.
The design will depend on the specifics of your requirements. For a nice example, see ACE Reactor.