在Java中继承和封装集合类

Jak*_*kub 5 java collections inheritance encapsulation

假设我有以下类型的数据:

class Customer {
  String id; // unique
  OtherCustData someOtherData;
}

class Service {
  String url; // unique
  OtherServiceData someOtherData;
}

class LastConnection {
  Date date;
  OtherConnData someOtherData; // like request or response
}
Run Code Online (Sandbox Code Playgroud)

现在我需要记住每个客户何时连接到每个服务.
我会做结构:

Map<Customer, Map<Service, LastConnection>> lastConnections;
Run Code Online (Sandbox Code Playgroud)

或者,为了能够通过id搜索而不必编写所有的equal()和hashCode():

Map<String, Map<String, LastConnection>> lastConnections;
Run Code Online (Sandbox Code Playgroud)

现在我可以通过访问LastConnection数据了

LastConnection connection = lastConnections.get(custId).get(srvUrl);
Run Code Online (Sandbox Code Playgroud)

这一切看起来都很难看,尤其是我必须将它作为参数传递给期望LastConnections地图的数十种方法,所以我想创建自己的类看起来像这样:

class CustomerConnections extends HashMap<String, LastConnection> {
}

class AllConnections extends HashMap<String, CustomerConnections> {
    public LastConnection get(String custId, String srvUrl) {
        return get(custId).get(srvUrl);
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,我已经知道继承是3v1l,所以让我们尝试组合:

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;
}
Run Code Online (Sandbox Code Playgroud)

问题是我不确定什么是尊重SOLID原则和所有最佳实践的最佳方法.创建除了扩展现有集合之外什么都不做的类似乎会使实体成倍增加,但会使我的代码更加清晰(特别是当有下一级别时 - 比如按月映射AllConnections等等).任何指示?

All*_*lan 5

创建除了扩展已经存在的集合之外什么都不做的类似乎是超出必要性的实体

我会将extend更改为encapsulate.您正在隐藏有关如何存储此信息的详细信息.您班级的客户无需了解您如何向他们提供客户连接历史记录.我认为这是一个好主意,因为您可以在不让api的客户端更改其代码的情况下更改基础模型.

但会使我的代码更清晰

这很棒,这是一个很好的理由.YourClass.getCustomerConnection(cId)比yourCollection.get(id).get(id).getConnection()更清晰.即使你是那个人,你也需要让使用这段代码的人的生活更轻松.

(特别是当有下一个级别时 - 比如按月的AllConnections地图等等)

好的,那么你就是在提前规划并使你的代码可扩展.哪个是好的OO练习.在我看来,你自己达成的结论是我会做的.