Eu tenho o seguinte mapa:
Map<Double, List<SoundEvent>> soundEventCells = new HashMap<Double, List<SoundEvent>>();
Isso HashMap
mapeia double
valores (que são pontos no tempo) para a SoundEvent
'célula' correspondente : cada 'célula' pode conter um número de SoundEvent
s. É por isso que é implementado como um List<SoundEvent>
, porque é exatamente o que é.
Por uma questão de melhor legibilidade do código, pensei em implementar uma classe interna estática muito simples assim:
private static class SoundEventCell {
private List<SoundEvent> soundEvents = new ArrayList<SoundEvent>();
public void addEvent(SoundEvent event){
soundEvents.add(event);
}
public int getSize(){
return soundEvents.size();
}
public SoundEvent getEvent(int index){
return soundEvents.get(index);
}
// .. remove() method unneeded
}
E que a declaração do mapa (e muitos outros códigos) ficaria melhor, por exemplo:
Map<Double, SoundEventCell> soundEventCells = new HashMap<Double, SoundEventCell>();
Isso é um exagero? Você faria isso em seus projetos?
java
design
object-oriented
Aviv Cohn
fonte
fonte
private static
porque só será usada pela classe externa, mas não está relacionada a nenhuma instância específica da classe externa. Não é exatamente esse o uso adequadoprivate static
?Respostas:
Não é um exagero. Comece com as operações necessárias, em vez de começar com "Eu posso usar um HashMap". Às vezes, um HashMap é exatamente o que você precisa.
No seu caso, suspeito que não. O que você provavelmente quer fazer é algo como isto:
Você definitivamente não quer ter um monte de código dizendo isso:
Ou talvez você possa apenas usar uma das implementações do Guava Multimap .
fonte
TimeLine
aula exatamente para esse tipo de coisa :) É um invólucro fino em torno de umaHashMap<Double, SoundEventCell>
(eventualmente eu fui com a ideia emSoundEventCell
vez deList<SoundEvent>
). Então, eu posso apenas fazertimeline.addEvent(4.5, new SoundEvent(..))
e ter o material de nível mais baixo encapsulado :)Embora possa ajudar na legibilidade em algumas áreas, também pode complicar as coisas. Pessoalmente, evito envolver ou estender coleções por motivos de fluência, pois o novo invólucro, na leitura inicial, implica para mim que pode haver um comportamento do qual preciso estar ciente. Considere um tom de princípio da menor surpresa.
Aderir à implementação da interface significa que só preciso me preocupar com a interface. A implementação concreta pode, é claro, abrigar um comportamento adicional, mas não preciso me preocupar com isso. Então, quando estou tentando encontrar o caminho através do código de alguém, prefiro as interfaces simples para facilitar a leitura.
Se, por outro lado, você estiver encontrando um caso de uso que se beneficia de um comportamento adicionado, terá um argumento para melhorar o código criando uma classe de pleno direito.
fonte
List
pode fazer, e faz todas essas coisas por um bom motivo.SoundEventCell
poderia implementarIterable
forSoundEvent
s, que ofereceria o iterador dosoundEvents
membro, para que você pudesse ler (mas não escrever) como qualquer lista. Hesito em mascarar a complexidade quase tanto quanto hesito em usar umList
quando precisar de algo mais dinâmico no futuro.O agrupamento limita sua funcionalidade apenas aos métodos que você decide escrever, basicamente aumentando seu código sem nenhum benefício. No mínimo, tentaria o seguinte:
Você ainda pode escrever o código do seu exemplo.
Dito isto, só fiz isso quando há alguma funcionalidade que a própria lista precisa. Mas acho que seu método seria um exagero para isso. A menos que você tenha um motivo para querer limitar o acesso à maioria dos métodos da Lista.
fonte
Outra solução pode ser definir sua classe de wrapper com um único método que expõe a lista:
Isso fornece a sua classe bem nomeada com código mínimo, mas ainda fornece encapsulamento, permitindo, por exemplo, tornar a classe imutável (fazendo uma cópia defensiva no construtor e usando
Collections.unmodifiableList
no acessador).(No entanto, se essas listas realmente estiverem sendo usadas apenas nesta classe, acho que seria melhor substituí-lo
Map<Double, List<SoundEvent>>
por umMultimap<Double, SoundEvent>
( docs ), pois isso geralmente salva muita lógica e erros de verificação nula.)fonte