Skip to content

Instantly share code, notes, and snippets.

@jerryan999
Created July 13, 2023 15:27
Show Gist options
  • Save jerryan999/ed63f9a0090cd17ee665809948db1617 to your computer and use it in GitHub Desktop.
Save jerryan999/ed63f9a0090cd17ee665809948db1617 to your computer and use it in GitHub Desktop.
specification pattern in golang
package main
import "fmt"
type Employee struct {
name string
age int
salary int
location string
}
type EmployeeSpecification interface {
IsSatisfiedBy(Employee) bool
}
type AgeSpecification struct {
minAge int
maxAge int
}
func (s AgeSpecification) IsSatisfiedBy(e Employee) bool {
return e.age >= s.minAge && e.age <= s.maxAge
}
type SalarySpecification struct {
minSalary int
maxSalary int
}
func (s SalarySpecification) IsSatisfiedBy(e Employee) bool {
return e.salary >= s.minSalary && e.salary <= s.maxSalary
}
type LocationSpecification struct {
location string
}
func (s LocationSpecification) IsSatisfiedBy(e Employee) bool {
return e.location == s.location
}
type AndSpecification struct {
specifications []EmployeeSpecification
}
func (s AndSpecification) IsSatisfiedBy(e Employee) bool {
for _, spec := range s.specifications {
if !spec.IsSatisfiedBy(e) {
return false
}
}
return true
}
type OrSpecification struct {
specifications []EmployeeSpecification
}
func (s OrSpecification) IsSatisfiedBy(e Employee) bool {
for _, spec := range s.specifications {
if spec.IsSatisfiedBy(e) {
return true
}
}
return false
}
type UserRepository interface {
Save(employee Employee) error
FindAll(spec EmployeeSpecification) ([]Employee, error)
}
type MemoryUserRepository struct {
employees []Employee
}
func (r MemoryUserRepository) Save(employee Employee) error {
r.employees = append(r.employees, employee)
return nil
}
func (r MemoryUserRepository) FindAll(spec EmployeeSpecification) ([]Employee, error) {
var filteredEmployees []Employee
for _, employee := range r.employees {
if spec.IsSatisfiedBy(employee) {
filteredEmployees = append(filteredEmployees, employee)
}
}
return filteredEmployees, nil
}
func main() {
employees := []Employee{
{"Alice", 25, 50000, "New York"},
{"Bob", 30, 60000, "San Francisco"},
{"Charlie", 35, 70000, "New York"},
{"David", 40, 80000, "San Francisco"},
{"Edward", 45, 90000, "New York"},
{"Flynn", 50, 100000, "San Francisco"},
}
repo := MemoryUserRepository{employees: employees}
for _, employee := range employees {
repo.Save(employee)
}
// filter employees by age
ageSpec := AgeSpecification{minAge: 30, maxAge: 45}
filteredEmployees, _ := repo.FindAll(ageSpec)
fmt.Println(filteredEmployees)
// composite specification
var comSpec EmployeeSpecification
salarySpec := SalarySpecification{minSalary: 60000, maxSalary: 90000}
locationSpec := LocationSpecification{location: "San Francisco"}
comSpec = AndSpecification{specifications: []EmployeeSpecification{ageSpec, salarySpec, locationSpec}}
filteredEmployees, _ = repo.FindAll(comSpec)
fmt.Println(filteredEmployees)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment