javadesign-patternsrefactoringsystem-designcommand-pattern

Should you use the Command Pattern for requests involving very little logic?


I am new to design patterns and want to get a better understanding of when to implement the command pattern. The command pattern from my understanding is intended to encapsulate a request and the logic needed to fulfill that request into its own object.

It makes sense to create a command for a more complicated request such as generating and saving a PDF report of some database result. For example:

public class PdfExport implements Command {

    private MyEntityDao someDao = new MyEntityDaoImpl();

    public PdfExport( ... ) {
        // Set up command here...
    }

    @Override
    public void execute() {
        List<MyEntity> data = someDao.getData();
        // Complex logic to create and export PDF...
    }

}

But say we just have an extremely simple task such as deleting a single record by its name field. For example:

public class DeleteRecordByName implements Command {

    private MyEntityDao someDao = new MyEntityDaoImpl();
    
    String name;

    public DeleteRecordByName(String name) {
        this.name = name;
    }

    @Override
    public void execute() {
        someDao.deleteByName(name);
    }

}

As you can see there is really no logic being implemented in the second command. The only reason I could come up with for doing this is that you have a layered architecture and want to keep your DAOs out of your client-side code, or to keep the command history.

Is there any benefit to creating a command for something as simple as deleting a single record?

As a follow-up question, is there a certain amount of logic that needs to be involved before it makes any sense at all to create a command object?


Solution

  • Yes, there are numerous reasons for simple Commands. The GoF book lists five points of applicability starting on page 235.

    Use the Command pattern when you want to

    1. parameterize objects by an action to perform... Commands are an object-oriented replacement for callbacks.
    2. specify, queue, and execute requests at different times. A Command object can have a lifetime independent of the original request.
    3. support undo. The Command's Execute operation can store state for reversing its effects in the command itself.
    4. support logging changes so that they can be reapplied in case of a system crash.
    5. structure a system around high-level operations built on primitives operations. Such a structure is common in information systems that support transactions.

    The book adds more details; and some of these features require expanding the Command interface beyond just an execute() method; but in answer to the OP, note that none of these features is concerned with any particularly complex logic the Command executes.

    The quintessential examples of Commands in Java are Runnable and Callable. Consider how often these are implemented with simple and even trivial logic.