Crazy Factory Pattern And Direct Object Creation Problem

Coverage Topic

  • Direct object creation design
  • Direct object creation problem analysis
  • Connected to anti pattern
  • Concept of factory pattern
  • When, where and why to use
  • Benefit of factory pattern
  • Conditional factory pattern
  • Problem analysis of conditional factory pattern
  • Improvement of traditional factory pattern
Let's drill down the basic concept

Where Am I?

Let's see the points from the 'Initial Thoughts' and 'Most Common Excuses'. If you have any common points, then mark those points.

Initial Thoughts
  • I don't Know about the code duplication anti-pattern
  • I'm confused about tight coupling and loose coupling dependency
  • I'm not clear about the open-closed principles
  • I hear the term Design Pattern; but it's very complex to learn
  • It looks like factory pattern, factory method and abstract factory
  • Unit testing? Why should I spend time to learn it?
Most Common Excuses
  • Just because of the interview, I learned the definition of the factory pattern.
  • My codes are still working without factory pattern.
  • Don't know when, where and why - it's really applicable.
  • I'm used to creating objects directly. My friends are also doing this.
  • Code delivery is important and sooner is better.
  • I'm not responsible to write down the unit testing.
  • I can test my methods. Therefore, if I write any test methods. Say, if the name of the test method are Test1, Test2 ...etc., then it is called unit testing. I'm confused about the unit testing and the integration testing.

Moral Points

Well, if you have any common points, then still you are in the safe zone. You are thinking about your current stage. If so, then it tends to move you to the next stage. At the beginning, it is very common to learn about the frameworks and syntaxes; regardless of the patterns and practices.

A Few More Important Points
  • If you are a lazy developer, then you need pattern and practices because, they are already proven solutions. You don't need to think about the design. Just follow the guideline to solve the problems.
  • It is the communication term programmer to programmer. For example, if you say, you have a factory pattern class to create the objects, then anybody will understand. You don't need to explain your codes and what do you mean. Even if, when the code reviewers will see the term, they will understand before reviewing your codes.
  • But if you are not a lazy developer, then find a solution and try to use your own solution for at least TWO or more similar problems. Well, congratulations!! You have your own pattern and you are safe to use it for similar problems.

The Problem

Recently, I was working in a team. I picked up a user story. Technically, I need to create an object from a family of color objects on runtime according to the selected-colors.

Use-Case Diagram

Therefore, pick any color and create a color object from a family of color objects.

Direct Color-Object Creation Class Diagram

In the above code, a color-type is passing into the color-picker and it is creating the color-object. Finally it returns the color information.

Therefore, in the class diagram, main focus points are:
  • ColorType: enum
  • ColorPicker: Direct color objects (red, green, blue) creator class.
Implementation According to the Class Diagram

Program Class

In these class, there is an instance of colorPicker object. I'm just passing the colorType into it to get the color information.

Implementation of Color-Picker Class

It was traditional implementation. The above code was functional and there was no compilation error. But the team rejected the wonderful implementation. Why did they reject it?

Direct Object Creation Problem Analysis from the Design


Unit Testing

Unit testing is impossible because of the tight-coupling dependency.

Explanation Why: First principle of unit testing states “Test the logic of the class only, nothing else”.

  • If you have dependencies in the class, then it should be loosely coupled; otherwise, object mocking is not possible.
  • If you call dependency directly inside the method of the class without object mocking, then this is not unit testing. This is something else, but not unit testing. Most of the time, this is the most common mistake.

Suppose, “GetColorByColorType()” is a candidate for the unit testing. Now look at the below codes.

It has 3 direct tightly-coupled dependencies

  1. GreenColor greenColor = new GreenColor();  
  2. RedColor redColor = new RedColor();  
  3. BlueColor blueColor = new BlueColor();  

GetColorInformation is called by all of these 3 objects. But we don’t want to test the logics of the GetColorInformation inside the GetColorByColorType method.

That’s why, we need object mocking. Object mocking of the interface/abstract class provides the dummy implementation of the GetColorInformation. That's how, we don’t need to know the logic of the method of GetColorInformation.

Requirement before Making Mock

  • The class can’t be sealed
  • The method can’t be static; but if you need then use adapter pattern.
  • You can mock if Interfaces, Abstract methods or properties or Virtual Methods or properties on concreate classes.

Mock Framework

There are many object mocking framework like Typemock Isolator, Rhino Mocks, Moq and NMock. You can use any one of them.

Code Duplication

The main problem for code duplication is that, if something goes wrong in the code, then you have to change everywhere. Somehow, if you forget to update the change, then it will break your code. Code duplication is an anti-pattern. So, avoid it.

Violation of Open-Closed Principle

Suppose, if I want to add another ultraviolet color, then I need to add one more if-else or switch case statement for the new extended color.



Open-Closed Principle

It states that "Modules and Methods should be open for extension but closed for modifications."

Therefore, additional if-else or switch-case statement is required for ultraviolet color. This modification is the violation of the open-closed principle. Because, new color extension is fine; but I shouldn’t touch the “ColorPicker” class.

What to Do

Extend new color, but don’t modify anything into ColorPicker class.

Solution

I need a solution to avoid these kinds of problems. Well, I’m dynamic; I have already learned how to fix this problem. Therefore, factory pattern is used to create an object from a family of classes.

Factory Pattern

Creates an instance of several derived classes

In the above class diagram, ColorFactory class is responsible to create the objects of the RedColor or GreenColor. RedColor and GreenColor are a family of classes.

Implementation of Factory Pattern

A parameter is passed into GetInstance method in the ColorFactory class. It is called parameterized Factory Method. Therefore, an object is returned depending on the parameter passed into it.

For example, if I need the Green-Color object, I should have to pass Green as a parameter. As a result, I will get back an object of GreenColor.

When, where and why to use

  • When I don't know which object I must use at runtime. Dynamic way to create object at runtime.
  • I'm going to hide the object creation; so, I need it.
  • If you need to change any type, just change into factory class instead of changing it in multiple places.

Benefit of Factory Pattern

  • Unite Testing.
  • Removing code duplication.
  • Improving Readability.
  • Reusable
  • Extensibility
  • Communication term programmer to programmer

Solution Using Conditional Factory Pattern

I have solved the problem using the factory Pattern.

Full Class Diagram according to Factory Pattern


Implementation according to Class Diagram

Factory Class

The below given class returns a color object according to the colorType.

ColorPicker Class

The below given class returns a color information after getting color object from the factory class.



Improvement using Traditional Factory Pattern

Therefore, we have solved the following problems from the design: code duplication, tight coupling and extension problem.

Okay! But ...

If I want to add another color (say, Black-Color), then I need an if-else/switch-case statement into the GetInstance method of the factory class. This is the violation of open-closed principle. I shouldn’t modify the “Color Factory” class.

Factory Pattern without Conditional Statement

If-else or switch-case statement is killing me now. Well let’s try to get rid of this problem. There are several ways to solve the problem. I’m going to use reflection to solve the problem. Although, reflection is always expensive and generally we avoid it, unless we really need it.

Basic Concept
  • LoadFrom
    There is an assembly class in the System.Reflection namespace. I need it to load the assembly.
    1. Assembly assembly = Assembly.LoadFrom(assemblyPath);  
  • CreateInstance
    I need another method of CreateInstance to create the object. I will get it into the Activator class of the System namespace.
    1. Activator.CreateInstance(type);  
ColorFactory Class Implementation

Now I don’t need to modify the Color-Factory. So, now I’m not violating the open–closed principle.

ColorMapper Class Implementation

In the ColorMapper class, I have used a dictionary; because, there is a chance to make a mistake; if I use directly namespace in the code or I can forget the name of the namespace anytime.

The key of the dictionary is holding the Enum type of the color. The value of the key is the namespace of the implemented class of the IColor interface.

  1. using System.Collections.Generic;  
  2. namespace Rony.DesignPattern.Color {  
  3.     public class ColorMapper {  
  4.         public static Dictionary < ColorType, string > ColorClassMapperDictionary = new Dictionary < ColorType, string > () {  
  5.             {  
  6.                 ColorType.Red, "Rony.DesignPattern.Color.RedColor"  
  7.             }, {  
  8.                 ColorType.Green,  
  9.                 "Rony.DesignPattern.Color.GreenColor"  
  10.             }, {  
  11.                 ColorType.Blue,  
  12.                 "Rony.DesignPattern.Color.BlueColor"  
  13.             }  
  14.         };  
  15.     }  
  16. }  

The above the scenarios describes when, where and why we need the factory pattern. I have implemented factory pattern two different ways using the traditional practice and reflection. But reflection is always costly. Generally, we avoid to use reflection; unless, it is really required. So, if you need factory pattern, then you can use conditional or switch-case statement. It is acceptable.

So, let's go down into the factory pattern and start to think. Don’t let you down. Find out the limitation and wash it out from the design.