Estou trabalhando em um código de interface do usuário em que tenho uma Action
classe, algo como isto -
public class MyAction extends Action {
public MyAction() {
setText("My Action Text");
setToolTip("My Action Tool tip");
setImage("Some Image");
}
}
Quando essa classe Action foi criada, foi assumido que a Action
classe não seria personalizável (em certo sentido - seu texto, dica de ferramenta ou imagem não serão alterados em nenhum lugar do código). Agora, precisamos alterar o texto da ação em algum local do código. Então, sugeri ao meu colega de trabalho para remover o texto da ação codificado do construtor e aceitá-lo como argumento, para que todos sejam forçados a passar o texto da ação. Algo como este código abaixo -
public class MyAction extends Action {
public MyAction(String actionText) {
setText(actionText);
setTooltip("My Action tool tip");
setImage("My Image");
}
}
Ele, no entanto, pensa que, como o setText()
método pertence à classe base, pode ser usado com flexibilidade para passar o texto da ação onde quer que a instância da ação seja criada. Dessa forma, não há necessidade de alterar a MyAction
classe existente . Portanto, seu código seria algo parecido com isto.
MyAction action = new MyAction(); //this creates action instance with the hardcoded text
action.setText("User required new action text"); //overwrite the existing text.
Não tenho certeza se essa é uma maneira correta de lidar com o problema. Eu acho que, no caso acima mencionado, o usuário alterará o texto, então por que não forçá-lo durante a construção da ação? O único benefício que vejo no código original é que o usuário pode criar a classe Action sem pensar muito em definir o texto.
Respostas:
Na verdade, isso não é um benefício, para a maioria dos casos, é uma desvantagem e, nos demais casos, eu chamaria de empate. E se alguém esquecer de chamar setText () após a construção? E se esse for o caso em algum caso incomum, talvez um manipulador de erros? Se você realmente deseja forçar o texto a ser definido, é necessário forçá-lo no momento da compilação, pois apenas erros em tempo de compilação são realmente fatais . Tudo o que acontece no tempo de execução depende do caminho de código específico que está sendo executado.
Eu vejo dois caminhos claros adiante:
null
ou uma sequência vazia, mas o fato de não estar atribuindo um texto é explícito e não implícito. É fácil ver a existência de umnull
parâmetro e ver que provavelmente houve algum pensamento nele, mas não é tão fácil ver a falta de uma chamada de método e determinar se a falta foi intencional ou não. Para um caso simples como esse, essa é provavelmente a abordagem que eu adotaria.fonte
A sobrecarga de construtores seria uma solução simples e direta aqui:
É melhor do que ligar
.setText
mais tarde, porque dessa forma nada precisa ser substituído,actionText
pode ser a coisa pretendida desde o início.À medida que seu código evolui e você precisará de ainda mais flexibilidade (o que certamente acontecerá), você se beneficiará do padrão de fábrica / construtor sugerido por outra resposta.
fonte
Adicione um método fluente 'setText':
O que poderia ser mais claro do que isso? Se você decidir adicionar outra propriedade personalizável, não há problema.
fonte
setText()
é definido na classe Action da qual MyAction herda. Provavelmente já possui um tipo de retorno nulo.Assim como Kevin Cline disse em sua resposta, acho que o caminho a seguir é criar uma API fluente . Gostaria apenas de acrescentar que a API fluente funciona melhor quando você possui mais de uma propriedade.
Isso tornará seu código mais legível e, do meu ponto de vista, mais fácil e, aham , "sexy" de escrever.
No seu caso, seria assim (desculpe-me por qualquer erro de digitação, já faz um ano desde que escrevi meu último programa java):
E o uso seria assim:
fonte
O conselho para usar construtores ou construtores é bom em geral, mas, na minha experiência, faltam alguns pontos-chave para Ações, que
Eu sugiro fortemente que o nome, a dica de ferramenta, o ícone etc ... sejam lidos em um arquivo de propriedades, XML, etc. Por exemplo, para a ação Abrir arquivo, você poderia passar uma propriedade e ela procuraria
Este é um formato muito fácil de traduzir para o francês, para tentar um novo ícone melhor, etc. Sem tempo de programador ou recompilação.
Este é apenas um esboço, muito resta ao leitor ... Procure outros exemplos de internacionalização.
fonte
É inútil chamar setText (actionText) ou setTooltip ("Minha dica da ferramenta de ação") dentro do construtor; é mais fácil (e você obtém mais desempenho) se você simplesmente inicializar diretamente o campo correspondente:
Se você alterar actionText durante o tempo de vida do objeto correspondente MyAction, deverá colocar um método setter; caso contrário, inicialize o campo apenas no construtor sem fornecer um método setter.
Como dica e imagem são constantes, trate-as como constantes; tem campos:
Na verdade, ao projetar objetos comuns (não beans ou objetos que representam estritamente estruturas de dados), é uma má idéia fornecer setters e getters, pois eles meio que quebram o encapsulamento.
fonte
Eu acho que isso é verdade se formos criar uma classe de ação genérica (como update, que é usada para atualizar Employee, Department ...). Tudo depende do cenário. Se uma classe de ação específica (como atualizar funcionário) (usada em muitos lugares do aplicativo - Atualizar funcionário) for criada com a intenção de manter o mesmo texto, dica de ferramenta e imagem em todos os locais do aplicativo (para o ponto de vista da consistência). Portanto, a codificação pode ser feita para texto, dica de ferramenta e imagem para fornecer o texto, dica de ferramenta e imagem padrão. Ainda para dar mais flexibilidade, para personalizá-los, ele deve ter os métodos setter correspondentes. Tendo em mente apenas 10% dos lugares, temos que mudar isso. A execução de texto de ação sempre do usuário pode causar texto diferente sempre para a mesma ação. Como 'Atualizar Emp', 'Atualizar funcionário', 'Alterar funcionário' ou 'Editar funcionário'.
fonte
Pense em como as instâncias serão usadas e use uma solução que guie, ou até force, os usuários a usá-las da maneira correta, ou pelo menos melhor. Um programador usando essa classe terá muitas outras coisas para se preocupar e pensar. Esta classe não deve ser adicionada à lista.
Por exemplo, se a classe MyAction for imutável após a construção (e possivelmente outra inicialização), ela não deverá ter um método setter. Se na maioria das vezes ele usar o "Meu texto de ação" padrão, deve haver um construtor sem parâmetros, além de um construtor que permita um texto opcional. Agora, o usuário não precisa pensar em usar a classe corretamente 90% do tempo. Se o usuário geralmente deve pensar um pouco no texto, pule o construtor sem parâmetros. Agora, o usuário é forçado a pensar quando necessário e não pode ignorar uma etapa necessária.
Se uma
MyAction
instância precisar ser mutável após a construção completa, você precisará de um setter para o texto. É tentador pular a configuração do valor no construtor (princípio DRY - "Não se repita") e, se o valor padrão geralmente for bom o suficiente, eu o faria. Mas, se não estiver, exigir o texto no construtor força o usuário a pensar quando deve.Observe que esses usuários não são burros . Eles apenas têm muitos problemas reais para se preocupar. Ao pensar na "interface" da sua turma, você também pode impedir que ela se torne um problema real - e desnecessário.
fonte
Na solução proposta a seguir, a superclasse é abstrata e tem todos os três membros configurados para um valor padrão.
A subclasse possui construtores diferentes para que o programador possa instancia-lo.
Se o primeiro construtor for usado, todos os membros terão os valores padrão.
Se o segundo construtor for usado, você fornecerá um valor inicial ao membro actionText, deixando outros dois membros com o valor padrão ...
Se o terceiro construtor for usado, você o instancia com um novo valor para actionText e toolTip, deixando imageURl com o valor padrão ...
E assim por diante.
fonte