Mam następującą mapę:
Map<Double, List<SoundEvent>> soundEventCells = new HashMap<Double, List<SoundEvent>>();
Ten HashMap
mapy double
wartości (które są punktami, w czasie) do odpowiadającej SoundEvent
„komórki”: każdy z „komórek” może zawierać kilka SoundEvent
sekund. Dlatego jest zaimplementowany jako List<SoundEvent>
, ponieważ właśnie tak jest.
Ze względu na lepszą czytelność kodu pomyślałem o zaimplementowaniu bardzo prostej statycznej klasy wewnętrznej, takiej jak:
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
}
I wtedy deklaracja mapy (i wiele innych kodów) wyglądałaby lepiej, na przykład:
Map<Double, SoundEventCell> soundEventCells = new HashMap<Double, SoundEventCell>();
Czy to przesada? Czy zrobiłbyś to w swoich projektach?
java
design
object-oriented
Aviv Cohn
źródło
źródło
private static
dlatego, że będzie używana tylko przez klasę zewnętrzną, ale nie jest związana z żadnym konkretnym wystąpieniem klasy zewnętrznej. Czy to nie jest właściwe użycieprivate static
?Odpowiedzi:
To wcale nie jest przesada. Zacznij od operacji, których potrzebujesz, a nie od „Mogę użyć HashMapy”. Czasami HashMap jest właśnie tym, czego potrzebujesz.
W twoim przypadku podejrzewam, że tak nie jest. To, co prawdopodobnie chcesz zrobić, to coś takiego:
Na pewno nie chcesz mieć dużo kodu mówiącego:
A może możesz po prostu użyć jednej z implementacji Guava Multimap .
źródło
TimeLine
klasę właśnie do takich rzeczy :) Jest to cienkie opakowanie wokółHashMap<Double, SoundEventCell>
(ostatecznie wpadłem na pomysłSoundEventCell
zamiast tegoList<SoundEvent>
). Mogę po prostu zrobićtimeline.addEvent(4.5, new SoundEvent(..))
i zapisać rzeczy niższego poziomu :)Chociaż może to poprawić czytelność w niektórych obszarach, może również komplikować sytuację. Osobiście opieram się na pakowaniu lub rozszerzaniu kolekcji ze względu na płynność, ponieważ nowe opakowanie, podczas pierwszego czytania, sugeruje mi, że może istnieć zachowanie, o którym muszę wiedzieć. Rozważ to odcień zasady najmniejszej niespodzianki.
Trzymanie się implementacji interfejsu oznacza, że muszę się tylko martwić o interfejs. Konkretne wdrożenie może oczywiście zawierać dodatkowe zachowanie, ale nie powinienem się tym martwić. Tak więc, gdy próbuję znaleźć drogę przez czyjś kod, wolę proste interfejsy dla czytelności.
Jeśli z drugiej strony znajdujesz przypadek użycia, który korzysta z dodatkowego zachowania, masz argument za poprawieniem kodu poprzez utworzenie pełnoprawnej klasy.
źródło
List
można zrobić i robi to wszystko z dobrego powodu.SoundEventCell
może zaimplementowaćIterable
dlaSoundEvent
s, który zaoferuje iteratorsoundEvents
członka, więc będziesz mógł czytać (ale nie pisać) jak każdą listę. Waham się zamaskować złożoność prawie tak samo, jak waham się przed użyciem,List
gdy będę potrzebować czegoś bardziej dynamicznego w przyszłości.Zawijanie go ogranicza twoją funkcjonalność tylko do tych metod, które zdecydujesz się napisać, zasadniczo zwiększając kod bez żadnych korzyści. Przynajmniej spróbowałbym:
Nadal możesz napisać kod ze swojego przykładu.
To powiedziawszy, robiłem to tylko wtedy, gdy potrzebna jest funkcjonalność, której sama lista potrzebuje. Ale myślę, że twoja metoda byłaby przesadna. Chyba że masz powód, aby chcieć ograniczyć dostęp do większości metod List.
źródło
Innym rozwiązaniem może być zdefiniowanie klasy opakowania za pomocą jednej metody, która wyświetla listę:
Daje to dobrze znaną klasę z minimalnym kodem, ale wciąż zapewnia enkapsulację, co pozwala np. Uczynić klasę niezmienną (poprzez wykonanie kopii obronnej w konstruktorze i użycie
Collections.unmodifiableList
w akcesorium).(Jednakże, jeśli te listy są rzeczywiście wykorzystywane tylko w tej klasie, myślę, że zrobisz lepiej zastąpić
Map<Double, List<SoundEvent>>
zMultimap<Double, SoundEvent>
( docs ), jako że często oszczędza dużo zerowej sprawdzania logiki i błędów).źródło