Sobes.tech
Junior

What design patterns are you familiar with?

sobes.tech AI

Answer from AI

  • Creational: Create objects.
    • Factory Method
    • Abstract Factory
    • Builder
    • Prototype
    • Singleton
  • Structural: Form structures of classes and objects.
    • Adapter
    • Bridge
    • Composite
    • Decorator
    • Facade
    • Flyweight
    • Proxy
  • Behavioral: Define algorithms and ways objects interact.
    • Chain of Responsibility
    • Command
    • Iterator
    • Mediator
    • Memento
    • Observer
    • State
    • Strategy
    • Template Method
    • Visitor

In my practice, I often use Factory Method for creating objects based on criteria, Builder for step-by-step construction of complex objects, Singleton for unique instances, Adapter for interface compatibility, Decorator for extending functionality, Facade for simplifying subsystem interfaces, Observer for reactive systems, and Strategy for algorithm selection.

Example of the "Factory Method" pattern in Golang:

package main

import "fmt"

type Vehicle interface {
	Drive()
}

type Car struct{}

func (c Car) Drive() {
	fmt.Println("Driving a car")
}

type Bike struct{}

func (b Bike) Drive() {
	fmt.Println("Riding a bike")
}

func NewVehicle(vehicleType string) Vehicle {
	switch vehicleType {
	case "car":
		return Car{}
	case "bike":
		return Bike{}
	default:
		return nil
	}
}

func main() {
	car := NewVehicle("car")
	bike := NewVehicle("bike")

	car.Drive()
	bike.Drive()
}

Example of the "Decorator" pattern in Golang:

package main

import "fmt"

type Coffee interface {
	Cost() float64
	Description() string
}

type SimpleCoffee struct{}

func (s SimpleCoffee) Cost() float64 {
	return 1.0
}

func (s SimpleCoffee) Description() string {
	return "Simple Coffee"
}

type MilkDecorator struct {
	coffee Coffee
}

func (m MilkDecorator) Cost() float64 {
	return m.coffee.Cost() + 0.5
}

func (m MilkDecorator) Description() string {
	return m.coffee.Description() + ", Milk"
}

type SugarDecorator struct {
	coffee Coffee
}

func (s SugarDecorator) Cost() float64 {
	return s.coffee.Cost() + 0.2
}

func (s SugarDecorator) Description() string {
	return s.coffee.Description() + ", Sugar"
}

func main() {
	coffee := SimpleCoffee{}
	milkCoffee := MilkDecorator{coffee: coffee}
	milkSugarCoffee := SugarDecorator{coffee: milkCoffee}

	fmt.Printf("Cost: %.2f, Description: %s\n", milkSugarCoffee.Cost(), milkSugarCoffee.Description())
}

It is important not only to know patterns but also to understand when to apply them so that the solution is optimal and maintainable.