Tell the class to create a member variable type
Suppose I have a class CityDistrict
like this:
class CityDistrict {
List<House> houses;
...
}
Suppose for some usecases is ArrayList
better for houses
and sometimes for LinkedList
. How would you tell CityDistrict to create that class that it should use forhouses
My three ideas:
1) Is this truncation for parametric classes? Something like
class CityDistrict<T> {
T<House> houses;
...
}
Then you can create CityDistrict<ArrayList>
. But I suppose the information that T should be of type List
is lost here.
2) Or you could create multiple constructors or static factory methods like generateArrayListCityDistrict
, but that's kind of ugly I think.
3) Use some kind of flag in the constructor CityDistrict(int ListFlag)
and match 1
with ArrayList
and so on. Also kind of ugly I guess.
Am I missing the obvious here? What would be a clean and OOP way to handle this situation?
source to share
You can pass Supplier<List<House>>
to the constructor. It will decide which implementation the instance should use:
class CityDistrict {
List<House> houses;
public CityDistrict(Supplier<List<House>> implementation) {
houses = implementation.get();
}
public static void main(String[] args) {
CityDistrict arrayListImpl = new CityDistrict(ArrayList::new);
CityDistrict linkedListImpl = new CityDistrict(LinkedList::new);
}
}
Although, I'm not sure if it's okay for the API user to decide what implementation should be used internally (especially if it might affect some performance issues). This violates the encapsulation rules a little. And it's important if you care about OOP techniques (which you should usually do).
I would rather provide a default implementation (a ArrayList
good choice here) and add the ability to switch to the desired implementation using a factory method:
class CityDistrict {
List<House> houses;
private CityDistrict(Supplier<List<House>> supplier) {
houses = supplier.get();
}
public CityDistrict() {
this(ArrayList::new);
}
public CityDistrict with(Supplier<List<House>> implementation) {
return new CityDistrict(implementation);
}
}
source to share