5

I'm learning about the design patterns and I encountered a problem which I cant resolve. I'm writing a client/server script. The administrator client send a task with its task data in json format, and the server should instantiate an object accordingly to the recieved task type, and fill its constructor with correct classes. As you can see bellow there are two example class.

public class StartProcessing implements ITask{
    private final IProcessor dataProcessor;

    public StartProcessing(IProcessor dataProcessor){
        this.dataProcessor = dataProcessor;
    }

    @Override
    public void ProcessTask() {
        this.dataProcessor.StartProcess();
    }

}

public class StartQueueFiller implements ITask{

    private IQueueFiller queueFiller;

    public StartQueueFiller(IQueueFiller queueFiller){
        this.queueFiller = queueFiller;
    }

    @Override
    public void ProcessTask() {
        this.queueFiller.Start();
    }

}

interface ITask {
    public void ProcessTask();
}

I've tried something like this, but I'll have like 50 different process and hundreds of tasks, so the constructor will be unmanageable, and I think the factory pattern is not so good in this case, and probably I just miss the point of the pattern. So how you would solve this problem? What should I use instead of the factory pattern?

public class TaskFactory(){

    private final IProcessor processor;
    private final IQueueFiller queuefiller;

    public TaskFactory(IProcessor processor, IQueueFiller queuefiller){
        this.processor = processor;
        this.queuefiller = queuefiller;
    }

    public ITask Create(String task){
        switch(task){
            case "startprocessor":
                return new StartProcessing(this.processor);
            case "startqueuefiller":
                return new StartQueueFiller(this.queuefiller);
        }
    }

}
3
  • 1
    You could use the Abstract Factory pattern, maybe mixed with a builder approach Commented Jan 15, 2018 at 16:12
  • As far as I know if I use abstract factory pattern, the factories should share a common interface, because of this I think I cant use the abstract factory pattern, or I just misinterpret the abstract factory pattern? Commented Jan 15, 2018 at 16:17
  • Take a look at Daniel Pryden's answer Commented Jan 15, 2018 at 16:18

1 Answer 1

5

I would just use the Abstract Factory pattern:

public interface TaskFactory {
    Task create();
}

Then we can store a bunch of factories in a data structure of some kind, e.g.:

private final Map<String, TaskFactory> factoriesMap = new HashMap<>();

void registerFactory(String identifier, TaskFactory factory) {
    factoriesMap.put(identifier, factory);
}

public Task create(String identifier) {
    return factoriesMap.get(identifier).create();
}

Then we can register different kinds of factories using a lambda or something:

Processor processor = ...;
registerFactory("startprocessor", () -> new StartProcessingTask(processor));

etc.

At some point you're going to realize that your "factory map" is basically a kind of Service Locator, in which case you either need to double-down on that, or find an alternative solution. I tend to prefer Dependency Injection as an approach here. Depending on your DI environment, you might make all your TaskFactory instances injectable using qualifiers. You can either bind lazy providers of actual task objects, or bind a factory-like object (e.g. "assisted inject").

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

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.