Introduction to Burger Delivery Application Design
Imagine managing a burger restaurant with a custom delivery app. Each burger type, beef, veggie, or chicken, is represented by a class. Initially, the app creates burger objects based on client orders, prepares them, and returns the result.
Challenges with Initial Implementation
- Concrete burger classes (BeefBurger, VeggieBurger) differ and do not share a common interface initially.
- Method returning burger objects is limited to a single type, hindering flexibility.
- Adding new burger types requires modifying existing code, violating the Open-Closed Principle.
- Duplication of burger creation logic leads to maintenance challenges.
Introducing a Common Base Class
Creating an abstract Burger class or interface to unify common behaviors:
- Allows the method to return a unified type.
- Simplifies code by moving shared methods into the base class.
Limitations and Need for Encapsulation
- The
orderBurgermethod remains open for modification when new burger types are added. - Introducing if-statements for each new burger violates the Single Responsibility Principle.
Simple Factory Idiom
- Encapsulate burger creation into a single
BurgerFactoryclass. - Factory's sole responsibility is creating burger objects.
orderBurgercalls the factory, passing burger type to get the correct burger object.- Centralizes creation logic and isolates concrete burger types within the factory.
Why Simple Factory Is Not a Full Pattern
- Factory still requires modification to add new burger types (adding if-conditions).
- Does not fully adhere to the Open-Closed Principle.
Transition to Factory Method Design Pattern
Key Concepts:
- Move burger creation back to an abstract
Restaurantclass. - Define an abstract factory method
createBurger()to be implemented by subclasses. - Subclasses like
BeefBurgerRestaurantandVeggieBurgerRestaurantdecide which burger to instantiate. - The
orderBurgermethod uses this factory method to obtain the burger, decoupling from concrete types.
Benefits:
- Delegates object creation to subclasses, enabling extensibility.
- Adheres to SOLID principles, especially Open-Closed and Single Responsibility.
- Promotes scalability: new burger types mean just adding new subclasses without changing existing code.
UML Class Diagram Overview
- Product interface: Burger
- Concrete Products: BeefBurger, VeggieBurger
- Creator class: Abstract
Restaurantwith factory method - Concrete Creators: Subclasses implementing
createBurger()for specific burger types
When to Use the Factory Method Pattern
- Unknown exact types at compile time
- Need for extending product types independently
- Desire to centralize creation logic and reduce code coupling
Real-World Extension Scenario
- Opening a new Italian-style restaurant delivering the same burgers but prepared differently.
- Adding new creation logic inside existing factories would again violate Open-Closed Principle.
- This scenario motivates more advanced patterns like the Understanding 7 Essential Software Design Patterns (covered in next video).
Conclusion
The Factory Method pattern organizes code to create products flexibly and maintainably, ideal for applications like burger delivery systems. It supports clean extensions and adheres to key software design principles, ensuring the app remains robust as the menu grows and changes.
For a deeper understanding of evolving application architectures, consider exploring Understanding Hexagonal Architecture: Transforming MVC Applications, which complements the scalability and maintainability goals discussed here.
What's up geeks and welcome to the channel!
Imagine you have a burgers restaurant and for this restaurant you created a delivery
application that delivers burgers Now if each type of burger we
deliver is represented by a class
then the code backing the delivery and production
of these burgers can be written as follows after receiving our client request our application
will identify the food it needs to prepare and based on this information
it will proceed by creating the
object corresponding to this type of burger,
prepare it, and then return it to the user however you see there's a slight limitation here
as the BeefBurger and VeggieBurger objects you are creating represent different types of products
and the method we are implementing here can
only return a single type a single object
therefore if these products do not have a common base class or interface we won't be
able to proceed with such an implementation So let's create a base class for our products and
try to use it within the code of our application
this class will be the Burger class
Now on top of abstracting our two products into a single class,
what we can also do is extract the common behaviors of these products to this
class as they are already implementing them
Okay our application looks complete now
but when we see code like this we know that when things change
like if we add new recipes to our delivery menu or more products to our restaurant
we're going to have to open
this code and change it
and that violates our open-closed and single responsibility principles
We'll also end up writing the same piece of code in several places in the
app making things even worse
So what do we do? Well let's look
at what varies and encapsulate it! When our restaurant grows and changes over time we
are going to add and remove recipes from the menu So in the second version of our app we removed the
veggie burger and added the chicken burger option
you can clearly see that the variety of
food we can deliver is getting in the way of closing this code for modification
and as long as our restaurant is open this code is going to remain open
To fix this what we do is take our
burger's creation code and encapsulate it,
separate it into a class called a Factory. Why a factory? because this is a
class whose sole responsibility is creating burgers, it's a burger factory.
Now anytime we want to order something
from our restaurant
we'll call this method, pass it a type, and after figuring it out,
the method will return the requested order for us that implements the Burger class
Now all this code is in one place nicely
separated from the rest of the restaurant code
and to integrate it back in our original method what we have to do is create a factory object
pass to it the type and boom our food is ready our orderBurger method no longer has to worry
about the concrete type of the burger requested
because whatever it is we know that
it will implement the Burger interface and that's all we care about.
We call this design the Simple Factory Idiom and our example can be represented by
the class diagram you see in front of you
it starts with the client of the factory
in our case the Restaurant class itself then we have our Factory which is the only place
where the concrete type of burgers is known and then we have our concrete
products, the burgers our restaurant
delivers via the app we are implementing,
all concrete products must implement the same interface or abstract product.
Now, one thing to note is that the simple factory we've been discussing
since the beginning of this video
is not a full-fledged official pattern it
is more of an idiom that's commonly used however it is the first step in understanding one
of the most powerful design patterns out there: The Factory Method Design Pattern.
This pattern is a creational design pattern,
it loosens the coupling of a given code by
separating the product's construction code from the code that uses this product.
In our previous example the product was the burgers we are delivering.
So let us go back to this example to
try and see together why the implementation we did
isn't considered a full-fledged design pattern. When we encapsulated the creation logic
of our burger in the simple factory class we isolated this logic and created a class
whose sole purpose is creating burger objects
by doing this we followed the single
responsibility principle and that's great! However if you look closely you will see that this
class on its own is still open for modification and when we add more recipes to our menu we
will have to add if-statements to this method
and one way to fix this is by applying
the factory method design pattern. To do that let's remove our simple factory
class and put back the creation logic and the orderBurger method inside the
Restaurant class to start from scratch.
Okay, the first thing we need to
do is abstract the restaurant class why are we doing that?
Well it's because the createBurger method that used to exist in the simple factory we had
will now become an abstract method inside
the Restaurant class
this method is the factory method and will be implemented by
the sub-classes of the restaurant class in this example and based on the burgers
we are delivering these subclasses will
be the BeefBurgerRestaurant
and the VeggieBurgerRestaurant You see that is actually how you pinpoint
the usage of a factory in a given code as the factory method design pattern
relies heavily on inheritance
it delegates objects creation to subclasses
that implement the factory method. So after defining an interface for our
products in this case the Burger interface we let creator subclasses decide
which class to instantiate
and that is exactly what we are
doing in this implementation. Okay now all that is left to do is replace
the creation code inside our business logic or the orderBurger method with the factory method
Notice that the orderBurger method is no longer
dependent on the request object
and that's because we don't need it as the users of our restaurant
can now directly instantiate and invoke the concrete restaurant class implementation they need
and the correct prepared burger will
be returned to them.
Now I want you to take a look at the structure of the factory method
pattern represented using a UML class diagram as you may encounter it while
going through different references.
Let's try to relate this structure
to our delivery application example the Product interface and the
ConcreteProducts obviously represent the burger classes in our example
The Creator class however, the one
housing the factory method, was represented
using the restaurant class in our example And finally the concrete creators are represented
by the different restaurant classes in which the creation process of our burgers is defined.
Okay now you know how to implement
the factory method pattern
but when should you use this pattern? should you apply it on all parts of your
application that have to do with creation stuff? Well if you have no idea beforehand
of the exact types and dependencies
of the objects your code will work with
then it is probably a hint that you should make use of this pattern right from the beginning
as the factory method makes it easy to extend the product construction code independently
from the rest of the application
and hence allows you to introduce
new types of products into the program without breaking existent client code
by doing this you wouldn't only be providing the users of your application with a
way to extend its internal components
but also and most importantly you will
be following and applying the open-closed principle and the single responsibility principle
as you are centralizing the product creation code in one place in the program.
Now before ending the video I want you
to imagine that your burger business boomed
and you decided to open another restaurant. This restaurant will deliver
the same burgers you have however this one will
prepare them the Italian way.
Great news right? but what about
the delivery application and the factory method design pattern we used?
Adding the Italian option inside the implementations of the abstract factory method
will lead to something like this
you can clearly see that this code
is kinda open for modification right? and on top of this we now have the need
to be dependent again on the request object provided to us by the client
but how could our code break even
though we are applying the factory method pattern?
This question will be answered in the next video of this series: The Abstract Factory Pattern.
So that's it for this video, I hope it was helpful, thank you guys for watching, take
care and I will see you in the next one!
The initial approach has concrete burger classes without a common interface, returns objects of a single type, and requires modifying existing code to add new burger types, which violates the Open-Closed Principle and leads to duplicated creation logic.
Creating an abstract Burger class or interface unifies shared behaviors, allows methods to return a common type, and reduces code duplication by centralizing common functionality, making the design more consistent and easier to extend.
The Simple Factory centralizes object creation but still requires modifying the factory to add new burger types (using if-statements), thus it does not fully adhere to the Open-Closed Principle and can become harder to maintain as the number of burger types grows.
Factory Method defines an abstract createBurger() method in the Restaurant class, letting subclasses decide which burger to instantiate. This delegates creation to subclasses, enables easy extension by adding new restaurants without modifying existing code, and adheres to SOLID principles.
Use the Factory Method pattern when the exact product types are unknown at compile time, you want to extend product types independently, and you need to centralize creation logic while minimizing code coupling to enable scalability and maintainability.
It allows new burger types to be added by creating new subclasses of Restaurant that implement createBurger(), avoiding changes to existing code and ensuring the system is open for extension but closed for modification.
Consider exploring advanced design patterns and architectures, such as hexagonal architecture or other essential software design patterns, to further enhance scalability and maintainability as your application grows complex and requirements evolve.
Heads up!
This summary and transcript were automatically generated using AI with the Free YouTube Transcript Summary Tool by LunaNotes.
Generate a summary for freeRelated Summaries
Scalable System Design Explained Using a Restaurant Analogy
Explore how building a scalable, resilient system parallels running a growing pizza parlor. This guide covers vertical and horizontal scaling, fault tolerance, microservices, load balancing, and decoupling with real-world examples to simplify complex technical concepts.
Understanding 7 Essential Software Design Patterns
Learn about 7 critical software design patterns that improve your programming skills. Discover how to effectively implement them!
Understanding Hexagonal Architecture: Transforming MVC Applications
In this engaging live session, we explore the principles of hexagonal architecture and its advantages over traditional MVC applications. The discussion includes real-world examples, challenges faced during the transition, and the importance of maintaining a clear separation between business logic and presentation layers.
Building the Ultimate Auto Space Parking Application
Learn how to create an advanced parking application with Auto Space using modern technologies.
Mastering the Lean Startup Approach: Your Guide to Successful Entrepreneurship
Learn how to apply the Lean Startup principle for sustainable business success with practical insights and examples.
Most Viewed Summaries
Kolonyalismo at Imperyalismo: Ang Kasaysayan ng Pagsakop sa Pilipinas
Tuklasin ang kasaysayan ng kolonyalismo at imperyalismo sa Pilipinas sa pamamagitan ni Ferdinand Magellan.
A Comprehensive Guide to Using Stable Diffusion Forge UI
Explore the Stable Diffusion Forge UI, customizable settings, models, and more to enhance your image generation experience.
Mastering Inpainting with Stable Diffusion: Fix Mistakes and Enhance Your Images
Learn to fix mistakes and enhance images with Stable Diffusion's inpainting features effectively.
Pamamaraan at Patakarang Kolonyal ng mga Espanyol sa Pilipinas
Tuklasin ang mga pamamaraan at patakaran ng mga Espanyol sa Pilipinas, at ang epekto nito sa mga Pilipino.
Pamaraan at Patakarang Kolonyal ng mga Espanyol sa Pilipinas
Tuklasin ang mga pamamaraan at patakarang kolonyal ng mga Espanyol sa Pilipinas at ang mga epekto nito sa mga Pilipino.

