Załóżmy, że mam następujące rodzaje danych:Dziedziczenie i enkapsulacji klas kolekcji w Javie
class Customer {
String id; // unique
OtherCustData someOtherData;
}
class Service {
String url; // unique
OtherServiceData someOtherData;
}
class LastConnection {
Date date;
OtherConnData someOtherData; // like request or response
}
teraz muszę pamiętać, gdy każdy z odbiorców przyłączonych do każdej z usług.
chciałbym zrobić strukturę:
Map<Customer, Map<Service, LastConnection>> lastConnections;
Lub, aby móc wyszukiwać według identyfikatorów i nie trzeba pisać wszystkie równe() i hashCode():
Map<String, Map<String, LastConnection>> lastConnections;
Teraz mogę przejść dane LastConnection przez
LastConnection connection = lastConnections.get(custId).get(srvUrl);
Wszystko to wydaje się brzydkie, zwłaszcza że muszę przekazać go jako parametry do kilkudziesięciu metod spodziewających mapę map LastConnections, s O myślę tworzenia własnych klas, które mogłoby wyglądać tak:
class CustomerConnections extends HashMap<String, LastConnection> {
}
class AllConnections extends HashMap<String, CustomerConnections> {
public LastConnection get(String custId, String srvUrl) {
return get(custId).get(srvUrl);
}
}
Ok, dowiedziałem się już, że dziedziczenie jest 3v1l, więc spróbujmy skład:
class CustomerConnections {
Map<String, LastConnection> customerConnections;
LastConnection get(String srvUrl) {
return customerConnections.get(srvUrl);
}
... // all other needed operations;
}
class AllConnections {
Map<String, CustomerConnections> allConnections;
public LastConnection get(String custId, String srvUrl) {
return get(custId).get(srvUrl);
}
public CustomerConnection get(String custId) {
return allConnections.get(custId);
}
... // all other needed operations;
}
Problem polega na tym, że Nie jestem pewien, jaki byłby najlepszy sposób przestrzegania zasad SOLID i wszystkich najlepszych praktyk. Tworzenie klas, które nic nie robią, z wyjątkiem rozszerzania już istniejących kolekcji, wydaje się być pomnożeniem podmiotów poza koniecznością, ale uczyniłoby mój kod bardziej przejrzystym (Zwłaszcza, gdy istnieją kolejne poziomy - takie jak Mapa AllConnections według miesiąca i tak dalej). Jakieś wskazówki?
Poza tym, że niewinny mały komentarz "wszystkie inne potrzebne operacje" ukrywa metryczny przekaz delegacji. –
@Michael Fair point – butterchicken
Chociaż musisz zrobić to tylko raz. A DelegatingMap implementuje Mapę może być użyta jako klasa podstawowa dla wszystkich takich rozszerzeń. –
paulcm