設計模式 - 服務定位器模式
服務定位器模式(Service Locator Pattern)用在我們想使用 JNDI 查詢定位各種服務的時候。考慮到爲某個服務查找 JNDI 的代價很高,服務定位器模式充分利用了緩存技術。在首次請求某個服務時,服務定位器在 JNDI 中查找服務,並緩存該服務對象。當再次請求相同的服務時,服務定位器會在它的緩存中查找,這樣可以在很大程度上提高應用程序的性能。以下是這種設計模式的實體。
- 服務(Service) - 實際處理請求的服務。對這種服務的引用可以在 JNDI 服務器中查找到。
- Context / 初始的 Context - JNDI Context 帶有對要查找的服務的引用。
- 服務定位器(Service Locator) - 服務定位器是通過 JNDI 查找和緩存服務來獲取服務的單點接觸。
- 緩存(Cache) - 緩存存儲服務的引用,以便複用它們。
- 客戶端(Client) - Client 是通過 ServiceLocator 調用服務的對象。
package main import "fmt" type Service interface { GetName() string Execute() } type Service1 struct{} func (s *Service1) Execute() { fmt.Println("Executing service1") } func (s *Service1) GetName() string { return "Service1" } type Service2 struct{} func (s *Service2) Execute() { fmt.Println("Executing service2") } func (s *Service2) GetName() string { return "Service2" } type InitContext struct{} func (i *InitContext) Lookup(jndiName string) Service { if jndiName == "service1" { fmt.Println("looking up and creating a new service1 object") return &Service1{} } if jndiName == "service2" { fmt.Println("looking up and creating a new service2 object") return &Service2{} } return nil } type Cache struct { Services map[string]Service } func NewCache() *Cache { return &Cache{ Services: map[string]Service{}, } } func (c *Cache) GetService(serviceName string) Service { if v, ok := c.Services[serviceName]; ok { fmt.Println("return cached service: ", serviceName) return v } return nil } func (c *Cache) AddService(name string, service Service) { c.Services[name] = service } type ServiceLocator struct { Cache *Cache } func NewServiceLocator() *ServiceLocator { return &ServiceLocator{ Cache: NewCache(), } } func (s *ServiceLocator) GetService(jndiName string) Service { service := s.Cache.GetService(jndiName) if service != nil { return service } // create a new service1 context := &InitContext{} service = context.Lookup(jndiName) s.Cache.AddService(jndiName, service) return service } func main() { locator := NewServiceLocator() service := locator.GetService("service1") service.Execute() service = locator.GetService("service2") service.Execute() service = locator.GetService("service1") service.Execute() service = locator.GetService("service2") service.Execute() }