Pergunta

Qual seria a melhor prática para compartilhar o objeto de localização (neste caso, ResourceBundle, onde eu salvo todas as traduções) em muitos objetos da GUI no aplicativo? Tenho poucas idéias, mas ambas têm desvantagens:

1) Passar o ResourceBundle por cada construtor de classe da GUI, mas então eu preciso salvá -lo dentro de todas as classes (para uso posterior) - significa ter o mesmo código em cada classe repetidamente

2) Declare o ResourceBundle como estático público (mas não final, porque talvez eu precise alterá -lo - por exemplo, o idioma mudou) na classe GUI principal (por exemplo, "Public Static Resourcebundle MSG"), depois o acesso posterior a ele sempre através dele (por exemplo, chamando Maguriclass. msg.getString ("algo")), mas também pode ser modificado/destruído por qualquer outra classe GUI no mesmo pacote ...

Talvez haja uma prática melhor para fazer o compartilhamento?

Obrigado.

Foi útil?

Solução

O objeto Global ResourceBundle não pode ser final, mas deve ser armazenado em cache em um mapa. Alterar o idioma não é necessário para alterar esta referência:

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

public class UIBundle {
    private static final Map<Locale, ResourceBundle> allUIResources = new HashMap<Locale, ResourceBundle>();

    public static String getString(final String key) {
        return getString(key, Locale.getDefault());
    }

    public static String getString(final String key, final Locale locale) {
        ResourceBundle rb = allUIResources.get(locale);
        if (rb == null) {
            rb = ResourceBundle.getBundle("my-ui-resource", locale);
            allUIResources.put(locale, rb);
        }
        return rb.getString(key);
    }

}

Com este código, você pode acessar textos em idiomas/locais específicos ou apenas usar o local padrão. Se você deseja trocar de localidade, basta definir o local padrão. Sua interface do usuário precisa saber sobre as mudanças no local, então você pode ter que introduzir alguma interface do ouvinte para todos os seus componentes da interface do usuário (PropertyChangelistener, PropertyChangesupport) e não alterar o local diretamente.

Outras dicas

Você pode implementar uma fábrica de cache, que retorna o ResourceBundle com base no valor de um parâmetro de localidade de entrada. Após a primeira chamada, o ResourceBundle será construído e depois armazenado em cache em uma referência estática, que pode ser posteriormente devolvida e reutilizada em chamadas posteriores para a fábrica.

Se você está preocupado com outras classes fazendo coisas que não deseja um objeto, faça dele um campo protegido/privado de uma classe que tenha os métodos que você deseja ser executado.

Os globais são maus, mas às vezes sua conveniência é maior que sua maldade.

A classe ResourceBundle implementa já um cache, portanto, não há necessidade de implementar o cache. Sua classe de acesso pode ser implementada como Singleton. Para mudar o idioma, uso um Threadlocal para o local:

public final class ThreadLocale extends ThreadLocal<Locale>
{
    public static final ThreadLocale theInstance = new ThreadLocale ();

    private ThreadLocale () 
    {
        super ();
    }

    protected Locale initialValue()
    {
        return Locale.getDefault ();
    }
}

No método da classe de acesso, que recebe o texto do pacote de recursos, eu uso o local atual do encadeamento:

public synchronized String getMessage (Object messageKey, Locale locale) throws MissingResourceException
{
    ResourceBundle resourceBundle = null;
    resourceBundle = ResourceBundle.getBundle (filename, ThreadLocale.theInstance.get ());
    return resourceBundle.getString (messageKey.toString ());
}

Assim, você pode definir um local para cada thread e não globalmente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top