Creational design patterns play a crucial role in software development as they provide flexible object creation mechanisms. They encapsulate the logic of creating objects, making it easier to manage object creation and improve code maintainability. In this article, we will explore some commonly used creational patterns in C#, JavaScript, Dart, and GoLang.
Singleton Pattern
The Singleton pattern ensures that there is only one instance of a class throughout the application. This can be useful when you need to have a single point of access to a resource or when creating a shared object. Here’s an example of implementing the Singleton pattern in C#:
public class Singleton
{
private static Singleton instance;
private Singleton()
{
// Private constructor to prevent external instantiation
}
public static Singleton Instance
{
get
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
Factory Method Pattern
The Factory Method pattern provides an interface for creating objects, but allows subclasses to determine the actual class to instantiate. This decouples the client code from the specific classes being created. Here’s an example of using the Factory Method pattern in JavaScript:
class Car {
constructor(make, model) {
this.make = make;
this.model = model;
}
}
class CarFactory {
createCar(make, model) {
return new Car(make, model);
}
}
const factory = new CarFactory();
const car = factory.createCar("Toyota", "Camry");
Abstract Factory Pattern
The Abstract Factory pattern provides an interface for creating families of related objects. It allows the client code to create objects without specifying their concrete classes. Here’s an example of implementing the Abstract Factory pattern in Dart:
abstract class Button {
void display();
}
class MaterialButton implements Button {
void display() {
print("Material Button");
}
}
class CupertinoButton implements Button {
void display() {
print("Cupertino Button");
}
}
abstract class GUIFactory {
Button createButton();
}
class MaterialFactory implements GUIFactory {
Button createButton() {
return MaterialButton();
}
}
class CupertinoFactory implements GUIFactory {
Button createButton() {
return CupertinoButton();
}
}
class Application {
Button button;
Application(GUIFactory factory) {
button = factory.createButton();
}
void createUI() {
button.display();
}
}
final factory = CupertinoFactory();
final application = Application(factory);
application.createUI();
Builder Pattern
The Builder pattern separates the creation of an object from its representation, allowing the same construction process to create different representations. It provides a step-by-step approach to building complex objects. Here’s an example of using the Builder pattern in GoLang:
type Car struct {
Make string
Model string
Color string
}
type CarBuilder struct {
car Car
}
func (b *CarBuilder) SetMake(make string) *CarBuilder {
b.car.Make = make
return b
}
func (b *CarBuilder) SetModel(model string) *CarBuilder {
b.car.Model = model
return b
}
func (b *CarBuilder) SetColor(color string) *CarBuilder {
b.car.Color = color
return b
}
func (b *CarBuilder) Build() Car {
return b.car
}
func main() {
car := CarBuilder{}.
SetMake("Toyota").
SetModel("Camry").
SetColor("Blue").
Build()
}
These are just a few examples of creational patterns commonly used in C#, JavaScript, Dart, and GoLang. By leveraging these patterns, you can enhance the flexibility and maintainability of your codebase. Make sure to understand the specific requirements of your application before choosing the appropriate creational pattern to implement.