0

I have one Worker interface with one method:

interface Worker {
    public void work()
}

I have 2 classes that implements Worker,

class RoadWorker implements Worker {
    public void setPropertyA() {}
    public void work() {}
}

another one,

class GardenWorker implements Worker {
    public void setPropertyB() {}
    public void work() {}
}

In my Application class - based on some input flag - I want to instantiate one specific type of worker...

class Application {
    // flag
    String whichWorker = "Road";

    // instantiate
    if (whichWorker == "Road") {
        RoadWorker worker = new RoadWorker();
        worker.setPropertyA();
    } else {
        GardenWorker worker = new GardenWorker();
        worker.setPropertyB();
    }

    // use
    worker.work();  <----- OF COURSE THIS DOES NOT WORK (no reference)

So, I tried this -

class Application {
    // flag
    String whichWorker = "Road";
    Worker worker;

    // instantiate
    if (whichWorker == "Road") {
        worker = new RoadWorker();
        worker.setPropertyA(); <----- DOES NOT WORK 
    } else {
        worker = new GardenWorker();
        worker.setPropertyB(); <----- DOES NOT WORK 
    }

    // use
    worker.work();  

My question is - how do I design my program to achieve this requirement? I know one crude option is to define worker as Object but then I will have to do lots of lots of type casting that I don't want. Can anyone please suggest?

1
  • Do not use == to compare strings!!!! Commented Dec 24, 2014 at 18:37

4 Answers 4

2
Worker anyworker = null;
if ("Road".equals( whichWorker )) {
    RoadWorker worker = new RoadWorker();
    worker.setPropertyA();
    anyworker = worker;
} else {
    GardenWorker worker = new GardenWorker();
    worker.setPropertyB();
    anyworker = worker;
}

Or pass the specific property values in the subclass constructor.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. That looks simple to me. Would you know what is the dis/advantage of this approach over passing values through constructor approach?
1

Use constructors to set properties or a factory pattern.

The first solution is simpler but has its limits:

interface Worker {
    public void work()
}

class RoadWorker implements Worker {
  RoadWorker(PropertyA property) {
   this.property = property;
  }
}

void foo() {
  Worker worker = null;

  if (whichWorker.equals("road")) {
    worker = new RoadWorker(property);
  }

  worker.work();
}

Two side notes:

  • don't compare things with ==, use equals instead
  • use an Enum instead that a string to switch over the worker type, they exist right for this purpose

If you nee more flexibility then a factory method pattern could be more suitable.

Comments

1

You can have the constructors for the worker implementations do the actions specific to those implementations.

RoadWorker:

class RoadWorker implements Worker {
    public RoadWorker() {
        this.setPropertyA();
    }

    public void setPropertyA() {}
    public void work() {}
}

GardenWorker:

class GardenWorker implements Worker {
    public GardenWorker() {
        this.setPropertyB();
    }

    public void setPropertyB() {}
    public void work() {}
}

Then remove those calls to the setProperty methods in your if statement:

class Application {
    // flag
    String whichWorker = "Road";
    Worker worker;

    // instantiate
    if (whichWorker.equals("Road")) {
        worker = new RoadWorker();
    } else {
        worker = new GardenWorker();
    }

    // use
    worker.work();

Note: I changed whichWorker == "Road" to whichWorker.equals("Road"), because for String comparison, you need to use equals instead of ==.

Comments

0

You can cast your worker instance with its proper instanciation type when you set its property.

For instance

if (whichWorker == "Road") {
    worker = new RoadWorker();
    ((RoadWorker)worker).setPropertyA();  
} else {
    worker = new GardenWorker();
    ((GardenWorker)worker).setPropertyB();
}

This should work

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.