A forma mais simples de implmentar o padrão Registry é criar uma classe não extensível e não instanciável onde podemos registrar o objeto colaborador e onde o objeto executor irá procurá-la.
public final class Registry { // não extensivel
private Registry(){} // não instanciável e não extensivel
private static Dictionary dictionary;
public static Dictionary getDictionary(){
return dictionary;
}
public static void setDictionary(Dictionary aDictionary){
dictionary = aDictionary;
}
}
Qualquer objeto que precise utilizar um dicionário agora sabe como obtê-lo sem se preocupar com a classe verdadeira desse objeto. Em particular, o registro pode ser
Imaginando que Dictionary
é uma interface, poderíamos ter classes PtDictionary
, EnDictionary
e EsDictionary
e escolher no inicio da aplicação qual usar.
public class Main{
public static final void main(String[] args){
// registra a utilização do dicionario ingles.
Registry.setDictionary(new EnDictionary());
}
}
Se a aplicação faz traduções então é necessário utilizar mais do que um dicionario. Poderíamos criar um método de registro para cada um, mas isso seria penoso. É mais fácil utilizar uma chave de registro. A chave de registro é um outro objeto (normalmente um String
, mas não precisa ser sempre) que permite recuperar o objeto depois.
No nosso caso utilizaremos um String
representando a língua.Repare como a estrutura interna foi alterada para usar um Map
.
public final class Registry { // não extensivel
private Registry(){} // não instanciável e não extensivel
private static final Map<String,Dictionary> dictionaries = new HashMap<>();
public static Dictionary getDictionary(String language){
return dictionaries.get(language);
}
public static void addDictionary(String language,Dictionary dictionary){
dictionaries.put(language, dictionary);
}
}
Repare que a implementação é muito semelhante a um Property Bag mas onde os métodos acessores e modificadores são estáticos.
Registros e Repositórios
Um uso comum para o padrão Registry é servir como ponto de encontro de objetos que implementam o padrão Repository. Um repositório está associado a uma entidade - mais especificamente um agregado - que é representada por uma classe.
Poderíamos registrar um repositório com um método de registro para cada entidade, mas seria mais interessante utilizar a entidade ( a classe da entidade) como chave do registro.
O exemplo a seguir assume que existe um tipo Repository<E>
genéricamente tipado.
public final class Repositories { // não extensivel
private Repositories(){} // não instanciável e não extensivel
private static final Map<String,Repository> repositories = new HashMap<>();
public static <E> Repository<E> forEntity(Class<E> entityType){
return repositories.get(entityType.getName());
}
public static <E> void addRepository(Class<E> entityType, Repository<E> repository){
repositories.put( entityType.getName(),repository);
}
}