Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

abstract initialize() method instead of dependency injection, good practice?

This is a simplified example of something I'm currently designing.

public class ExampleManager {

    private Foo foo;
    private ArrayList<Example> examples;
    ...

    public ExampleManager() {
        this.foo = new Foo();
        this.examples = new ArrayList<Example>();
    }

    public void add(Example e) {
        examples.add(e);
    }

    public void doSomethingWithExamples() {
        for (int i = 0; i < examples.size(); i++) {
            examples.get(i).doSomething();
        }
    }
    ...
}

public abstract class Example {
    private Foo foo;

    public Example(Foo foo) {
        this.foo = foo;
    }
    ...
}

In order to use the library, I have to extend the Example class and add examples to the ExampleManager, which should be the only class that modifies the Example objects.
So I have this Example1 class:

public class Example1 extends Example {

    public Example1(Foo foo) {
        super(foo);
    }
    ...
}

and I currently initialize the manager like this:

ExampleManager manager = new ExampleManager();
Example1 example1 = new Example1(manager.getFoo());
manager.add(example1);

My Example needs the Foo object, but I'm wondering if I could get rid of the Foo argument in the Example1 constructor, so if someone uses the library, doesn't have to call manager.getFoo() in order to create an Example.
I'm thinking about the following solution, which will hide the Foo initialization, so the person who makes use of the library just have to implement the initialize(Foo) method, and the Foo would be initialized automatically when adding the example to the ExampleManager)
In ExampleManager: change the add(Example) method for:

public void add(Example e) {
    e.initialize(foo);
    examples.add(e);
}

In Example, initialize(Foo foo); would be an abstract method, so in Example1 I would have something like this:

@Override
public void initialize(Foo foo) {
    this.foo = foo;
}

Is there any better way to do this?

like image 569
miviclin Avatar asked Nov 30 '25 12:11

miviclin


1 Answers

It seems to me that you have some issues with your OO model in the first place if you need to hand objects around like you describe. - Or maybe your sample code does not reveal the real point of things.

Especially

ExampleManager [...] should be the only class that modifies the Foo objects

and

Example needs the Foo object

look somewhat 'special'.

Can you elaborate what the interactions are between the ExampleManager and the Foo instance, and between the Example and the Foo instance?

Ok, with regard to your comment, I propose the observer pattern, much like your initialize() approach:

public abstract class Example {
    protected Foo callbackHandler;

    public void setCallbackHandler( Foo handler ) {
        this.callbackHandler = handler;
    }

    protected void doCallback( SomeType event ) {
        if ( this.callbackHandler != null ) {
            this.callbackHandler.doYourThing( event );
        }
    }
}

and have ExampleManager register itself or its Foo instance as the callback handler when an object is added to it. Non-abstract subclasses will then only need to call doCallback(...) whenever they want to communicate something and won't have to deal with any setup stuff for the callback.

like image 105
JimmyB Avatar answered Dec 03 '25 00:12

JimmyB



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!