Go Design Pattern — Factory Method

Akhilesh Mahajan
3 min readSep 13

--

In this article, we will talk about the Factory Method (A Type of Creational Design Pattern).

Factory Method

This is a kind of design pattern that provides an interface for creating objects in the superclass but allows the subclass to alter the type of object created. In simple words, whenever we want to create objects for similar kinds of products, define an interface for the Product specifying methods which logically makes sense for every product type. In the Factory pattern, we create objects without exposing the creation logic to the client and refer to newly created objects using a common interface.

Example: Consider the below diagram.

Factory Method

Rather than specifying a constructor function for each type (square, circle, etc.), we can define a generic type Shape that specifies methods that logically make sense for every Shape Type. And define a ShapeFactory, whose responsibility is basically to generate shapes of different types(based on some input parameter to determine which type to return)

// generic shape interface
// which defines method that shape type should have
type IShape interface{
func Draw()
}
// define Square Type
type Square struct {
Side float64
}

// Interface methods for square shape type
func (sq *Square) Draw(){
fmt.Println("Drawing Square")
}

func GenerateNewSquare(side int) Square{
return Square{
Side : side
}
}

// define circle type
type Circle struct{
Radius float64
}

// Interface methods for square shape type
func (c *Circle) Draw(){
fmt.Println("Drawing Circle")
}

Now define a Factory Object that will generate a shape of any type.

func GenrateShape(shapeType string) IShape{
if shapeType == "Square"{
return GenerateNewSquare(4)
}
}
func main(){
squareObj:= GenerateShape("Square")
fmt.Println(squareObj.Draw())
}

// Output will be "Drawing Square"

WHERE THE FACTORY METHOD CAN BE APPLICABLE:

  1. When we don’t know the types and dependencies of the object our code should work with.
    Let’s say, we are working with a logistics management system that initially deals with only Truck Logistics. Now the demand is coming to add Ship Logistics to the system. To add this new logistics type, we need to disturb the whole code and add a new struct, and functionalities (which might be repeated and is the same as truck logistics which minute business logic change). Rather than doing all this, if we have defined a generic type as Logistics Interface previously, which has all the methods defined that logically satisfy for both Truck and Ship, say Deliver(), now we just have to create a new struct type, define all methods and use the same.
  2. When we want to extend the internal components of our code.
    Let’s say that some new shape type has to be added to the shape. We need not disturb the whole codebase. Create struct and methods for new shape type and add value to the generic constructor to generate the shape.
  3. When we want to reuse the code already written.

HOW TO IMPLEMENT FACTORY METHOD

  1. Make all subtypes follow the same interface. The interface should define methods that make sense to all subtypes.
type IGun Interface(){
getName() string
setName(name string)
}

2. Add an empty factory method inside the creator class. The return type should be the common interface. In the factory method, make calls to individual generator methods. The factory method might take an additional variable to know which subtype to generate.

func GenerateGun(gunType string) IGun{
// generate some gun of gunType
}

3. Create a set of sub-types listed in the factory method.

// product
type Gun struct {
name string
}

func (g *Gun) setname(name string){
// some logic
}

func (g *Gun) getname() string{
return g.name
}

// sub products
type Ak47 struct{
Gun
}

func NewAk47() Ak47{
return Ak47{}
}
func main(){
ak47Obj := GenerateGun("ak47")
ak47Obj.setname("ak47")
fmt.Println(ak47Obj.getname()) // Output : ak47
}

Reference:

--

--