21

设计模式 - 服务定位器模式

 3 years ago
source link: http://violetzijing.is-programmer.com/posts/215466.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

服务定位器模式(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()
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK