I want to check if the examples below (from a test interview) corresponds to the correct design pattern name :
Example 1 : can that piece of code illustrate the "Builder" pattern or it might be the "Strategy" one ?
FileStream* files = new FileStream("my_file.zip");
BufferedStream* bufferds = new BufferedStream(files);
ZipStream* zips = new ZipStream(bufferds);
Example 2 : is the code below represent the "Strategy" pattern ?
struct UnixText {
void write(string str) { cout << str; }
void lf() { cout << "\n"; }
};
struct WindowsText {
void write(string str) { cout << str; }
void crlf() { cout << "\r\n"; }
};
struct Writer {
virtual void write(string str) = 0;
virtual void newline() = 0;
virtual ~Writer() {}
};
struct UnixWriter : Writer {
UnixWriter(UnixText* tx) { _target = tx; }
virtual void write(string str) { _target->write(str); }
virtual void newline() { _target->lf(); }
private:
UnixText* _target;
};
struct WindowsWriter : Writer {
WindowsWriter(WindowsText* tx) { _target = tx; }
virtual void write(string str) { _target->write(str); }
virtual void newline() { _target->crlf(); }
private:
WindowsText* _target;
};
int main()
{
Writer* writer = (g_IsUnix) ? (Writer*) new UnixWriter(new UnixText()) : (Writer*) new WindowsWriter(new WindowsText());
writer->write("Hello");
writer->newline();
writer->write("World");
}
The first example uses I/O streams and it is a good use of Decorator pattern. Here it has a constructor that takes an instance of the same abstract class or interface. That's the recognition key of the Decorator pattern
The second one, you are passing some Writing Strategy to the UnixWriter and WindowsWriter which is the context. So it can be considered as Strategy pattern. But you can still improve it by having a contract for Writing Strategy. So your concrete writers should only know about that super type rather than having references to concrete implementations. That will make your system more flexible.
Related
I am writing an Observer design pattern where Subject knows what Observer it has (same as the original design) and Observer also knows what Subject it's attached to, mainly to tackle scenarios like Observer going out of scope and Subject has a reference to a destroyed object.
So if an Observer watches a Subject, both know about each other. This is handled via observer->removeSubject and observer->addSubject.
In the following snippet, I am testing a case where Observers go out of scope, meaning ~Observer() gets invoked first however I seem to be getting a segfault on the following line when I debug in an online gdb tool in the second iteration of ~Observer()
std::cout << "Observers size = " << _observers.size() << "\n";
template<typename T>
class Subject;
template<typename T>
class Observer
{
std::set<Subject<T>*> _subjects;
public:
virtual void update(T val) = 0;
void addSubject(Subject<T>* subject)
{
printf ("[Observer] Adding Subject to observer - ");
_subjects.insert(subject);
std::cout << "Subject size = " << _subjects.size() << "\n\n";
}
void removeSubject(Subject<T>* subject)
{
printf ("[Observer] Removing Subject from observer - ");
_subjects.erase(subject);
std::cout << "Subject size = " << _subjects.size() << "\n";
}
virtual ~Observer()
{
printf ("\n~Observer\nSubject Size = %ld\n", _subjects.size());
for (auto& subject : _subjects)
{
subject->detach(this);
}
}
};
template<typename T>
class Subject
{
std::set<Observer<T>*> _observers;
protected:
Subject() = default;
public:
void attach(Observer<T>* observer)
{
printf ("~~ [Subject] Attaching observer ~~\n");
_observers.insert(observer);
observer->addSubject(this);
}
void detach(Observer<T>* observer)
{
printf ("~~ [Subject] Detaching observer ~~\n");
std::cout << "Observers size = " << _observers.size() << "\n";
_observers.erase(observer);
observer->removeSubject(this);
}
void notify(const T& val)
{
for (auto& observer : _observers)
{
observer->update(val);
}
}
virtual ~Subject()
{
printf ("\n~Subject\n");
printf ("Observer size = %ld\n", _observers.size());
for (auto& obs : _observers)
{
obs->removeSubject(this);
}
}
};
template<typename T>
class ConcreteSubject : public Subject<T>
{
T _value;
public:
void set(const T& value)
{
_value = value;
this->notify(value);
}
};
template<typename T>
class ConcreteObserver : public Observer<T>
{
public:
void update(T value)
{
std::cout << "Observer Notified: " << value << "\n";
}
};
int main()
{
ConcreteSubject<int> sub;
{
ConcreteObserver<int> obs;
ConcreteObserver<int> obs1;
sub.attach(&obs);
sub.attach(&obs1);
sub.set(5);
}
}
One part that I am concerned about is the following where subject is removed from _subjects while _subjects is being iterated over.
Should a copy of _subjects be made to be iterated over in ~Observer() instead?
void removeSubject(Subject<T>* subject)
{
printf ("[Observer] Removing Subject from observer - ");
_subjects.erase(subject);
std::cout << "Subject size = " << _subjects.size() << "\n";
}
virtual ~Observer()
{
printf ("\n~Observer\nSubject Size = %ld\n", _subjects.size());
for (auto& subject : _subjects)
{
subject->detach(this);
}
}
There may be more problems in your code but I can see at last this one:
When Observer is being destroyed in destructor, it iterates over _subjects collection. You call Subject::detach() on each subject. Subject::detach() in turn calls Observer::removeSubject() on the very same observer and Observer::removeSubject() removes the subject from the very same _subjects collection which you are currently iterating upon. This is undefined behaviour which later probably leads to the segfault you are having.
Solution 1
In Observer::~Observer() you can make a copy of the _subjects collection and iterate on this copy. This seems to be the simplest solution.
Solution 2
virtual ~Observer()
{
while (!_subjects.empty())
{
(*_subjects.begin())->detach(this);
}
}
Solution 3
This solution may actually be the most performant one.
If you are destroying the Observer you do not need to clear the _subjects collection one by one because the observer object will be destroyed anyway. Therefore you may introduce a private bool _destroying member variable. Its default value will be false but in the destructor it would be set to true. And when true, it would prevent removing from _subjects collection in removeSubject().
void removeSubject(Subject<T>* subject)
{
if (!_destroying)
{
_subjects.erase(subject);
}
}
virtual ~Observer()
{
_destroying = true;
for (auto& subject : _subjects)
{
subject->detach(this);
}
}
I am trying to create a DI container in C++ (for studying purposes). I know about boost DI container option, but I just want to have fun writing one by myself.
I would like that the created container only had one instance per object "registered", so I should apply the Singleton design pattern.
But, what would be the best (idiomatic) way to implement the Singleton Pattern as an in C++20 or, at least, in modern C++ and why?
Do you mean something like this, using meyer's singleton.
(https://www.modernescpp.com/index.php/thread-safe-initialization-of-a-singleton)
I never use singletons that need to be created with new, since their destructor never gets called. With this pattern the destructors do get called when the program terminates.
#include <iostream>
//-----------------------------------------------------------------------------
// create an abstract baseclass (closest thing C++ has to an interface)
struct data_itf
{
virtual int get_value1() const = 0;
virtual ~data_itf() = default;
protected:
data_itf() = default;
};
//-----------------------------------------------------------------------------
// two injectable instance types
struct test_data_container :
public data_itf
{
int get_value1() const override
{
return 0;
}
~test_data_container()
{
std::cout << "test_data_container deleted";
}
};
struct production_data_container :
public data_itf
{
int get_value1() const override
{
return 42;
}
~production_data_container()
{
std::cout << "production_data_container deleted";
}
};
//-----------------------------------------------------------------------------
// meyers threadsafe singleton to get to instances implementing
// interface to be injected.
//
data_itf& get_test_data()
{
static test_data_container test_data;
return test_data;
}
data_itf& get_production_data()
{
static production_data_container production_data;
return production_data;
}
//-----------------------------------------------------------------------------
// object that needs data
class my_object_t
{
public:
explicit my_object_t(const data_itf& data) :
m_data{ data }
{
}
~my_object_t()
{
std::cout << "my_object deleted";
}
void function()
{
std::cout << m_data.get_value1() << "\n";
}
private:
const data_itf& m_data;
};
//-----------------------------------------------------------------------------
int main()
{
auto& data = get_production_data();
my_object_t object{ data };
object.function();
return 0;
}
I am receiveing commands through json, which I insert in to a pipe. For this reason thye must have the same base class.
The pipe is read by a pipe handler, some commands are consumed by the pipe handler, others have to be passed down to a device, which is a member of the pipe handler. I could simply do this:
class Command{};
class HandlerCommand : public Command {
void execute(Handler* h);
};
class DeviceCommand : public Command {
void execute(Device* d);
};
Command* c = pipe.receive();
if (const auto hc = dynamic_cast<const HandlerCommand*>(c)) { hc.execute( **handlerptr** ); }
else if (const auto dc = dynamic_cast<const DeviceCommand*>(c)) { dc.execute( **deviceptr** );}
Device and pipehandler should not have the same base, since they have no common methods, fields, they are conceptually different.
Is there a way to avoid using dynamic cast here. I was thinking maybe there is some neat design pattern for this, but couldn`t quit come up with a better solution.
EDIT: did not derive DeviceCommand and HandlerCommand from command, fixed this.
You cannot use polymorphism of two things which have nothing in common. You will need the same base class/interface: in your case Command. As mentioned above your base class requires a pure virtual function that must be implemented by the derived classes. I will utilize a Command * clone()const prototype, which could be very useful later on. Please introduce a virtual destructor of your base class, otherwise, to track down this memory error could be a pain in the ass. Note, regarding your dynamic_cast the member function execute, must be const. You may try this:
#include <iostream>
#include <vector>
class Handler
{
public:
Handler(){}
};
class Device
{
public:
Device(){}
};
enum class CommandType{Handler,Devise};
class Command
{
public:
virtual ~Command(){}
virtual Command*clone()const = 0;
virtual CommandType getType()const = 0;
};
class HandlerCommand : public Command {
public:
HandlerCommand():Command(){}
void execute(Handler* h) const
{
std::cout << __FUNCTION__<<"\n";
}
HandlerCommand*clone()const { return new HandlerCommand(*this); }
CommandType getType()const { return CommandType::Handler; }
};
class DeviceCommand : public Command{
public:
DeviceCommand():Command(){}
void execute(Device* d)const
{
std::cout << __FUNCTION__<<"\n";
}
DeviceCommand*clone()const { return new DeviceCommand(*this); }
CommandType getType()const { return CommandType::Devise; }
};
int main()
{
Device dev;
Handler handler;
std::vector<Command*> pipe{ new HandlerCommand(), new DeviceCommand() };
while (!pipe.empty())
{
Command* c = pipe.back();
if (c->getType() == CommandType::Handler) { static_cast<const HandlerCommand*>(c)->execute(&handler); }
else if (c->getType() == CommandType::Devise ) { static_cast<const DeviceCommand*>(c)->execute(&dev); }
delete c;
pipe.pop_back();
}
std::cin.get();
}
outputs:
DeviceCommand::execute
HandlerCommand::execute
Version 2.0 using std::variant. You will need at least C++17 to compile this. Note, a single pipe container can exclusively comprise one of the mentioned classes within the variant. So there is no casting anymore, but you will need two pipes. Because of that, I introduced a time stamp variable.
#include <iostream>
#include <vector>
#include <variant>
class Handler
{
public:
Handler() {}
};
class Device
{
public:
Device() {}
};
class HandlerCommand {
int ts;
public:
HandlerCommand(int _ts):ts(_ts) {}
void execute(Handler* h) const
{
std::cout << ts << ": "<< __FUNCTION__ << "\n";
}
int timeStamp()const { return ts; }
};
class DeviceCommand {
int ts;
public:
DeviceCommand(int _ts) :ts(_ts) {}
void execute(Device* d)const
{
std::cout << ts << ": " << __FUNCTION__ << "\n";
}
int timeStamp()const { return ts; }
};
using Command = std::variant<HandlerCommand, DeviceCommand>;
int main()
{
Device dev;
Handler handler;
std::vector<Command> hcPipe{HandlerCommand(2),HandlerCommand(5)};
std::vector<Command> dcPipe{DeviceCommand(1),DeviceCommand(4)};
Command single = DeviceCommand(0);
if (single.index() == 0)
{
std::get<HandlerCommand>(single).execute(&handler);
}
else
{
std::get<DeviceCommand>(single).execute(&dev);
}
while (!hcPipe.empty() || !dcPipe.empty())
{
if (!hcPipe.empty() && (dcPipe.empty() || std::get<HandlerCommand>(hcPipe.front()).timeStamp() < std::get<DeviceCommand>(dcPipe.front()).timeStamp()))
{
std::get<HandlerCommand>(hcPipe.front()).execute(&handler);
hcPipe.erase(hcPipe.begin());
}
else
{
std::get<DeviceCommand>(dcPipe.front()).execute(&dev);
dcPipe.erase(dcPipe.begin());
}
}
std::cin.get();
}
outputs:
0: DeviceCommand::execute
1: DeviceCommand::execute
2: HandlerCommand::execute
4: DeviceCommand::execute
5: HandlerCommand::execute
C++ has limited ability to use pointer-to-member functions. I need something that will allow me to dynamically choose a callback member function, in order to use the Visitor pattern of the XMLNode::Accept(XMLVisitor *visitor) method from the TinyXML2 library.
To use XMLNode::Accept(), I must call it with a class which implements the XMLVisitor interface. Hence:
typedef bool (*Callback)(string, string);
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
callback(e.Name(), e.GetText());
}
Callback callback;
}
This works fine if my caller is NOT an object which wants to use one of its own methods as a callback function (so that it can access class variables). For example, this works:
bool myCallBackFunc(string e, string v) {
cout << "Element " << e << " has value " << v << endl;
return true;
}
int main(...) {
tinyxml2::XMLDocument doc;
doc.LoadFile("somefile.xml");
MyVisitor visit;
visit.callback = myCallBackFunc;
doc.Accept(&visit);
}
However, in my use case, the parsing is done inside a method in a class. I have multiple applications which have similar but unique such classes. I'd like to use only one generic MyVisitor class, rather than have the visitor class have unique knowledge of the internals of each class which will call it.
Thus, it would be convenient if the callback function were a method in each calling class so that I can affect the internal state of the object instantiated from that calling class.
Top level: I have 5 server applications which talk to 5 different trading partners, who all send XML responses, but each is enough different that each server app has a class which is unique to that trading partner. I'm trying to follow good OO and DRY design, and avoid extra classes having unique knowledge while still doing basically the same work.
Here's the class method I want Accept() to call back.
ServiceClass::changeState(string elem, string value) {
// Logic which sets member vars based on element found and its value.
}
Here's the class method which will call Accept() to walk the XML:
ServiceClass::processResponse(string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
MyVisitor visit;
visit.callback = &changeState; // ERROR. Does not work.
visit.callback = &ServiceClass::changeState; // ERROR. Does not work.
doc.Accept(&visit);
}
What's a simple way to get what I want? I can imagine more classes with derived classes unique to each situation, but that seems extremely verbose and clumsy.
Note: In the interest of brevity, my sample code above has no error checking, no null checking and may even have minor errors (e.g. treating const char * as a string ;-).
Below is the std::bind(..) example for what you're trying to do in C++11. For earlier C++ versions you could use the boost::bind utilities.
Fix your MyVisitor::VisitExit(...) method to return a boolean, by the way.
The code is converting const char * to std::string. tinyxml2 does not guarantee that the char * arguments from Name() or GetText() are not null. In fact in my experience they will be null at some point. You should guard against this. For the sake of not modifying your example too much I've not protected against this possibility everywhere in the example.
typedef bool(*Callback)(string, string);
using namespace std;
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
// return callback(e.Name(), e.GetText());
return true;
}
Callback callback;
};
/** Typedef to hopefully save on confusing syntax later */
typedef std::function< bool(const char * element_name, const char * element_text) > visitor_fn;
class MyBoundVisitor : public tinyxml2::XMLVisitor {
public:
MyBoundVisitor(visitor_fn fn) : callback(fn) {}
bool VisitExit(const tinyxml2::XMLElement &e) {
return callback(e.Name() == nullptr ? "\0" : e.Name(), e.GetText() == nullptr ? "\0": e.GetText());
}
visitor_fn callback;
};
bool
myCallBackFunc(string e, string v) {
cout << "Element " << e << " has value " << v << endl;
return true;
}
int
main()
{
tinyxml2::XMLDocument doc;
doc.LoadFile("somefile.xml");
MyVisitor visit;
visit.callback = myCallBackFunc;
doc.Accept(&visit);
visitor_fn fn = myCallBackFunc; // copy your function pointer into the std::function<> type
MyBoundVisitor visit2(fn); // note: declare this outside the Accept(..) , do not use a temporary
doc.Accept(&visit2);
}
So from within the ServiceClass method you'd do:
ServiceClass::processResponse(string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
// presuming changeState(const char *, const char *) here
visitor_fn fn = std::bind(&ServiceClass::changeState,this,std::placeholders::_1,std::placeholders::_2);
MyBoundVisitor visit2(fn); // the method pointer is in the fn argument, together with the instance (*this) it is a method for.
doc.Accept(&visit);
}
You can use generics in order to support whichever callback you'd like.
I've tried to mock the classes of the library in order to give you a fully runnable example:
#include <string>
#include <iostream>
#include <functional>
class XmlNode {
public:
XmlNode(const std::string& n, const std::string t) : name(n), txt(t) {}
const std::string& Name() const { return name; }
const std::string& GetText() const { return txt; }
private:
std::string name;
std::string txt;
};
class XMLVisitor {
public:
virtual void VisitExit(const XmlNode& node) = 0;
virtual ~XMLVisitor() {}
};
template<typename T>
class MyVisitor : XMLVisitor {
public:
MyVisitor() {}
void myInnerPrint(const XmlNode& node) {
std::cout << "MyVisitor::myInnerPrint" << std::endl;
std::cout << "node.Name(): " << node.Name() << std::endl;
std::cout << "node.GetText(): " << node.GetText() << std::endl;
}
void SetCallback(T newCallback) {
callback = newCallback;
}
virtual void VisitExit(const XmlNode& node) {
callback(node);
}
T callback;
};
int main() {
XmlNode node("In", "Member");
MyVisitor<std::function<void(const XmlNode&)>> myVisitor;
auto boundCall =
[&myVisitor](const XmlNode& node) -> void {
myVisitor.myInnerPrint(node);
};
myVisitor.SetCallback(boundCall);
myVisitor.VisitExit(node);
return 0;
}
First define a template and a helper function:
namespace detail {
template<typename F>
struct xml_visitor : tinyxml2::XMLVisitor {
xml_visitor(F&& f) : f_(std::move(f)) {}
virtual void VisitExit(const tinyxml2::XMLElement &e) {
f_(e);
}
private:
F f_;
};
}
template<class F>
auto make_xml_visitor(F&& f)
{
return detail::xml_visitor<std::decay_t<F>>(std::forward<F>(f));
}
Then use the helper function to construct a custom visitor from a lambda which captures this:
void ServiceClass::processResponse(std::string xml) {
// Parse XML and do something only if certain elements present.
tinyxml2::XMLDocument doc;
doc.Parse(xml.c_str(), xml.length());
auto visit = make_xml_visitor([this](const auto& elem)
{
this->changeState(elem.Name(), elem.GetText);
});
doc.Accept(std::addressof(visit));
}
The rule is that a function pointer must always accept a void * which is passed in to the module which calls it, and passed back. Or use a lambda which is the same thing with some of the machinery automated for you. (The void * is the "closure").
So
typedef bool (*Callback)(string, string, void *context);
class MyVisitor : public tinyxml2::XMLVisitor {
public:
bool VisitExit(const tinyxml2::XMLElement &e) {
callback(e.Name(), e.GetText(), contextptr);
}
Callback callback;
void *contextptr;
}
bool myCallBackFunc(string e, string v, void *context) {
ServiceClass *service = (ServiceClass *) context;
cout << "Element " << e << " has value " << v << endl;
service->ChangeState(e, v);
return true;
}
As you know, different vendor may have different name of data field. Although the name is difference, the data struct is almost the same.
For example,
struct s1 {
int s1Price,
int s1Volume
};
struct s2 {
int s2Price,
int s2Volume
};
Like stock market data, the data would sent to program automatically, and the program just receives the data and then processes it.
I want to design a program which can easily change to other vendor's data struct.
If I develop program with s1, sometime later, I want to change to s2 with smallest change.
I hope you can get my point.
Could you give me any advice ? Any design patter or your experience ?
The keyword here is abstraction.
Here is one way of doing it :
#include <iostream>
struct s1 {
int s1Price;
int s1Volume;
};
struct s2 {
int s2Price;
int s2Volume;
};
class Idata
{
public:
virtual ~Idata() {}
public:
virtual int getPrice() = 0;
virtual int getVolume() = 0;
};
class s1Data : public Idata, public s1 {
public:
s1Data(const s1& S1) : s1(S1) {}
virtual int getPrice() {
return s1Price;
}
virtual int getVolume() {
return s1Volume;
}
};
class s2Data : public Idata, public s2 {
public:
s2Data(const s2& S2) : s2(S2) {}
virtual int getPrice() {
return s2Price;
}
virtual int getVolume() {
return s2Volume;
}
};
void my_func_that_will_never_change_because_it_uses_abstraction(Idata *data)
{
std::cout << data->getPrice() << std::endl;
std::cout << data->getVolume() << std::endl;
}
int main(void)
{
s1 Sfirst{42, 21};
s2 Ssecond{99, 88};
s1Data DataFirst(Sfirst);
s2Data DataSecond(Ssecond);
my_func_that_will_never_change_because_it_uses_abstraction(&DataFirst);
my_func_that_will_never_change_because_it_uses_abstraction(&DataSecond);
}
Code all your program the same way my_func_that_will_never_change_because_it_uses_abstraction is coded (by using the interface IData not the concrete underlying types) and you'll have nothing to change except the initialisation phase which determine which type of data you will have in the first place.