2

I'm having a dilemma regarding Command Design Pattern. Receiver is the interface for a class that knows how to perform operations.

In the example case given in the link, receiver class Stock Trade knows how to perform 2 operations, StockTrade#buy and StockTrade#sell. Those operations correspond to 2 existing commands, BuyStockOrder and SellStockOrder.

However, what if additional commands would need to be added, for example FooStockOrder and BarStockOrder? Then, the Receiver interface would have to be changed (and all existing implementations), therefore violating the Open-Closed principle.

How to tackle that problem in a way that Receiver is (almost) never changed?

2
  • does this help? blog.everymansoftware.com/2012/01/… Commented Feb 24, 2015 at 12:41
  • Not quite, because in the provided example, there is no actual Receiver class, which should be responsinble for actually executing the operations that correspond with commands. Commented Feb 24, 2015 at 13:23

1 Answer 1

4

You are forgetting your S.O.L.I.D principles, specifically Dependancy Inversion

Don't define your interface in a way that it specifically expects a concrete implimentation like, BuyStockOrder or SellStockOrder.

Rather define your interface to expect an abstraction like CommandRequest, you will then send in concrete implimentations of the CommandRequest without ever having to change your interface.

Then your Receiver implimentation can decide what to do with it, of course the correct way to deal with this would be using a Strategy Pattern but I'll leave that up to you.

Here is some code as a simple example:

public class Receiver : IReceiver
{
    public CommandResult Process(CommandRequest request)
    {
        // Check the type of request and handle appropriately (or send to who can handle it)

        return new Result();
    }
}

public interface IReceiver
{
    CommandResult Process(CommandRequest request);
}

public abstract class CommandResult
{
    public bool Successful { get; set; }
}

public abstract class CommandRequest
{
}

public class Result : CommandResult
{
}

public class BuyStock : CommandRequest
{
    public string Name { get; set; }
    public decimal Value { get; set; }
}

public class SellStock : CommandRequest
{
    public string Name { get; set; }
    public decimal Value { get; set; }
}

internal class Program
{
    private static void Main(string[] args)
    {
        var receiver = new Receiver();
        var result = receiver.Process(new SellStock { Name = "PAYPL", Value = 100.20m });

        Console.WriteLine(result.Successful ? "Yay!" : "Boo!");
    }
}
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.