In Go we can create functions that implement a interface, like http.Handler
interface and concrete type http.HandlerFunc
. I created another simple example of this kind of pattern to calculate bonus for different employees.
type BonusCalculator interface {
Calculate(salary float64) float64
}
type BonusFunc func(salary float64) float64
func (bonus BonusFunc) Calculate(salary float64) float64 {
return bonus(salary)
}
var (
DeveloperBonus BonusFunc = func(salary float64) float64 { return salary*1.5 2500.00 }
ManagerBonus BonusFunc = func(salary float64) float64 { return salary * 2.0 }
DirectorBonus BonusFunc = func(salary float64) float64 { return salary * 3.3 }
)
func CalculateBonus (bonus BonusCalculator, salary float64) float64 {
return bonus.Calculate(salary)
}
func main() {
bonus := CalculateBonus(DirectorBonus, 35000.00)
fmt.Printf("bonus %.2f", bonus)
}
So above we have simple BonusFuncs
implementing interface BonusCalculator
instead of use structs to do the same.
Is there a name to this pattern? I see it in many places and never found a name for it.
CodePudding user response:
Is there a name to this pattern? I see it in many places and never found a name for it.
Yes, this pattern is called Adapter because it allows some sort of "interface" (closures in this case) to be used as another kind of interface (a type that satisfies BonusCalculator
).
In your example, you have an interface BonusCalculator
:
type BonusCalculator interface {
Calculate(salary float64) float64
}
However, you have closures of type func(salary float64) float64
, and you want to be able to pass them when a type that satisfies BonusFunc
is required, i.e., a type that has the method Calculate(salary float64) float64
(the closures don't have a method with such name, so they don't satisfy BonusCalculator
).
What you want is to adapt a func(salary float64) float64
to a BonusCalculator
. So, you define a new type, BonusFunc
, which is the adapter. It will derive from the closure type you want to adapt and, in turn, will satisfy BonusCalculator
by defining a method Calculate(salary float64) float64
on it that simply calls the underlying closure:
type BonusFunc func(salary float64) float64
func (bonus BonusFunc) Calculate(salary float64) float64 {
return bonus(salary)
}
The BonusFunc
is the Adapter; it exists only for adapting a func(salary float64) float64
so that the interface BonusCalculator
can be satisfied. Now, whenever you assign a func(salary float64) float64
to a BonusFunc
, you obtain a value that satisfies Bonuscalculator
.