Creational design patterns

In this blog, we delve into creational design patterns, focusing on the Factory Method and Singleton patterns. We provide detailed explanations and examples to help understand these concepts.

GraphQL has a role beyond API Query Language- being the backbone of application Integration
background Coditation

Creational design patterns

In our last blog, we went through design patterns and their benefits, including one of the types; structural design patterns.
In this blog, we will look into Creational design patterns and It’s Usage

Creational Design Patterns

The creational design patterns deal with the creation and initialization of objects. These patterns provide methods for creating objects in a situation-appropriate manner without specifying the exact class of object that will be created. 

These are some types of creational design patterns.

  • Factory Method
  • Abstract Factory 
  • Builder
  • Prototype

Let us discuss the Factory and Singletone pattern.

Factory Pattern

The Factory Design Pattern involves creating various objects without specifying the exact class of the object being created. In some cases, creating an object may involve intricate processes that are not suitable to be included in the client object. The factory class acts as an abstraction, hiding the complex creation logic from the client and offering a standard interface for the client to access newly created objects. The Factory Method is implemented in subclasses, which are responsible for creating the objects of the class.

Consider the following example. Suppose you have a vehicle manufacturing company, and you’re currently manufacturing Sedans and SUVs. After some time, you wanted to start manufacturing trucks, so three classes could be initialized with the common method. `CreateVehicle’ according to the parameter passed to this function will return the respective object.

  • Let us create a struct with some required data and an interface that has the CreateVechicle method

//Vehicle struct with required data
type Vehicle struct {
	Name     string
	Type     string
	MaxSpeed int32
	Engine   string
}

//Interface for factory with CreateVehicle method
type IVehicle interface {
	CreateVehicle() Vehicle
}

  • Now as per the pattern let’s implement all of these types individually with the CreateVehicle method 

func (s SUV) CreateVehicle() Vehicle {
	return Vehicle{
		Name:     "SUV Model 1",
		Type:     "SUV",
		MaxSpeed: 150,
		Engine:   "2600cc",
	}

}

//Truck Implementation
type Truck struct {
	Vehicle
}

func (t Truck) CreateVehicle() Vehicle {
	return Vehicle{
		Name:     "Truck Model 1",
		Type:     "Truck",
		MaxSpeed: 100,
		Engine:   "5000cc",
}

}

//Sedan Implementation
type Sedan struct {
	Vehicle
}

func (s Sedan) CreateVehicle() Vehicle {
	return Vehicle{
		Name:     "Sedan Model 1",
		Type:     "Sedan",
		MaxSpeed: 150,
		Engine:   "2000cc",
	}

}

  • And finally, let us implement the factory function which will give the object according to the vehicle type provide and the main method to test out implementation.

// fn to get a object for specific type of vehicle
func getVehicle(vehicleType string) (IVehicle, error) {
	if vehicleType == "Sedan" {
		return Sedan{}, nil
	}
	if vehicleType == "SUV" {
		return SUV{}, nil
	}
	if vehicleType == "Truck" {
		return Truck{}, nil
	}
	return nil, fmt.Errorf("Wrong vehicle type passed")
}

func main() {
vehicle, _ := getVehicle("Sedan")

	fmt.Printf("%+v\n", vehicle.CreateVehicle())

	vehicle, _ = getVehicle("SUV")

	fmt.Printf("%+v\n", vehicle.CreateVehicle())

	vehicle, _ = getVehicle("Truck")

	fmt.Printf("%+v\n", vehicle.CreateVehicle())
}


Singleton Pattern

The singleton pattern ensures you have one instance of an object. This is useful when only one object is required to control the action during execution. Since only one instance of the class is created, any instance fields of a Singleton are guaranteed to be unique across all instances in the system.

To implement this we will require to use the sync package provided by Go, which will ensure that the object instantiates only once.


type Object struct{}

// Initializing global object instance and sync.Once which helps us to execute the function only once
var (
	object *Object
	once   sync.Once
)

And now we will write a function that will instantiate the object.


// CreateNewObject will be called many times but will give the only object which instantiated first.
func CreateNewObject() *Object {
	if object == nil {
		once.Do(func() {
			object = &Object{}
		})
	}
	return object
}

// Calling CreateNewObject five times to ensure the same memory address is printing on each call
func main() {
	for i := 0; i < 5; i++ {
		fmt.Printf("%p\n", CreateNewObject())
	}
}

The output will be the address of the object with the same memory address.

Hello, I am Akshay Navale, a highly driven and passionate software developer, avid learner, and tech enthusiast, always striving to do better. My passion for technology drives me to continuously learn and improve.

Want to receive update about our upcoming podcast?

Thanks for joining our newsletter.
Oops! Something went wrong.

Latest Articles

Implementing custom windowing and triggering mechanisms in Apache Flink for advanced event aggregation

Dive into advanced Apache Flink stream processing with this comprehensive guide to custom windowing and triggering mechanisms. Learn how to implement volume-based windows, pattern-based triggers, and dynamic session windows that adapt to user behavior. The article provides practical Java code examples, performance optimization tips, and real-world implementation strategies for complex event processing scenarios beyond Flink's built-in capabilities.

time
15
 min read

Implementing feature flags for controlled rollouts and experimentation in production

Discover how feature flags can revolutionize your software deployment strategy in this comprehensive guide. Learn to implement everything from basic toggles to sophisticated experimentation platforms with practical code examples in Java, JavaScript, and Node.js. The post covers essential implementation patterns, best practices for flag management, and real-world architectures that have helped companies like Spotify reduce deployment risks by 80%. Whether you're looking to enable controlled rollouts, A/B testing, or zero-downtime migrations, this guide provides the technical foundation you need to build robust feature flagging systems.

time
12
 min read

Implementing incremental data processing using Databricks Delta Lake's change data feed

Discover how to implement efficient incremental data processing with Databricks Delta Lake's Change Data Feed. This comprehensive guide walks through enabling CDF, reading change data, and building robust processing pipelines that only handle modified data. Learn advanced patterns for schema evolution, large data volumes, and exactly-once processing, plus real-world applications including real-time analytics dashboards and data quality monitoring. Perfect for data engineers looking to optimize resource usage and processing time.

time
12
 min read