0
Under review

Replace Conditional with Polymorphism - what about object creation?

Sylwester Wróblewski 2 years ago updated by Alexander Shvets 2 years ago 3
Let's say we have that class Bird with a type and that method to get speed. So creating new instance is probably just:
> new Bird(type)
After refactor we need to find all places where bird was created and replace them with new initialization. So in the end we need additional method/factory that contains switch statment for creating objects?

switch(type){
 case SOME_BIRD: return new SomeBird();
...
}

This leaves us with additional X classes for polymorphism classes and additional methods/classes for simple initialization, then when the new bird type is presented we need to create a new class and update instance creation. For my basic knowledge it would look like just extracting switch to external helper method would be more elegent also stripping data class from additional logic:

> float speed = getBirdSpeed(bird.getType());

Or is there some easier/more elegant solution to that problem I don't know about? Just started a book and jumped from one link to another since it should not be a problem, but this raised my curiosity.

+1
Under review

Hi Sylwester!

Thanks for the good question!

This refactoring makes maximum sense when there are several behaviors that involve switch. So, let's take on a bit realistic example: working with various SQL database servers.

Imagine that you develop a CMS that can work with various types of SQL servers, such as MySQL, MSSQL, Postgres, etc. Your CMS would act as a client and send SQL queries to the currently configured type of SQL server. That query should be executed in the format that the particular type of SQL server understands. As you might imagine, there's a whole bunch of possible SQL queries and while all these server types implement SQL, their syntax may still somewhat differ. Therefore you'll need the way to distinguish between DB types in various queries. Instead of complicating the main CMS code with those switches, you'd want to extract each possible SQL syntax in their own subclass. Your CMS would work with these objects through the abstract interface. And there would be a single switch somewhere that initializes the currently configured SQL server object. This is the way all the modern CMSes work with databases.

Please let me know if this clears the question somewhat.

Ahhhh I see. So it is more useful for cases where we have Logic classes that require some configurable resources. Like CMS, FTP clients, connections overall etc. where it is convinient to save some initial data required for connection inside them and then just call a single method "getFile(whatData)", "getMultipleFiles(list of whatData) or "doesFileExist(file)". All those methods would require a switch to check concrerte implementation based on connection type and now polymorphism will take care of all the nuances concerning concrete implementation. And since it all shares the same interface to extend it by new implementation you just need to write a new class implementing that interface and you are redy to go. No more switches/if's needed. Also there is no need to worry about checking if new implementation did break existing ones since it is decoupled.

Yeah, great summary! I plan to update this whole section in the second edition of the course, as the current example doesn't shine in comparison to the usefulness of this refactoring.