DEV Community

Cover image for Don’t use if-else blocks anymore! Use Strategy and Factory Pattern Together

Don’t use if-else blocks anymore! Use Strategy and Factory Pattern Together

Tamer Ardal on October 18, 2024

As we move forward in a project, lost in if-else blocks, struggling with complex conditions and repetitive code, we look for a solution. But why sh...
Collapse
 
lexlohr profile image
Alex Lohr

I know this pattern under the name of branchless programming - the factory pattern is usually an OOP pattern where you define objects through methods, ie. new MyProduct().color(Colors.Blue).size(Size.XL).build().

Collapse
 
schmoris profile image
Boris

That sounds like a version of the builder pattern to me, might be mistaken tho.

Collapse
 
mahmoudalaskalany profile image
Mahmoud Alaskalany

That is a builder pattern

Collapse
 
parables profile image
Parables

Great article but the title is a bit of an over-statement....
It sounds like if-else statements are a terrible thing...

This is not a silver bullet and for newbies reading this, don't go refactoring all your if-else blocks with this...

Understanding and mastering Design Patterns is a skill every developer needs to learn but most importantly, knowing when to use the right tool for the right job.

Sometimes, a simple if-else statement is the best solution... Know when to refactor

Collapse
 
nozibul_islam_113b1d5334f profile image
Nozibul Islam

Great article! Your explanation of how to replace if-else blocks with the Strategy and Factory patterns is clear and practical. The use of enums and EnumMap for organizing payment strategies is a clever approach that enhances both maintainability and readability. It's a perfect example of applying design patterns to create a more scalable solution in software development. I'm definitely inspired to implement this in my own projects!

Suggestion:
Consider adding a section that discusses potential pitfalls or challenges when implementing these patterns. For instance, it could be helpful to address how to manage dependencies between payment strategies or how to handle exceptions in a way that maintains clarity and avoids overly complex error handling.

Collapse
 
tamerardal profile image
Tamer Ardal

Thanks for your suggestion 🙂

Collapse
 
khangnd profile image
Khang

Why does comment sound like AI to me? 🤔

Collapse
 
blafasel3 profile image
Maximilian Lenhardt

I like this pattern, much more concise.

I would like to suggest a little improvement: I would use a switch Statement on the payment type instead of the map inside the PaymentFactory. Then you just get a compile error because a case is missing here if you happen to add another payment type. The map will fail at runtime :)

Collapse
 
cicirello profile image
Vincent A. Cicirello • Edited

Your PaymentFactory class isn't a factory. In the factory pattern, a factory method instantiates new object instances. In your example, the getPaymentStrategy method returns one of three pre-existing objects depending on payment type. Call that method again with same payment type and you get same payment strategy instance. This isn't a factory.

Collapse
 
jwp profile image
John Peters

I recall reading something similar to this on CodeProject 15 years ago. Was interested then but never implemented it. Today I find it rare to have huge if then or switch statements. Thanks for reminding me....

Collapse
 
kurealnum profile image
Oscar

Just a heads up that you can add highlighting to the code blocks if you'd like. Just change:

code block with no colors example

... to specify the language:

code block with colors example

More details in our editor guide!

Collapse
 
tamerardal profile image
Tamer Ardal

Wow thanks, I didn't know that

Collapse
 
dotnetfullstackdev profile image
DotNet Full Stack Dev

@tamerardal Nice article! Its very pin to the point and great explanation too.
I tried similar article, with little advanced by adding selection of

  • card(bankcard1, bankcard2..etc),

  • UPI (upi1,upi2... etc),

  • online banking (online banking1, onlinebanking2.. etc)

Have a look and add your thoughts and suggestions
Mastering Multiple Payment Gateways with Strategy and Abstract factory Combo

Collapse
 
citronbrick profile image
CitronBrick

You can use the below syntax to enable syntax highlighting in Dev.to

triplebacktick java
code
triplebacktick

Collapse
 
efpage profile image
Eckehard

Your titel is too much click bait for me. There is nothing wrong with IfThenElse. Any programming construct will probably be confusing if used in the wrong situation. But this is more of a problem with the programmer than with the method.

Look at this example.

if (x>0) 
   console.log("positive")
else 
   console.log("negative")
Enter fullscreen mode Exit fullscreen mode

Please show me how this could be made simpler with the factory pattern?

You can simplify this with ternary operator like this:

(x>0) ? console.log("positive") : console.log("negative")
Enter fullscreen mode Exit fullscreen mode

But this will be harder to read, as the ternary operator is meant to be used in a different way like this and in this case it will be better readable:

console.log((x>0) ? "positive" : "negative")
Enter fullscreen mode Exit fullscreen mode

There have been multiple posts about escaping the if/else hell like here, but it depends much on your task which one fit´s best.

If you need a "default"-case, you can use this:

function checkStatus(status){
   const statusList = {
      available: 'The user is currently available',
      busy: 'The user is currently busy',
      away: 'The user is currently away from keyboard',
      breaktime: 'The user is currently having a good lunc'
   }

   return statusList[status] ?? 'Option not found' 
}
Enter fullscreen mode Exit fullscreen mode

Another pattern I like much is this a special form to use the ternary operator:

let txt = 
paymentType.equals("CREDIT_CARD")  ? "Processing credit card payment..." :
paymentType.equals("DEBIT_CARD")) ? "Processing debit card payment...") :
paymentType.equals("CRYPTO")) ? "Processing crypto payment...") : false;

if (txt) System.out.println(txt) 
else throw new IllegalArgumentException("Invalid payment type");
Enter fullscreen mode Exit fullscreen mode
Collapse
 
tamerardal profile image
Tamer Ardal • Edited

Thank you very much for your comment. I think you missed the point a little bit. I did this to keep it a bit simple, but either your or my examples do not represent the real-world situation.

For example, no one logs if the payment type is a credit card. In the real world, we do some service calling, then insert or update data in the database, and finally respond to an API call.

In this scenario, every if-else block has too many code lines. This is very messy and contrary to SOLID principles. And I've seen people doing extremely complex jobs using too much if-else, which makes it very difficult for newcomers to understand the code.

Of course, if you are a beginner or actions are simple, you can use if-else blocks. I also use if-else blocks to do simple checks. Not using them for simple operations would be overengineering.

And I admit the title is a bit click-bait...

In summary, this article was not for beginners, but for those who are already working on a large project and using if-else or switch-case in complex operations.

By doing so, if another method is added in the future, we comply with the Open-Closed Principle by creating new classes without touching the existing code, rather than adding a new else if in the service.

I hope I have explained who this article is more suitable for.

Collapse
 
efpage profile image
Info Comment hidden by post author - thread only accessible via permalink
Eckehard

Dont use cars anymore, I invented a rocket...

I know things can get very messy and it is good to know solutions for that. But this is a very special solution to a very special problem and I suppose, there are many ways to solve this in a structured manner. If you tried to use If/else for that, it shows just your limited experience, it has nothing to do with limitations of the if/else construction.

Maybe you sould be a bit more careful with your titles...

Collapse
 
gregorygaines profile image
Gregory Gaines

I wouldn't say never use if/else. What if inside credit card payments you have chip, tap, swipe, Google Pay, Apple Pay.

Now we have ChipCardPayment, TapCardPayment, SwipeCardPayment, GooglePayCardPayment, ApplePayCardPayment.

If you don't use if/else your're stuck creating a class for every condition. What about non oop languages, they won't be able to fully follow this principle.

Collapse
 
vilim2000 profile image
Jesse Sargent

Great article!

Collapse
 
nsadisha profile image
Sadisha Nimsara

Great article. Clearly explained how we can make use of these concepts. Appreciate it.

Collapse
 
tamerardal profile image
Tamer Ardal

Thanks 🙂

Collapse
 
artsem_miklashevich profile image
Artsem Miklashevich

btw, you are still using if in the PaymentService, also strategy.get probably uses 'if'

Collapse
 
rgunczer profile image
Robert Gunczer

I would never replace something so simple as if-else with more abstraction and patterns.
The only thing I would do is to use "switch expressions" and that's it.

this is "merchant of complexity" category

Collapse
 
skyjur profile image
Ski • Edited

As you can see in this article, using design patterns instead of if-else blocks to manage payment transactions makes the project more developable and improves the readability of the code. Try these patterns in your next project instead of using if-else blocks.

To be fair what I see is that you have replaced 8 simple lines of code with lots of code that doesn't do a thing. This is the opposite of "improves the readability" and the opposite of "more developable". Strategy pattern is overkill in most cases except for rare ones and you didn't provide good examples where strategy pattern would be a good fit except for one example where it's overkill and makes everything more complicated without a reason.

Collapse
 
engali_badouin_609c18c444 profile image
EngAli Badouin

Hello Tamer, thank your for the appreciated tutorial.

i need to say more people judge about article without knowledge, some people see if else best and some see more classes wil be created.

you guys should read more about SOLID principles because most of all design pattern based on it.

also solid and design pattern benefit wont appear with small business, always appear with big projects big business when you need to apply clean Architecture for your project.

we always face big problems with switch cases and else if in projects and finally we replace it with strategy DP.

Read more learn more i believe DP the best design to make your code clean, readable and maintainable.

Thank you all.

Collapse
Collapse
 
saugata_guha profile image
Saugata Guha • Edited

Be careful, it might sound good and your ego might get a boost, when no one is understanding you. The code will get thrown out, if the next person do not understand it. You might say, that the guy is a bad programmer, it does not matter, all your work goes down the drain, it will be re-written. Very basic programming fact, keep it simple, otherwise, you yourself will not understand it after a while.

You can use a switch statement instead of a long if then else statement.
I will be very careful about the person who says "Don't use if-else blocks anymore"
Good luck.
These are good for publishing papers.

Collapse
 
jeromevillamor profile image
Jerome Ryan Villamor

Based on your example, I'll go with if-else. Simpler and cleaner. You can refactor it once it becomes bigger.

Collapse
 
aiosoftware_dev profile image
Andrei AIO Software

Is this only for Java ?

Collapse
 
tamerardal profile image
Tamer Ardal

Of course is not. You can use it in every OOP Language.

Some comments have been hidden by the post's author - find out more