Skip to content

Instantly share code, notes, and snippets.

@genert
Last active October 14, 2017 20:48
Show Gist options
  • Save genert/459333f58ac302f1349127e94ddf2e8c to your computer and use it in GitHub Desktop.
Save genert/459333f58ac302f1349127e94ddf2e8c to your computer and use it in GitHub Desktop.
Go design patterns
package creational
import (
"errors"
"fmt"
)
const (
LuxuryCarType = 1
CarFactoryType = 1
)
type Vehicle interface {
GetWheels() int
GetSeats() int
}
type VehicleFactory interface {
GetVehicle(v int) (Vehicle, error)
}
type CarFactory struct{}
func (c *CarFactory) GetVehicle(v int) (Vehicle, error) {
switch v {
case LuxuryCarType:
return new(LuxuryCar), nil
default:
return nil, errors.New(fmt.Sprintf("Vehicle of type %d not recognized\n", v))
}
}
type Car interface {
GetDoors() int
}
type LuxuryCar struct{}
func (l *LuxuryCar) GetDoors() int {
return 4
}
func (l *LuxuryCar) GetWheels() int {
return 4
}
func (l *LuxuryCar) GetSeats() int {
return 5
}
func GetVehicleFactory(f int) (VehicleFactory, error) {
switch f {
case CarFactoryType:
return new(CarFactory), nil
default:
return nil, errors.New(fmt.Sprintf("Factory with id %d not recognized\n", f))
}
}
// Usage
carF, err = GetVehicleFactory(CarFactoryType)
if err != nil {
panic(err)
}
carVehicle, err := carF.GetVehicle(LuxuryCarType)
if err != nil {
panic(err)
}
package structural
import "fmt"
//------------------------------------------------------------------------
type LegacyPrinter interface {
Print(s string) string
}
//------------------------------------------------------------------------
type MyLegacyPrinter struct{}
func (l *MyLegacyPrinter) Print(s string) (newMsg string) {
newMsg = fmt.Sprintf("Legacy Printer: %s\n", s)
println(newMsg)
return
}
//------------------------------------------------------------------------
type NewPrinter interface {
PrintStored() string
}
type PrinterAdapter struct {
OldPrinter LegacyPrinter
Msg string
}
func (p *PrinterAdapter) PrintStored() (newMsg string) {
if p.OldPrinter != nil {
newMsg = fmt.Sprintf("Adapter: %s", p.Msg)
newMsg = p.OldPrinter.Print(newMsg)
} else {
newMsg = p.Msg
}
return
}
//------------------------------------------------------------------------
package creational
type BuildProccess interface {
SetWheels() BuildProccess
SetSeats() BuildProccess
SetStructure() BuildProccess
Build() VehicleProduct
}
type VehicleProduct struct {
Wheels int
Seats int
Structure string
}
type CarBuilder struct {
vehicle VehicleProduct
}
func (b *CarBuilder) SetWheels() BuildProccess {
b.vehicle.Wheels = 4
return b
}
func (b *CarBuilder) SetSeats() BuildProccess {
b.vehicle.Seats = 5
return b
}
func (b *CarBuilder) SetStructure() BuildProccess {
b.vehicle.Structure = "car"
return b
}
func (b *CarBuilder) Build() VehicleProduct {
return b.vehicle
}
type ManufactoringDirector struct {
builder BuildProccess
}
func (m *ManufactoringDirector) SetBuildProcess(b BuildProccess) {
m.builder = b
}
func (m *ManufactoringDirector) Construct() {
m.builder.SetWheels().SetSeats().SetStructure()
}
// Usage
manufactoringComplex := ManufactoringDirector()
carBuilder := &CarBuilder()
manufactoringComplex.SetBuildProcess(carBuilder)
manufactoringComplex.Construct()
car := carBuilder.Build()
// You can now access car
if car.Wheels != 4 {
panic("What the f")
}
package composition
type Athlete struct{}
func (a *Athlete) Train() {
println("Training")
}
func Swim() {
println("Swimming!")
}
type CompositeSwimmerA struct {
MyAthlete Athlete
MySwim *func()
}
//--------------------------------------------------------------------------
type Trainer interface {
Train()
}
type Swimmer interface {
Swim()
}
type SwimmerImplementor struct{}
func (s *SwimmerImplementor) Swim() {
println("Swimming!")
}
type CompositeSwimmerB struct {
Trainer
Swimmer
}
//--------------------------------------------------------------------------
type Animal struct{}
func (r *Animal) Eat() {
println("Eating")
}
type Shark struct {
Animal
Swim func()
}
//--------------------------------------------------------------------------
type Tree struct {
LeafValue int
Right *Tree
Left *Tree
}
//--------------------------------------------------------------------------
type Parent struct {
SomeField int
}
type Son struct {
P Parent
}
func GetParentField(p Parent) int {
return p.SomeField
}
package creational
import (
"errors"
"fmt"
)
type PaymentMethod struct {
Pay(amount float32) string
}
const (
Cash = 1
DebitCard = 2
)
func GetPaymentMethod(pm int) (PaymentMethod, error) {
switch pm {
case Cash:
return new(CashPM), nil
case DebitCard:
return new(DebitCardPM), nil
}
default:
return nil, errors.New(fmt.Sprintf("Payment method %d is not supported\n", pm))
}
type CashPM struct {}
type DebitCardPM struct {}
func (pm *CashPM) Pay(amount float32) string {
return fmt.Sprintf("%0.2f paid using cash\n", amount)
}
func (pm *DebitCardPM) Pay(amount float32) string {
return fmt.Sprintf("%0.2f paid using debitcard\n", amount)
}
// Usage
payment, err := GetPaymentMethod(Cash)
if err != nil {
panic(err)
}
msg := payment.Pay(13.37)
package pipedrive
import (
"errors"
"fmt"
)
const (
White = 1
Blue = 2
Black = 3
)
func GetShirtsCloner() ShirtCloner {
return nil
}
type ShirtsCache struct{}
func (s *ShirtsCache) GetClone(m int) (ItemInfoGetter, error) {
switch m {
case White:
newItem := *whitePrototype
return &newItem, nil
case Black:
newItem := *blackPrototype
return &newItem, nil
case Blue:
newItem := *bluePrototype
return &newItem, nil
default:
return nil, errors.New("Shirt model not recognized")
}
}
type ShirtCloner interface {
GetClone(m int) (ItemInfoGetter, error)
}
type ItemInfoGetter interface {
GetInfo() string
}
type ShirtColor byte
type Shirt struct {
Price float32
SKU string
Color ShirtColor
}
func (s *Shirt) GetInfo() string {
return fmt.Sprintf("Shirt with SKU '%s' and Color id %d that costs %f\n", s.SKU, s.Color, s.Price)
}
var whitePrototype *Shirt = &Shirt{
Price: 15.00,
SKU: "empty",
Color: White,
}
var blackPrototype *Shirt = &Shirt{
Price: 16.00,
SKU: "empty",
Color: Black,
}
var bluePrototype *Shirt = &Shirt{
Price: 17.00,
SKU: "empty",
Color: Blue,
}
func (i *Shirt) GetPrice() float32 {
return i.Price
}
// Usage
shirtCache := GetShirtsCloner()
item1, err := shirtCache.GetClone(White)
// This is not thread-safe. Use concurrency!
package creational
type singleton struct {
count int
}
var instance *singleton
func GetInstance() *singleton {
if instance == nil {
instance = new(singleton)
}
return instance
}
func (s *singleton) AddOne() int {
s.count++
return s.count
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment