How to add a caching mechanism to the abstract factory pattern in Golang
I have already written a simple abstract factory pattern, with a general factory and general products. The requirement is to add a caching mechanism in the general factory and general products so that concrete factories and concrete products can be cached. The benefit is that modifications can be made uniformly in the general methods, without the need to write extra code for concrete products or concrete factories.
Expected outcome for unified caching management for all factories and unified caching management for different factories of the same product
I aim to achieve unified caching management for all factories, as well as unified caching management for different factories that produce the same product.
Below is my code:
type HardwareAbstractionLayer interface {
GetProcessor() CentralProcessor
}
type CentralProcessor interface {
GetMaxFreq() int64
}
type AbstractHardwareAbstractionLayer struct{}
func (l *AbstractHardwareAbstractionLayer) GetProcessor() CentralProcessor {
return nil
}
type LinuxHardwareAbstractionLayer struct {
*AbstractHardwareAbstractionLayer
}
func (l *LinuxHardwareAbstractionLayer) GetProcessor() CentralProcessor {
cpu := new(LinuxCentralProcessor)
return cpu
}
type AbstractCentralProcessor struct{}
func (l *AbstractCentralProcessor) GetMaxFreq() int64 {
return -1
}
type LinuxCentralProcessor struct {
*AbstractCentralProcessor
}
func (p *LinuxCentralProcessor) GetMaxFreq() int64 {
log.Println("queryMaxFreq called")
return rand.Int63()
}
type memoize struct {
sync.RWMutex
value interface{}
expirationTime time.Time
}
func Memoize(original func() interface{}) func() interface{} {
return MemoizeWithExpiration(original, -1)
}
func MemoizeWithExpiration(original func() interface{}, ttl time.Duration) func() interface{} {
m := &memoize{}
return func() interface{} {
m.RLock()
if ttl >= 0 && time.Now().Before(m.expirationTime) && m.value != nil {
defer m.RUnlock()
return m.value
}
m.RUnlock()
m.Lock()
defer m.Unlock()
if ttl >= 0 && time.Now().Before(m.expirationTime) && m.value != nil {
return m.value
}
m.value = original()
if ttl >= 0 {
m.expirationTime = time.Now().Add(ttl)
} else {
m.expirationTime = time.Time{}
}
return m.value
}
}
func DefaultExpiration() time.Duration {
return time.Minute
}