Question

In the doJob() method, B is referenced through getter. I personally do not favor this idea and would prefer just b.execute() since I know for sure that getB() will never be modified.

I know that by doing this, would be moving away from encapsulation, but isn't encapsulating B object an overkill here?

class A{
    private B b;

    public void setB(B b){
         this.b = b;
    }

    public B getB(){
         return b;
    }

    public void doJob(){
       getB().execute();
    }
}
Was it helpful?

Solution

It really doesn't matter if you access B through its attribute or getter as long as the attribute remains private (so yes, calling getB() is an overkill, it certainly doesn't break any design pattern).

OTHER TIPS

In this scenario it's probably overkill because it's a simple object. But what if there was lazy loading and your object looked like this..

class A{
    private B b;

    public void setB(B b){
         this.b = b;
    }

    public B getB(){
         this.b = this.b ?? new B();
         return this.b;
    }

    public void doJob(){
       getB().execute();
    }
}

Then it's not overkill to access your private members via a property.

I don't know if this will help you, but if B is a dependency then your object should be setup like this where IB is the interface of the concrete object B. It's an inversion of control pattern to decouple the concrete object B from A. But this is overkill for simple object graphs as well

class A{
    private IB b;

    // Use inversion of control
    public A(IB b){
         this.b = b;
    }

    public IB getB(){
         return this.b;
    }

    public void doJob(){
       getB().execute();
    }
}

You are minimizing risk by using the getter. What if it turns out the B was null in one use case or you need to initialize B because of a new requirement. This pattern allows you to update getB() without having to change anything else in A.

public B getB(){
   if(b == null) {
       b = getEntityManger().findB(); // or wherever you wanted to get B from
   }

   return b;
}

Providing accessor/mutator methods for a private member enables you to add error checking, change the storage of the member, and do other things internal to the class. How you access the member within the class is your choice.

If you discover you need to change the class internals later, then switching to the accessor/mutator can be done then. Certainly this simple example does not require the accessor (getter) method. But realize that a more complex case might benefit by using the getter.

That is ok only if you make the whole class, or at least make the setter and getter, final.

Otherwise this breaks:

class A2 extends A {

    private B2 b;

    @override
    public void setB(B b){
         this.b = new B2(b);
    }

    @override
    public B getB(){
         return b.toB();
    }
}

Now calling the non-overriden doJob() will use wrong member variable.

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