C++ design pattern to get rid of if-then-else - c++

I have the following piece of code:
if (book.type == A) do_something();
else if (book.type == B) do_something_else();
....
else do so_some_default_thing.
This code will need to be modified whenever there is a new book type
or when a book type is removed. I know that I can use enums and use a switch
statement. Is there a design pattern that removes this if-then-else?
What are the advantages of such a pattern over using a switch statement?

You could make a different class for each type of book. Each class could implement the same interface, and overload a method to perform the necessary class-specific logic.
I'm not saying that's necessarily better, but it is an option.

As others have pointed out, a virtual function should probably be your first choice.
If, for some reason, that doesn't make sense/work well for your design, another possibility would be to use an std::map using book.type as a key and a pointer to function (or functor, etc.) as the associated value, so you just lookup the action to take for a particular type (which is pretty much how many OO languages implement their equivalent of virtual functions, under the hood).

Each different type of book is a different sub-class of the parent class, and each class implements a method do_some_action() with the same interface. You invoke the method when you want the action to take place.

Yes, it's called looping:
struct BookType {
char type;
void *do();
};
BookType[] types = {{A, do_something}, {B, do_something_else}, ...};
for (int i = 0; i < types_length; i++) {
if (book.type == types[i].type) types[i].do(book);
}
For a better approach though, it's even more preferrable if do_something, do_something_else, etc is a method of Book, so:
struct Book {
virtual void do() = 0;
};
struct A {
void do() {
// ... do_something
}
};
struct B {
void do() {
// ... do_something_else
}
};
so you only need to do:
book.do();

Those if-then-else-if constructs are one of my most acute pet peeves. I find it difficult to conjure up a less imaginative design choice. But enough of that. On to what can be done about it.
I've used several design approaches depending on the exact nature of the action to be taken.
If the number of possibilities is small and future expansion is unlikely I may just use a switch statement. But I'm sure you didn't come all the way to SOF to hear something that boring.
If the action is the assignment of a value then a table-driven approach allows future growth without actually making code changes. Simply add and remove table entries.
If the action involves complex method invocations then I tend to use the Chain of Responsibility design pattern. I'll build a list of objects that each knows how to handle the actions for a particular case.
You hand the item to be processed to the first handler object. If it knows what to do with the item it performs the action. If it doesn't, it passes the item off to the next handler in the list. This continues until the item is processed or it falls into the default handler that cleans up or prints an error or whatever. Maintenance is simple -- you add or remove handler objects from the list.

You could define a subclass for each book type, and define a virtual function do_something. Each subclass A, B, etc would have its own version of do_something that it calls into, and do_some_default_thing then just becomes the do_something method in the base class.
Anyway, just one possible approach. You would have to evaluate whether it really makes things easier for you...

Strategy Design Pattern is what I think you need.

As an alternative to having a different class for each book, consider having a map from book types to function pointers. Then your code would look like this (sorry for pseudocode, C++ isn't at the tip of my fingers these days):
if book.type in booktypemap:
booktypemap[book.type]();
else
defaultfunc();

Related

C++ construct if satisfies conditions

i have a design issue, not complicated actually, but i would like to find an elegant way to solve it. And i thought about this:
Issue:
i have a class A that initialize and keep a collection of B
B is just an interface and must be implemented (so we have classes C,D,E,..).
in constructor A recive a bunch of dataset and must initialize some of B (also lot of different instantiation of same or different class) given each dataset. I would like A to not to know any implementation of B.
I have several working solution, but i was thinking about a kind of "delegate in the constructor".
eg:
1. for each dataset, ds
2. for each implementation of B, bi
3. try to instantiate bi(ds)
4. if success (means no exception)
5. keep reference
this because the data and calculus i use to check if bi are pretty the same of initialization and being in a performance-critic application i would like to avoid doing that twice or doing it in collection class.
it would be really nice but obviously the problem is line 2...
...as well as the doubt about using exception for something that is not actually an exception. (line 4)
so what should be a pattern that
- let me evaluate data and construct all in one.
- avoid creating several "architectural-classes" i would like to avoid an explosion of classes ( kind of typical when exagerating with following design patterns java-style principles imho ) for such a simple task.
- as fast as possible.
- ...is elegant :)
The answer is based on my intuition right now, so it may not be perfect, but on the other hand, most of the design solutions aren't.
I would create just one additional class, call it factory or something similar. Then run all the constructions through this class. It should be able to be initialized with possible instantiations of derives of B either in run-time (by running callbacks at the beginning of the program), or, even better, by variadic template traits.
template<class ... RegisteredBImplementations>
class CFactory
{
B* Create (dataset const& d)
{
// some magical meta-ifs to create compile time conditions
// or for (auto& registered_type : registered types), and then choose one
return new T(d);
}
}
Then, A could use an instance of this class to initialize it's pointers properly:
for (auto& dataset : datasets)
{
m_BPtrs.emplace_back( std::unique_ptr<dataset> (m_FactoryInstance.Create(dataset)) );
}
The main point of this solution is that class A effectively manages "B" objects, leaving proper construction of them to the other class. They are effectively separated, and addition of a new B implementation means a change only in CFactory, not in A.
Your pseudocode suggests a solution: your use of bi is nothing more than a factory function that takes a dataset as input and returns a B* as output. So, you really just need to take bi from a collection of std::function<B* (dataset)> objects.
It would be easy enough to require that these factories are only 'conditional' factories: that sometimes they return valid objects, and sometimes they don't, returning nullptr instead. This would let you avoid exceptions, and is more faithful to the intent of your usage.
The simplest solution is to delegate to a Factory method.
std::unique_ptr<B> build(DataSet const& ds) {
if (ds.property() == value) {
return std::unique_ptr<B>(new D(ds));
}
return std::unique_ptr<B>(new C(ds));
}
Then A need only depend on the declaration of build.

Alternatives to passing a flag into a method?

Sometimes when fixing a defect in an existing code base I might (often out of laziness) decide to change a method from:
void
MyClass::foo(uint32_t aBar)
{
// Do something with aBar...
}
to:
void
MyClass::foo(uint32_t aBar, bool aSomeCondition)
{
if (aSomeCondition)
{
// Do something with aBar...
}
}
During a code review a colleague mentioned that a better approach would be to sub-class MyClass to provide this specialized functionality.
However, I would argue that as long as aSomeCondition doesn't violate the purpose or cohesion of MyClass it is an acceptable pattern to use. Only if the code became infiltrated with flags and if statements would inheritance be a better option, otherwise we would be potentially be entering architecture astronaut territory.
What's the tipping point here?
Note: I just saw this related answer which suggests that an enum may be a better
choice than a bool, but I think my question still applies in this case.
There is not only one solution for this kind of problem.
Boolean has a very low semantic. If you want to add in the future a new condition you will have to add a new parameter...
After four years of maintenance your method may have half a dozen of parameters, if these parameters are all boolean it is very nice trap for maintainers.
Enum is a good choice if cases are exclusive.
Enums can be easily migrated to a bit-mask or a context object.
Bit mask : C++ includes C language, you can use some plain old practices. Sometime a bit mask on an unsigned int is a good choice (but you loose type checking) and you can pass by mistake an incorrect mask. It is a convenient way to move smoothly from a boolean or an enum argument to this kind of pattern.
Bit mask can be migrated with some effort to a context-object. You may have to implement some kind of bitwise arithmetics such as operator | and operator & if you have to keep a buildtime compatibility.
Inheritence is sometime a good choice if the split of behavior is big and this behavior IS RELATED to the lifecycle of the instance. Note that you also have to use polymorphism and this is may slow down the method if this method is heavily used.
And finally inheritence induce change in all your factory code... And what will you do if you have several methods to change in an exclusive fashion ? You will clutter your code of specific classes...
In fact, I think that this generally not a very good idea.
Method split : Another solution is sometime to split the method in several private and provide two or more public methods.
Context object : C++ and C lack of named parameter can be bypassed by adding a context parameter. I use this pattern very often, especially when I have to pass many data across level of a complex framework.
class Context{
public:
// usually not a good idea to add public data member but to my opinion this is an exception
bool setup:1;
bool foo:1;
bool bar:1;
...
Context() : setup(0), foo(0), bar(0) ... {}
};
...
Context ctx;
ctx.setup = true; ...
MyObj.foo(ctx);
Note:
That this is also useful to minimize access (or use) of static data or query to singleton object, TLS ...
Context object can contain a lot more of caching data related to an algorithm.
...
I let your imagination run free...
Anti patterns
I add here several anti pattern (to prevent some change of signature):
*NEVER DO THIS *
*NEVER DO THIS * use a static int/bool for argument passing (some people that do that, and this is a nightmare to remove this kind of stuff). Break at least multithreading...
*NEVER DO THIS * add a data member to pass parameter to method.
Unfortunately, I don't think there is a clear answer to the problem (and it's one I encounter quite frequently in my own code). With the boolean:
foo( x, true );
the call is hard to understand .
With an enum:
foo( x, UseHigherAccuracy );
it is easy to understand but you tend to end up with code like this:
foo( x, something == someval ? UseHigherAccuracy : UseLowerAccuracy );
which is hardly an improvement. And with multiple functions:
if ( something == someval ) {
AccurateFoo( x );
}
else {
InaccurateFoo( x );
}
you end up with a lot more code. But I guess this is the easiest to read, and what I'd tend to use, but I still don't completely like it :-(
One thing I definitely would NOT do however, is subclass. Inheritance should be the last tool you ever reach for.
The primary question is if the flag affects the behaviour of the class, or of that one function. Function-local changes should be parameters, not subclasses. Run-time inheritance should be one of the last tools reached for.
The general guideline I use is: if aSomeCondition changes the nature of the function in a major way, then I consider subclassing.
Subclassing is a relatively large effort compared to adding a flag that has only a minor effect.
Some examples:
if it's a flag that changes the direction in which a sorted collection is returned to the caller, that's a minor change in nature (flag).
if it's a one-shot flag (something that affects the current call rather than a persistent change to the object), it should probably not be a subclass (since going down that track is likely to lead to a massive number of classes).
if it's a enumeration that changes the underlying data structure of your class from array to linked list or balanced tree, that's a complex change (subclass).
Of course, that last one may be better handled by totally hiding the underlying data structure but I'm assuming here that you want to be able to select one of many, for reasons such as performance.
IMHO, aSomeCondition flag changes or depends on the state of current instance, therefore, under certain conditions this class should change its state and handle mentioned operation differently. In this case, I can suggest the usage of State Pattern. Hope it helps.
I would just change code:
void MyClass::foo(uint32_t aBar, bool aSomeCondition)
{
if (aSomeCondition)
{
// Do something with aBar...
}
}
to:
void MyClass::foo(uint32_t aBar)
{
if (this->aSomeCondition)
{
// Do something with aBar...
}
}
I always omit bool as function parameter and prefer to put into struct, even if I would have to call
myClass->enableCondition();

runtime type comparison

I need to find the type of object pointed by pointer.
Code is as below.
//pWindow is pointer to either base Window object or derived Window objects like //Window_Derived.
const char* windowName = typeid(*pWindow).name();
if(strcmp(windowName, typeid(Window).name()) == 0)
{
// ...
}
else if(strcmp(windowName, typeid(Window_Derived).name()) == 0)
{
// ...
}
As i can't use switch statement for comparing string, i am forced to use if else chain.
But as the number of window types i have is high, this if else chain is becoming too lengthy.
Can we check the window type using switch or an easier method ?
EDIT: Am working in a logger module. I thought, logger should not call derived class virtual function for logging purpose. It should do on its own. So i dropped virtual function approach.
First of all use a higher level construct for strings like std::string.
Second, if you need to check the type of the window your design is wrong.
Use the Liskov substitution principle to design correctly.
It basically means that any of the derived Window objects can be replaced with it's super class.
This can only happen if both share the same interface and the derived classes don't violate the contract provided by the base class.
If you need some mechanism to apply behavior dynamically use the Visitor Pattern
Here are the things to do in order of preference:
Add a new virtual method to the base class and simply call it. Then put a virtual method of the same name in each derived class that implements the corresponding else if clause inside it. This is the preferred option as your current strategy is a widely recognized symptom of poor design, and this is the suggested remedy.
Use a ::std::map< ::std::string, void (*)(Window *pWindow)>. This will allow you to look up the function to call in a map, which is much faster and easier to add to. This will also require you to split each else if clause into its own function.
Use a ::std::map< ::std::string, int>. This will let you look up an integer for the corresponding string and then you can switch on the integer.
There are other refactoring strategies to use that more closely resemble option 1 here. For example,if you can't add a method to the Window class, you can create an interface class that has the needed method. Then you can make a function that uses dynamic_cast to figure out if the object implements the interface class and call the method in that case, and then handle the few remaining cases with your else if construct.
Create a dictionary (set/hashmap) with the strings as keys and the behaviour as value.
Using behaviour as values can be done in two ways:
Encapsulate each behaviour in it's
own class that inherit from an
interface with"DoAction" method that
execute the behavior
Use function pointers
Update:
I found this article that might be what you're looking for:
http://www.dreamincode.net/forums/topic/38412-the-command-pattern-c/
You might try putting all your typeid(...).name() values in a map, then doing a find() in the map. You could map to an int that can be used in a switch statement, or to a function pointer. Better yet, you might look again at getting a virtual function inside each of the types that does what you need.
What you ask for is possible, it's also unlikely to be a good solution to your problem.
Effectively the if/else if/else chain is ugly, the first solution that comes to mind will therefore to use a construct that will lift this, an associative container comes to mind and the default one is obviously std::unordered_map.
Thinking on the type of this container, you will realize that you need to use the typename as the key and associate it to a functor object...
However there are much more elegant constructs for this. The first of all will be of course the use of a virtual method.
class Base
{
public:
void execute() const { this->executeImpl(); }
private:
virtual void executeImpl() const { /* default impl */ }
};
class Derived: public Base
{
virtual void executeImpl() const { /* another impl */ }
};
It's the OO way of dealing with this type of requirement.
Finally, if you find yourself willing to add many different operations on your hierarchy, I will suggest the use of a well-known design pattern: Visitor. There is a variation called Acyclic Visitor which helps dealing with dependencies.

dynamical binding or switch/case?

A scene like this:
I've different of objects do the similar operation as respective func() implements.
There're 2 kinds of solution for func_manager() to call func() according to different objects
Solution 1: Use virtual function character specified in c++. func_manager works differently accroding to different object point pass in.
class Object{
virtual void func() = 0;
}
class Object_A : public Object{
void func() {};
}
class Object_B : public Object{
void func() {};
}
void func_manager(Object* a)
{
a->func();
}
Solution 2: Use plain switch/case. func_manager works differently accroding to different type pass in
typedef enum _type_t
{
TYPE_A,
TYPE_B
}type_t;
void func_by_a()
{
// do as func() in Object_A
}
void func_by_b()
{
// do as func() in Object_A
}
void func_manager(type_t type)
{
switch(type){
case TYPE_A:
func_by_a();
break;
case TYPE_B:
func_by_b();
default:
break;
}
}
My Question are 2:
1. at the view point of DESIGN PATTERN, which one is better?
2. at the view point of RUNTIME EFFCIENCE, which one is better? Especailly as the kinds of Object increases, may be up to 10-15 total, which one's overhead oversteps the other? I don't know how switch/case implements innerly, just a bunch of if/else?
Thanks very much!
from the view point of DESIGN PATTERN, which one is better?
Using polymorphism (Solution 1) is better.
Just one data point: Imagine you have a huge system built around either of the two and then suddenly comes the requirement to add another type. With solution one, you add one derived class, make sure it's instantiated where required, and you're done. With solution 2 you have thousands of switch statements smeared all over the system and it is more or less impossible to guarantee you found all the places where you have to modify them for the new type.
from the view point of RUNTIME EFFCIENCE, which one is better? Especailly as the kinds of Object
That's hard to say.
I remember a footnote in Stanley Lippmann's Inside the C++ Object Model, where he says that studies have shown that virtual functions might have a small advantage against switches over types. I would be hard-pressed, however, to cite chapter and verse, and, IIRC, the advantage didn't seem big enough to make the decision dependent on it.
The first solution is better if only because it's shorter in code. It is also easier to maintain and faster to compile: if you want to add types you need only add new types as headers and compilation units, with no need to change and recompile the code that is responsible for the type mapping. In fact, this code is generated by the compiler and is likely to be as efficient or more efficient than anything you can write on your own.
Virtual functions at the lowest level cost no more than an extra dereference in a table (array). But never mind that, this sort of performance nitpicking really doesn't matter at this microscopic numbers. Your code is simpler, and that's what matters. The runtime dispatch that C++ gives you is there for a reason. Use it.
I would say the first one is better. In solution 2 func_manager will have to know about all types and be updated everytime you add a new type. If you go with solution 1 you can later add a new type and func_manager will just work.
In this simple case I would actually guess that solution 1 will be faster since it can directly look up the function address in the vtable. If you have 15 different types the switch statement will likely not end up as a jump table but basically as you say a huge if/else statement.
From the design point of view the first one is definitely better as thats what inheritance was intended for, to make different objects behave homogeneously.
From the efficiency point of view in both alternatives you have more or less the same generated code, somewhere there must be the choice making code. Difference is that inheritance handles it for you automatically in the 1st one and you do it manually in the 2nd one.
Using "dynamic dispatch" or "virtual dispatch" (i.e. invoking a virtual function) is better both with respect to design (keeping changes in one place, extensibility) and with respect to runtime efficiency (simple dereference vs. a simple dereference where a jump table is used or an if...else ladder which is really slow). As a slight aside, "dynamic binding" doesn't mean what you think... "dynamic binding" refers to resolving a variable's value based on its most recent declaration, as opposed to "static binding" or "lexical binding", which refers to resolving a variable by the current inner-most scope in which it is declared.
Design
If another programmer comes along who doesn't have access to your source code and wants to create an implementation of Object, then that programmer is stuck... the only way to extend functionality is by adding yet another case in a very long switch statement. Whereas with virtual functions, the programmer only needs to inherit from your interface and provide definitions for the virtual methods and, walla, it works. Also, those switch statements end up all over the place, and so adding new implementations almost always requires modifying many switch statements everywhere, while inheritance keeps the changes localized to one class.
Efficiency
Dynamic dispatch simply looks up a function in the object's virtual table and then jumps to that location. It is incredibly fast. If the switch statement uses a jump table, it will be roughly the same speed; however, if there are very few implementations, some programmer is going to be tempted to use an if...else ladder instead of a switch statement, which generally is not able to take advantage of jump tables and is, therefore, slower.
Why nobody suggests function objects? I think kingkai interested in solving the problem, not only that two solutions.
I'm not experienced with them, but they do their job:
struct Helloer{
std::string operator() (void){
return std::string("Hello world!");
}
};
struct Byer{
std::string operator() (void){
return std::string("Good bye world!");
}
};
template< class T >
void say( T speaker){
std::cout << speaker() << std::endl;
}
int main()
{
say( Helloer() );
say( Byer() );
}
Edit: In my opinion this is more "right" approach, than classes with single method (which is not function call operator). Actually, I think this overloading was added to C++ to avoid such classes.
Also, function objects are more convenient to use, even if you dont want templates - just like usual functions.
In the end consider STL - it uses func objects everywhere and looks pretty natural. And I dont even mention Boost

Changing behavior of an object at runtime

How can be changed the behavior of an object at runtime? (using C++)
I will give a simple example. I have a class Operator that contains a method operate. Let’s suppose it looks like this:
double operate(double a, double b){
return 0.0;
}
The user will give some input values for a and b, and will choose what operation to perform let’s say that he can choose to compute addition or multiplication. Given it’s input all I am allowed to do is instantiate Operator and call operate(a, b), which is written exactly how I mentioned before.
The methods that compute multiplication or addition will be implemented somewhere (no idea where).
In conclusion I have to change the behavior of my Operator object depending on the user's input.
The standard pattern for this is to make the outer class have a pointer to an "implementation" class.
// derive multiple implementations from this:
class Implementation
{
virtual ~Implementation() {} // probably essential!
virtual void foo() = 0;
};
class Switcheroo
{
Implementation *impl_;
public:
// constructor, destructor, copy constructor, assignment
// must all be properly defined (any that you can't define,
// make private)
void foo()
{
impl_->foo();
}
};
By forwarding all the member functions of Switcheroo to the impl_ member, you get the ability to switch in a different implementation whenever you need to.
There are various names for this pattern: Pimpl (short for "private implementation"), Smart Reference (as opposed to Smart Pointer, due to the fowarding member functions), and it has something in common with the Proxy and Bridge patterns.
I'm mentioning this only as trivia and can't unrecommend it more, but here we go...
WARNING DANGER!!!
A stupid trick I've seen is called clutching, I think, but it's only for the truely foolish. Basically you swap the virtualtable pointer to that of another class, it works, but it could theoretically destroy the world or cause some other undefined behavior :)
Anyways instead of this just use dynamic classing and kosher C++, but as an experiment the above is kind of fun...
Coplien's Envelope/Letter Pattern (in his must read book Advanced C++ Programming Styles and Idioms) is the classic way to do this.
Briefly, an Envelope and a Letter are both subclasses of an abstract base class/interfcae that defines the public interface for all subclasses.
An Envelope holds (and hides the true type of) a Letter.
A variety of Letter classes have different implementations of the abstract class's public interface.
An Envelope has no real implementation; it just forards (delegates) to its Letter. It holds a pointer to the abstract base class, and points that at a concrete Letter class instance. As the implementation needs to be changed, the type of Letter subclass pointer to is changed.
As users only have a reference to the Envelope, this change is invisible to them except in that the Envelope's behavior changes.
Coplien's examples are particularly clean, because it's the Letters, not the envelope that cause the change.
One example is of a Number class hierarchy. The abstract base declares certain operations over all Numbers, e.g, addition. Integer and a Complex are examples of concrete subclasses.
Adding an Integer and an Integer results in an Integer, but adding a Interget and a Complex results in a Complex.
Here's what the Envelope looks like for addition:
public class Number {
Number* add( const Number* const n ) ; // abstract, deriveds override
}
public class Envelope : public Number {
private Number* letter;
...
Number* add( const Number& rhs) { // add a number to this
// if letter and rhs are both Integers, letter->add returns an Integer
// if letter is a a Complex, or rhs is, what comes back is a Complex
//
letter = letter->add( rhs ) ) ;
return this;
}
}
Now in the client's pointer never changes, and they never ever need to know what the Envelop is holding. Here's the client code:
int main() {
// makeInteger news up the Envelope, and returns a pointer to it
Number* i = makeInteger( 1 ) ;
// makeComplex is similar, both return Envelopes.
Number* c = makeComplex( 1, 1 ) ;
// add c to i
i->add(c) ;
// to this code, i is now, for all intents and purposes, a Complex!
// even though i still points to the same Envelope, because
// the envelope internally points to a Complex.
}
In his book, Coplien goes into greater depth -- you'll note that the add method requires multi-dispatch of some form --, and adds syntactic sugar. But this is the gist of how you can get what's called "runtime polymorphism".
You can achieve it through dynamic binding (polymorphism)... but it all depends on what you are actually trying to achieve.
You can't change the behavior of arbitrary objects using any sane way unless the object was intended to use 'plugin' behaviour through some technique (composition, callbacks etc).
(Insane ways might be overwriting process memory where the function code lies...)
However, you can overwrite an object's behavior that lies in virtual methods by overwriting the vtable (An approach can be found in this article ) without overwriting memory in executable pages. But this still is not a very sane way to do it and it bears multiple security risks.
The safest thing to do is to change the behavior of objects that were designed to be changed by providing the appropriate hooks (callbacks, composition ...).
Objects always have the behaviour that's defined by their class.
If you need different behaviour, you need a different class...
You could also consider the Role Pattern with dynamic binding..i'm struggling with the same thing that you do..I read about the Strategy pattern but the role one sounds like a good solution also...
There are many ways to do this proxying, pImpl idiom, polymorphism, all with pros and cons. The solution that is best for you will depend on exactly which problem you are trying to solve.
Many many ways:
Try if at first. You can always change the behavior with if statement. Then you probably find the 'polymorphism' way more accurate, but it depends on your task.
Create a abstract class, declaring the methods, which behavior must be variable, as virtual.
Create concrete classes, that will implement the virtual methods. There are many ways to achieve this, using design patterns.
You can change the object behavior using dynamic binding. The design patterns like Decorator, Strategy would actually help you to realize the same.