Los patrones de diseño, son dinámicos, hay que adaptarlos para cada caso. Si bien hemos aprendido que suelen usarse en conjunto con otros, hay casos en los que podemos aplicarlos aislados.
El patron criteria nos permite filtrar, una lista de instancias, en base a criterios. Para ello definiremos implementaciones de la interfaz ICriteria, implementando por otro lado cada criterio de filtrado.
Una vez definida toda la estructura, montaremos los filtros en orden que esperamos que se vaya aplicando.
En Java podríamos poner, todos los métodos AND, ORD, etc en una misma clase utilizando genéricos.
En este ejemplo, definiré objetos independientes, para gestionar las operaciones lógicas, no por ello, esta implementación debería ser la única que podéis aplicar.
No sigáis este código al pie de la letra, ser creativos, adaptarlo. Vayamos a la implementación en go!!!!
Criteria.go
package main
type Criteria interface {
Apply(properties []Property) []Property
}
type OrCriteria struct {
Left Criteria
Right Criteria
}
func (or OrCriteria) Apply(properties []Property) []Property {
result := or.Left.Apply(properties)
return append(result, or.Right.Apply(properties)...)
}
type AndCriteria struct {
Left Criteria
Right Criteria
}
func (and AndCriteria) Apply(properties []Property) []Property {
result := and.Left.Apply(properties)
return and.Right.Apply(result)
}
type CriteriaPool struct{}
func (c CriteriaPool) Apply(properties []Property) []Property {
result := []Property{}
for _, property := range properties {
if property.Pool {
result = append(result, property)
}
}
return result
}
type CriteriaFlat struct{}
func (c CriteriaFlat) Apply(properties []Property) []Property {
result := []Property{}
for _, property := range properties {
if "Flat" == property.Type {
result = append(result, property)
}
}
return result
}
type CriteriaHouse struct{}
func (c CriteriaHouse) Apply(properties []Property) []Property {
result := []Property{}
for _, property := range properties {
if "House" == property.Type {
result = append(result, property)
}
}
return result
}
Porperty.go
package main
type Property struct {
Name string
Type string
Pool bool
}
func NewProperty(name string, properType string, pool bool) Property {
return Property{Name: name, Type: properType, Pool: pool}
}
How to use
package main
import "fmt"
func main() {
result := []Property{}
result = append(result, NewProperty("Flat 1", "Flat", false))
result = append(result, NewProperty("Flat 2", "Flat", false))
result = append(result, NewProperty("House 1", "House", false))
result = append(result, NewProperty("Flat 4", "Flat", false))
result = append(result, NewProperty("House 2", "House", true))
result = append(result, NewProperty("House 3", "House", false))
result = append(result, NewProperty("Flat 3", "Flat", false))
result = append(result, NewProperty("House 5", "House", true))
result = append(result, NewProperty("House 4", "House", false))
result = append(result, NewProperty("Flat 3", "Flat", true))
PrintPropertyList("Flat", CriteriaFlat{}, result)
PrintPropertyList("House", CriteriaHouse{}, result)
PrintPropertyList("Pool", CriteriaPool{}, result)
PrintPropertyList("House or Pool", OrCriteria{CriteriaHouse{}, CriteriaPool{}}, result)
PrintPropertyList("House and Pool", AndCriteria{CriteriaHouse{}, CriteriaPool{}}, result)
}
func PrintPropertyList(filter string, criteria Criteria, properties []Property) {
fmt.Printf("\nFiltering by %s\n", filter)
for _, property := range criteria.Apply(properties) {
fmt.Printf("Name: %s, Type: %s, Pool: %t\n", property.Name, property.Type, property.Pool)
}
}
Seguirme en GitHub, twitter, me ayudará a continuar generando contenido!.