# README
Exploring the Abstract Factory Pattern in Golang with SportsFactory
Design patterns are essential tools for any software developer. They provide proven solutions to common problems, ensuring code is maintainable, scalable, and robust. One such pattern is the Abstract Factory Pattern. In this blog post, we'll dive into the Abstract Factory Pattern using an example from the Learning-LLD-Using-Golang repository, specifically focusing on the SportsFactory. What is the Abstract Factory Pattern?
The Abstract Factory Pattern is a creational design pattern that provides an interface for creating families of related or dependent objects without specifying their concrete classes. This pattern is particularly useful when the exact types and dependencies of the objects are not known until runtime or when you need to ensure that the objects are created in a consistent manner. Structure of the SportsFactory Example
In the SportsFactory example, the pattern is used to create different types of sports equipment. The main components of this implementation are:
Abstract Factory Interface: Defines the methods for creating abstract products.
Concrete Factories: Implement the abstract factory interface to create concrete products.
Abstract Product Interfaces: Declare interfaces for different types of products.
Concrete Products: Implement the abstract product interfaces.
Let's break down the code step-by-step. Abstract Factory Interface
The abstract factory interface, SportsFactory, defines the methods for creating sports equipment:
type SportsFactory interface {
MakeShoe() Shoe
MakeShirt() Shirt
}
Concrete Factories
The concrete factories implement the SportsFactory interface to create specific types of sports equipment. For instance, here are the Nike and Adidas factories:
type Nike struct{}
func (n *Nike) MakeShoe() Shoe {
return &NikeShoe{
Shoe: Shoe{
Logo: "Nike",
Size: 14,
},
}
}
func (n *Nike) MakeShirt() Shirt {
return &NikeShirt{
Shirt: Shirt{
Logo: "Nike",
Size: "L",
},
}
}
type Adidas struct{}
func (a *Adidas) MakeShoe() Shoe {
return &AdidasShoe{
Shoe: Shoe{
Logo: "Adidas",
Size: 14,
},
}
}
func (a *Adidas) MakeShirt() Shirt {
return &AdidasShirt{
Shirt: Shirt{
Logo: "Adidas",
Size: "L",
},
}
}
Abstract Product Interfaces
The abstract product interfaces define the methods that concrete products must implement. Here are the Shoe and Shirt interfaces:
type Shoe struct {
Logo string
Size int
}
type Shirt struct {
Logo string
Size string
}
Concrete Products
The concrete products implement the abstract product interfaces. Here are the NikeShoe and NikeShirt implementations:
type NikeShoe struct {
Shoe
}
type NikeShirt struct {
Shirt
}
Similarly, here are the AdidasShoe and AdidasShirt implementations:
type AdidasShoe struct {
Shoe
}
type AdidasShirt struct {
Shirt
}
Using the Abstract Factory
To use the abstract factory, we first create instances of the concrete factories and then use these instances to create products:
package main
import "fmt"
func main() {
adidasFactory := GetSportsFactory("adidas")
nikeFactory := GetSportsFactory("nike")
adidasShoes := adidasFactory.makeShoes()
nikeShoes := nikeFactory.makeShoes()
adidasShirts := adidasFactory.makeShirts()
nikeShirts := nikeFactory.makeShirts()
printShoeDetails(adidasShoes)
printShoeDetails(nikeShoes)
printShirtDetails(adidasShirts)
printShirtDetails(nikeShirts)
}
func printShoeDetails(s IShoesFactory) {
fmt.Printf("Logo: %s", s.getLogo())
fmt.Println()
fmt.Printf("Size: %d", s.getSize())
fmt.Println()
}
func printShirtDetails(s IShirtsFactory) {
fmt.Printf("Logo: %s", s.getLogo())
fmt.Println()
fmt.Printf("Size: %d", s.getSize())
fmt.Println()
}
This code produces:
Logo: Adidas
Size: 18
Logo: Nike
Size: 20
Logo: Adidas
Size: 40
Logo: Nike
Size: 50
Conclusion
The Abstract Factory Pattern is a powerful tool in a developer's toolkit, especially when dealing with the creation of related objects. By using this pattern, you can ensure that your code adheres to the SOLID principles, making it more maintainable and scalable.
In this blog post, we explored the Abstract Factory Pattern through the SportsFactory example implemented in Golang. This example demonstrates how to create families of related objects, such as sports equipment, without specifying their concrete classes.