Question

I have been told to develop my code according to the following code example:

Class Dogs{
   List<Dog> listOfDogs = new ArrayList<Dog>();
   // Setters, getters...
}

Class Dog{
   // Attributes and methods
}

The question is: why is it better to implement a Dogs class as a container for the ArrayList of Dog objects, instead of just referring to a simple ArrayList. Is this considered encapsulation?

Was it helpful?

Solution

Basically, creating a Dogs class provides you with additional layer of indirection.

This means that all your other code will reference (i.e. use) only the Dogs class, but not the internal list. This, in turn, means that whenever you decide to switch from using list to, say, using plain arrays internally (or to change Dogs's implementation in any other way, for that matter), you can readily do so.

That's a motivation for it. As for the question of it being 'better', that depends strongly on whether you can limit usage of the internal container by a stable Dogs's API. If you can, creating a Dogs class is justified. Otherwise, it's simpler and easier to just go ahead and use List.

One example of the aforementioned 'stable API' is an application of the Visitor pattern. In this case, the Dogs class shall have a single visit() method accepting a visitor argument. A visitor 'knows' how to process a Dog, but is completely unaware of the Dogs internal structure. Which is a good thing.

OTHER TIPS

I can see why someone asked you to do this although just like the other answers suggest, this is too broad of a question to answer correctly. Depends on the scenario.

Now the justification here could be that when you have a container for a Dog objects you get to control how these objects are created, accessed and changed. If you just have a List lying around you can't really control proper access or Add/Delete operations to it. However if you have a Dogs class. You can return readonly lists, don't allow addition of dogs that are of certain breed, etc. It can basically be a controller class for all that has to do with dogs.

Class Dogs
{
  List listofDogs = new ArrayList<Dog>();

  public void AddDog(Dog newDog)
  {
     //check if valid
  }

  public List<Dog> getDogs()
  {
    //return readonly dogs collection
  }
}

I see no reason to make a separate Dogs class, unless there are other operations to be performed on Dogs as a group besides the standard collections operations of adding, removing, and accessing members. For example, if there was a releaseTheHounds() method or a callEveryoneForDinner() method, etc.

HOWEVER, it may be that what you were told was that you are supposed to use a List type to declare listOfDogs, rather than ArrayList. That is, this:

List listOfDogs = new ArrayList<Dog>();

Instead of this:

ArrayList listOfDogs = new ArrayList<Dog>();

You are doing this already and it is a good practice. Here, the "encapsulation" is the hiding of ArrayList as the implementor of the List interface. This makes it easy to switch to another implementation easily (e.g. TreeList) without having to change any code that accesses listOfDogs.

Last but not least, you really should declare it this way:

List<Dog> listOfDogs = new ArrayList<Dog>();

Then you are ensuring that the List holds Dog instances and nothing else.

it makes serialization to webforms somewhat easier with the mvc frameworks i have used

It depends on your problem and the operations that you want to do on that array list .you may want to extend some operations of the ArrayList or add new one that will be applied to all array list items for instance a method to sort this list in desc order .

I believe they might have wanted you to work on something that resembles 'The object pool pattern'. The Object Pool Design Pattern is a creational design pattern that can improve performance when working with classes that are slow to instantiate. Rather than constructing new objects, reusable objects are retrieved from, and released to, a pool as required.

In this case, Dogs would be the Pool, Dog would be the PooledObject, and any class that uses an object of the PooledObject type would be the client.

We use such implementation when we have a set of method that is typical for a set of objects. So that we focus not on a particular choice of representation but on the shared operations and properties. For example, stack uses this pattern, the operations typically available on a stack are the following: push, remove, determine whether the stack is empty, etc.. and instead of Dog it uses Object; so you can stack any object.

Now you can add object other than Dog, and they will share the same methods.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top