Design Pattern: Simple Factory and Cheesecake Factory

Design Pattern: Simple Factory and Cheesecake Factory

Design patterns in life and Ruby – gain an intuitive understanding of OO design patterns by linking them with real-life examples.

 

Factory Patterns are about encapsulating object creation.

But before diving into details of these patterns, let’s talk about cheesecakes. Because cheesecakes are about … happiness! 😝😋😍

Let’s focus our gaze at six of my personal favorites: Original Cheesecake, Ore0 Cheesecake, Coffee Cheesecake, Tiramisu Cheesecake, S’mores Cheesecake, and Hazelnut Cheesecake.

 

Here is how we make a cheesecake:

def make_cheesecake(type)
  cheesecake = nil
  
  case type
    when 'oreo'
      cheesecake = OreoCheesecake.new
    when 'coffee'
      cheesecake = CoffeeCheesecake.new
    when 'tiramisu'
      cheesecake = TiramisuCheesecake.new
    when 'smores'
      cheesecake = SmoresCheesecake.new
    when 'hazelnut'
      cheesecake = HazelnutCheesecake.new
    else
      cheesecake = OriginalCheesecake.new
  end
  
  cheesecake.make_crust
  cheesecake.add_layers
  cheesecake.bake
  cheesecake.refrigerate
  cheesecake.add_toppings
  cheesecake
end

Create a cheesecake instance based on the selected type -> Make crust -> Add layers on top of the crust -> Bake it -> Refrigerate it -> Add toppings to the cake -> Return the cake! 🍰🍰🍰

 

Wait … that Mango key lime cheesecake looks very tempting. 🤔🤔🤔

Let me add it to my list:

def make_cheesecake(type)
  cheesecake = nil

  case type
    when 'oreo'
      cheesecake = OreoCheesecake.new
    when 'coffee'
      cheesecake = CoffeeCheesecake.new
    when 'tiramisu'
      cheesecake = TiramisuCheesecake.new
    when 'smores'
      cheesecake = SmoresCheesecake.new
    when 'hazelnut'
      cheesecake = HazelnutCheesecake.new
    when 'mango'
      cheesecake = MangoKeyLimeCheesecake.new
    else
      cheesecake = OriginalCheesecake.new
  end
  
  cheesecake.make_crust
  cheesecake.add_layers
  cheesecake.bake
  cheesecake.refrigerate
  cheesecake.add_toppings
  cheesecake
end

 

One second …

I have been having too much caffeine lately. I don’t want the coffee cheesecake to be on my list anymore. Let me update the make_cheesecakemethod again.

def make_cheesecake(type)
  cheesecake = nil

  case type
    when 'oreo'
      cheesecake = OreoCheesecake.new
    when 'tiramisu'
      cheesecake = TiramisuCheesecake.new
    when 'smores'
      cheesecake = SmoresCheesecake.new
    when 'hazelnut'
      cheesecake = HazelnutCheesecake.new
    when 'mango'
      cheesecake = MangoKeyLimeCheesecake.new
    else
      cheesecake = OriginalCheesecake.new
  end
  
  cheesecake.make_crust
  cheesecake.add_layers
  cheesecake.bake
  cheesecake.refrigerate
  cheesecake.add_toppings
  cheesecake
end

 

Oooh…. they have a low carb version of cheesecake. It’s always nice to have a low carb option on the list. It needs to be on my list!

def make_cheesecake(type)
  cheesecake = nil

  case type
    when 'oreo'
      cheesecake = OreoCheesecake.new
    when 'tiramisu'
      cheesecake = TiramisuCheesecake.new
    when 'smores'
      cheesecake = SmoresCheesecake.new
    when 'hazelnut'
      cheesecake = HazelnutCheesecake.new
    when 'mango'
      cheesecake = MangoKeyLimeCheesecake.new
    when 'low_carb'
      cheesecake = LowCarbCheesecake.new
    else
      cheesecake = OriginalCheesecake.new
  end
  
  cheesecake.make_crust
  cheesecake.add_layers
  cheesecake.bake
  cheesecake.refrigerate
  cheesecake.add_toppings
  cheesecake
end

 

Since the first time we defined make_cheesecake, we have updated it three times. Each change was for the exact same reason — to update my cheesecake list. And everything else, make_crust, add_layers, bake, refrigerate, and add_toppings, remained the same.

 

Sorry for keep changing my mind every three seconds.

But as they say:

change is the only constant in life (and software development).

 

To be honest, we will need to change the list at least one more time: pumpkin cheesecake will be available from September. It’s WORLD FAMOUS! Without a doubt, we need to add it to the list once September arrives.

Oops, that means we need to remove it from the list when the holiday season passes.

 

It’s obvious that my cheesecake list changes often.

In this case, there is a design principle we should try to follow:

encapsulate what varies.

 

It’s time for a Cheesecake Factory!

 

class CheesecakeFactory
  def create_cheesecake(type)
    case type
      when 'oreo'
        OreoCheesecake.new
      when 'tiramisu'
        TiramisuCheesecake.new
      when 'smores'
        SmoresCheesecake.new
      when 'hazelnut'
        HazelnutCheesecake.new
      when 'mango'
        MangoKeyLimeCheesecake.new
      else
        OriginalCheesecake.new
    end
  end
end

The CheesecakeFactory is a simple class. All it does is creating and returning the correct cheesecake based on a given type.

With the help of CheesecakeFactorymake_cheesecake method becomes much simpler.

def make_cheesecake(type)
  factory = CheesecakeFactory.new
  cheesecake = factory.create_cheesecake(type)
  cheesecake.make_crust
  cheesecake.add_layers
  cheesecake.bake
  cheesecake.refrigerate
  cheesecake.add_toppings
  cheesecake
end

The make_cheesecake method now can focus on the actual steps that go into making a cheesecake without having to worry about different cheesecake types.

Our CheesecakeFactory is an example of using the Simple Factory. Simple Factory is used for encapsulating object creation. 

 

The Factory Pattern Family

Besides Simple Factory, there are two other members of the Factory Pattern family: Factory Method and Abstract Factory. We won’t go into details of these two patterns.

In a nutshell, Factory Method and Abstract Factory use inheritance. Factory Method is about creating one type of object and Abstract Factory is about creating a family of different types of objects. All three of them are about encapsulating object creation by using the design principle: encapsulate what varies.

 

Benefit of using Simple Factory

Pulling the logic of creating the correct cheesecake based on a given type is a small move that gives us lots of benefits. The biggest benefit being we can modify the cheesecake list without touching the make_cheesecake method and its test. All we need to do is update the CheesecakeFactory class and leave make_cheesecake and its test alone.

We want to separate the parts that vary often from the stable parts. Because each time we modify a part of our code, we might introduce bugs. The parts that vary are the fragile parts of our system. We want to keep the stable parts away from the fragile parts, so if we did introduce bugs when updating a part of the system, it would be easier for us to locate the bug.

 

Takeaways:

  1. Factory Patterns are used for encapsulating object creation.
  2. Design Principle: encapsulate what varies.

 

I need to run to get a cheesecake now.

Next time, we will take a look at some waaaaaaaaffles!

Don’t forget to subscribe so you won’t miss the next post 🙃.

Enjoyed the article?

My best content on Software Design, Rails, and Career in Dev. Delivered weekly.

Unsubscribe at anytime. I'll never spam you. Powered by ConvertKit

Leave a Comment