Estava lendo o tópico “Este Singleton está utilizado corretamente?”, por sinal uma discussão muito interessante, e fiz uma análise da seguinte passagem do usuário pcalcado:
[quote]…Você está usando Singleton como variável global. No seu exemplo o problema não é ter mais de um cache, o problema é que os clientes devem usar o mesmo cache.
Como fazer isso? Padrão Registry ou Dependency Injection são as soluções mais comuns…[/quote]
Então resolvi buscar informações sobre o Padrão Registry, mas infelizmente não econtrei nada a respeito que pudesse mostrar de forma clara o funcionamento deste padrão.
Aonde conseguir informações, como um diagrama UML e/ou algum exemplo de código em Java, sobre este padrão?
Eu já tinha achado esta página do Fowler, mas como o padrão demonstrado era tão simples, eu acabei pensando que este estava incompleto (Risos).
Em minha busca por referências a este padrão, acabei me deparando com um outro padrão o “Service Locator”. Os nomes são diferentes, mas o padrão é o mesmo? Ou são apenas padrões que possuem semelhanças em suas finalidades?
Registry (Registro) é um padrão que visa possibilitar o encontro atemporal entre dois objetos.Atemporal no sentido que os objetos podem se procurar a qualquer momento.
A implementação do padrão registry é uma classe não instanciavel e não-extensivel cujos métodos são todos estáticos
Existem várias aplicações do padrão registry.
Possibilita que os objetos de modelo se encontrem mutuamente (foi neste sentido que Fowler o aplicou)
Neste sentido ele é um Repository e os seus métodos têm a ver com encontrar entidades
Pode ser usado para carregar determinadas propriedades do ambiente de execução da aplicação, que a aplicação usará em qq ponto do seu codigo.
A classe java.lang.System é um exemplo disto. Os métodos getProperty() destinam-se a concontrar aquelas propriedades. No caso elas são strings, mas poderiam ser qq outro tipo de objeto
Permite que um objeto use um serviço tal que o serviço possa mudar.
Aqui o conceito é que o registro é inicializado com um conjunto de serviços. (cada uma com interface diferente ou não) E os objetos usuários desses serviços pesquisam o registro por eles.
Isto é usado em Jini , RMI e no DriverManager, por exemplo.
Neste uso o Registry pode localizar diferentes serviços , ou até serviços iguais com configurações diferentes.
O ServiceLocator é, normalmente apenas o cache do serviço já encontrado por algum mecanismo. Não é bem a mesma coisa que o Registry.
P.S.
Podemos identificar um Registry quando a classe so tem metodos estáticos e eles funcionam como um Map , retornando alguma coisa, com base em algum tipo de chave.
O meu interesse por esses dois padrões surgiu pela necessidade de implementar uma aplicação que será composta de diversas entidades que irão buscar dados em um mesmo local. Mas como localizar este serviço (Local)? A princípio o padrão Singleton me pareceu o mais óbvio, mas felizmente eu me deparei com a colocação feita pelo pcalcado, que ao meu ver exprime bem a minha necessidade.
Se possível gostaria de saber mais sobre o padrão Service Locator para poder entender melhor a diferença entre ele e o padrão Registry.
[quote=Henrique Mota Esteves]O meu interesse por esses dois padrões surgiu pela necessidade de implementar uma aplicação que será composta de diversas entidades que irão buscar dados em um mesmo local.(…)
[/quote]
Então o que vc quer é um Repository. Procure por esse pattern.
[quote]
Se possível gostaria de saber mais sobre o padrão Service Locator para poder entender melhor a diferença entre ele e o padrão Registry. [/quote]
sergiotaborda, quando abri este tópico eu estava com dúvidas de como fazer para que as entidades que precisem buscar dados em um mesmo local iriam fazer para poder acessar este repositório, e não na maneira como este repositório iria fornecer estes dados. Isto se deve ao fato da simplicidade de implementação imaginada para este repositório que, possivelmente, irá obter os dados na memória. Se você tiver acesso ao livro “Patterns Of Enterprise Application Architecture” do Fowler, anteriormente mencionado pelo pcalcado, você irá ver que na descrição do padrão Repository por ele feita, quando um objeto precisa buscar alguma informação, primeiro ele acessa o serviço através de um Registry e somente depois disto ele faz uso deste serviço, buscando a informação solicitada, como poder ser observado no trecho de código extraído deste mesmo livro:
public class Person {
public List dependents() {
Repository repository = Registry.personRepository();
Criteria criteria = new Criteria();
criteria.equal(Person.BENEFACTOR, this);
return repository.matching(criteria);
}
}
A minha visão para o problema ao qual estou tentando resolver está certa ou errada?
public class Person {
public List dependents() {
Repository repository = Registry.personRepository();
Criteria criteria = new Criteria();
criteria.equal(Person.BENEFACTOR, this);
return repository.matching(criteria);
}
}
A minha visão para o problema ao qual estou tentando resolver está certa ou errada?
[/quote]
Esse código funciona. Então, se entendi direito, o seu problema é como implementar o Registry.personRepository() ?
public final class Registry {
private Registry(){}
public static Repository personRepository(){
// codigo aqui
}
}
Agora, existem muitas estratégias para preencher aquele codigo ali.
Poderia ser assim:
public final class Registry {
private Registry(){}
final private Map repositories = new HashMap();
public static void registerRepository(Class classe, Repository rep){
repositories.put(classe,rep);
}
public static Repository domainRepository(Class classe){
return (Repository)repositories.get(classe);
}
}
public class Person {
public List dependents() {
Repository repository = Registry.domainRepository(Person.class);
Criteria criteria = new Criteria();
criteria.equal(Person.BENEFACTOR, this);
return repository.matching(criteria);
}
}
Registry tem um só método domainRepository e não N métodos 1 para cada tipo de entidade.
A implementação de Registry é muito simples
A única coisa a fazer é vc ter um codigo de bootstrap que iniciliza o registro com os repositorios certos. Vc pode obter os repositorios de uma fábrica , se for o caso.
Mas tb podia ser assim:
public class Person {
public List dependents() {
Criteria criteria = new Criteria();
criteria.equal(Person.BENEFACTOR, this);
return Repository.matching(Person.class, criteria);
}
}
public final class Repository{
private Repository(){}
final private Map repositories = new HashMap();
public static <T> List<T> matching(Class<T> classe ,Criteria criteria){
return ((Repository)repositories.get(classe)).matching(criteria);
}
}
[size=8]Editado:O retorno é uma lista de T e não um so T[/size]
Em que Repository atua como Register também. Não sei se a sua duvida ficou esclarecida…
Acredito que o propósito deste post foi atingido, mas caso alguém tenha mais alguma coisa a acrescentar fique à vontade. Quando coloquei a minha dúvida para discussão, estava pretendendo achar uma maneira de poder fazer com que diversas entidades pudessem localizar um determinado serviço, neste caso um repositório de dados, para de lá poderem retirar informações. E isto tudo sem ter que apelar para o modelo “Variável Global com Singleton”.
Só não se esqueça que IoC geralmente é melhor que Registry porque desacopla o cliente de como e onde ele obtêm o serviço. Além do mais, procure sobre Query Objects para abstrair classes do Hibernate como Crteria API, que não devem estar na Camada de Negócios.
Li a sua apostila sobre o framework Spring (IoC) depois de abrir este tópico. Realmente ele elimina esta dependência por você mencionada. A solução de IoC oferecida pelo Spring frente ao padrão Registry é sem dúvida muito mais inteligente.
Mas uma questão ainda fica no ar. Para este meu caso, utilizar o Spring não seria o mesmo que tentar matar um mosquito com um canhão?
Como elogio nunca é demais. pcalcado, parabéns pela sua apostila. É cada dia mais difícil achar material gratuito e de qualidade na internet.
Como estou começando um projeto, preciso de uma prova de conceito da arquitetura. Mas primeiro preciso definir algumas coisas. Vejo muita coisa na NET parecida com nomes diferentes e tenhod dificuldade em bater o martelo numa estrutura ou em outra.
Minha proposta eh aproximadamente essa:
VIEW:
Usar ZK com os famosos models.
Controller:
Uso uma extensão do container da View (péssima prática, mas isso eh uma outra pergunta para outro tópico) e chamar um service disponível.
Service
Colocar regras de negócio aqui e na interação com alguma estrutura de dados, usar o respositorio e buscar a interface DAO adequada. A partir dessa interface, chamar os métodos desse DAO correspondentes.
DAO:
Utilizar Hibernate.
PERGUNTAS:
Não é muita camada? Isso está estranho…
O sergio explicou muito bem o padrão repository! Mas eu o usarei apenas para trocar a fonte de dados automaticamente (de memória em testes, para BD no desenvolvimento), estou no caminho certo?
Onde o Spring entraria nesse contexto todo? (eu acho que seria na hora de instanciar as classes das N camadas, daí poderia perder o contato uma com as outras, mas isso nao seria uma espécie de MAIS UM LUGAR pra configurar?)
PS: Alguém poderia passar o link da apostila do pcalcado para eu entender como usar o Spring adequadamente e entender os verdadeiros benefícios de usar o Ioc (na prática).