0

How I can modify this class to follow DIP (Dependency Inversion Principle) in order to remove the two ArrayList dependencies in the constructor? How should the interfaces be?

One thing that confuses me is that the new references points to an ArrayList<type> not just the constructor of a class. And I don't know how to handle that situation...

package mvc.controllers;

import java.util.ArrayList;
import mvc.models.AbstractModel;
import mvc.views.AbstractViewPanel;

public abstract class AbstractController {

    private ArrayList<AbstractViewPanel> registeredViews;
    private ArrayList<AbstractModel> registeredModels;

    public AbstractController() {
        registeredViews = new ArrayList<AbstractViewPanel>();
        registeredModels = new ArrayList<AbstractModel>();
    }

    public void addModel(AbstractModel model) {
        registeredModels.add(model);
        model.addPropertyChangeListener(this);
    }

    public void removeModel(AbstractModel model) {
        registeredModels.remove(model);
        model.removePropertyChangeListener(this);
    }

    public void addView(AbstractViewPanel view) {
        registeredViews.add(view);
    }

    public void removeView(AbstractViewPanel view) {
        registeredViews.remove(view);
    }
    ...
}
Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
Jeflopo
  • 2,192
  • 4
  • 34
  • 46
  • do what? The question is rather wooly and unclear helped by typos certainly and lack of understanding probably. Can you rephrase what you want to know and get more to the point on where you're struggling? – Pete Jan 06 '12 at 09:58
  • Done, I hope that is clearer now. Excuse my grammar errors. English isn't my first thongue/language. – Jeflopo Jan 06 '12 at 10:16
  • This guide http://misko.hevery.com/code-reviewers-guide/ has some really good examples, also covering DI – Wouter de Kort Jan 06 '12 at 10:43
  • The DIP is the Dependency Inversion Principle. Your mistake is easy to make since Dependency Injection is a technique for satisfying the DIP. – Dave Schweisguth Feb 07 '16 at 06:23

3 Answers3

1

It's not really clear what dependency you're trying to remove, but if you want to remove the explicit ArrayList instantiation, you could use constructor injection:

private final List<AbstractViewPanel> registeredViews;
private final List<AbstractModel> registeredModels;

public AbstractController(final List<AbstractViewPanel> registeredViews,
        final List<AbstractModel> registeredModels) {
    this.registeredViews = registeredViews;
    this.registeredModels= registeredModels;
}
artbristol
  • 32,010
  • 5
  • 70
  • 103
  • I thought I had to create interfaces to inject the Arraylists instances... But that's not the point. The interfaces would help me to isolate, or almost isolate (lose couple) the implementations of the methods addModel, addView, removeModel, viewModel... But that's not needed if I just want to externalize the arrays right (reduce depency) The model and view methods then are part of the implementation of this AbstractController class. that's right ? – Jeflopo Jan 07 '12 at 14:50
1

To do it in Dependency Inversion -way, you could do one of the following:

  1. Dependencies to the lists are given in the constructor:

    public abstract class AbstractController {
    
    private List<AbstractViewPanel> registeredViews;
    private List<AbstractModel> registeredModels;
    
    public AbstractController(List<AbstractViewPanel> registeredViews, List<AbstractModel> registeredModels) {
        this.registeredViews = registeredViews;
        this.registeredModels = registeredModels;
    }
    
  2. Add mutators (setters) for the lists:

    public abstract class AbstractController {
    
    private List<AbstractViewPanel> registeredViews;
    private List<AbstractModel> registeredModels;
    
    public AbstractController() {
    }
    
    public void setRegisteredViews(List<AbstractViewPanel> views) {
       this.registeredViews = views;
    }
    
    public void setRegisteredModels(List<AbstractModel> models) {
       this.registeredModels = models;
    }
    

Btw, I changed the ArrayLists to Lists. There's no need to introduce a dependency on the List implementation.

Kaitsu
  • 4,094
  • 3
  • 30
  • 37
  • Really appreciated to see more than one way to do it :) Thank you. Consider my reply to artbristol your reply too. Both were very useful !! – Jeflopo Jan 07 '12 at 14:52
0

I wouldn't inject a List into an object, and thus break encapsulation, just for the sake of unit testing it by mocking the list. The List is not an external dependency. It's part of the internals of the class.

If you want to unit-test this class, test that the method who uses the objects stored in the list do actually use them as they should. You should also test that the propertyChange method is called when you change a property of a model that you've added to the controller.

Or you could add a getView() and a getModels() method (potentially protected), to test that the addition worked as expected.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Then you are pointing that I was trying to resolve a problem that isn't there ? :D That I've created the problem... I like what you're pointing too. However, i was also looking to be able to do things like that... whether it is more correct or not, Maybe not in this case... But could fit well in other codes. – Jeflopo Jan 07 '12 at 15:01