Lecture thumbnail 0:00 / 0:00 The composite command is one of the most common composite patterns.

And it’s a combination, obviously, of the composite design pattern and the command design pattern.

So where exactly would you encounter a composite command?

Well, in many places, for example, let’s talk about bank accounts.

Let’s suppose that you want to transfer some money from bank account A to bank account B Now, my question

to you is, do you model this as a single command or a combination of commands?

The answer is both.

You model this as a single command, which in turn is a combination of other commands.

And that’s the whole point of the composite design pattern, basically wrapping several elements into

one element which has the same API as a singular element.

So don’t worry, you’ll see this in a moment.

But now let me just show you the command interface.

So I’ve made this interface instead of an abstract class.

And here we have a the traits of a command.

So a command can be called, it can be undone, and it also has getters and setters for indicating whether

it succeeded.

Notice this is also a setter, not just a getter.

So we can change whether a command succeeded or not.

So let’s talk about composite bank account commands.

Now, before we implement the money transfer command, let’s make a general purpose composite command.

I’m going to have a class called Composite Bank Account Command.

So this is going to be a collection of commands.

So here you’re welcome to use any type, any collection type that you want.

You can use a collection of T, I’m going to use a list of T, so list of bank account command.

And obviously I also need to implement the command interface so that I have a composite.

So let’s implement all the missing members here.

So we’re going to fill in those gaps.

So what is a composite command?

Well, when it comes to calling the composite command, you simply call every single one of the contained

commands.

So here we can do a for each take each command and just call it

like so that’s all there is to it.

When it comes to undoing the commands, you want to undo every single command in reverse order.

So here you would say something like the following for each var cmd n and then you would look through

the lists elements in reverse order.

So you would cast the list into an enumerable.

This is unfortunately required because because the list has its own reverse method which is mutating.

We don’t want this, so we just cast this to an enumerable and then we do reverse this way.

We use the Linq, reverse, not the list reverse.

And here we can undo this particular command.

And by the way, we can also do a check just for the sake of safety.

We can check that the command succeeded because you don’t want to undo a command that didn’t succeed.

Here we go.

So we have the call and the undo.

Now, what about the success flags?

How would you properly have a getter and the setter for the success of several commands?

Well, my argument is as follows A composite command can only be considered successful if all of the

constituent parts succeed.

So here I would return this dot all take every single command and make sure it succeeds.

If it succeeded, if every single one has succeeded, then everything is okay.

But if one of those has failed, I would consider the entire operation to have failed.

When it comes to the setter, it’s easy.

Just do for each var cmd in this cmd dot success equals value.

This is how I would implement this.

I’m not sure why you’d want to set every single status on a composite command as opposed to just a single

command.

But this is the approach that we’ll take.

Okay, so now that we have this, we can already start using this paradigm.

We can already make a composite out of, let’s say, a deposit operation plus a withdrawal operation.

So let me make a bank account.

Let’s make a deposit command, just an ordinary command.

So we’ll deposit, let’s say, $100, and then let’s have a withdrawal operation.

So we’ll withdraw, let’s say $50 so we can now build a composite command.

Now I’m going to add a couple of constructors here coming back to the composite bank account command.

Now we are a list so we can have a constructor which takes an I enumerable, but I also want an empty

constructor because that helps with inheritance.

So let’s go into I’m going to go into my generate menu and just, just make a couple of these.

So we have an ordinary command and we have one that gets initialized from an enumerable.

So there’s plenty of options here.

So let’s make a composite bank account command which will perform both the deposit as well as withdrawal

operations.

So here I’ll make a new composite bank account command here, I’ll just make an array and put deposit

and withdrawal in there.

So remember, we have a constructor which.

Takes an innumerable.

So an array like here will do just fine.

And then what we can do is we can try calling the composite command.

So composite dot call and printing out the bank account and we can also try undoing the composite.

So composite dot undo.

So we undo it.

And once again, we print out the bank account balance.

So let’s run all of this and let’s take a look at what we get here.

Okay?

So as you can see, everything is okay.

We deposited 100, so the balance is 100.

We withdrew 50, the balance is 50.

So here is 50.

And then we do symmetric operations for undoing.

So we deposit 50 as a way of undoing the withdrawal.

So we’re now at 100 and then we come back all the way to zero, which is the initial the starting balance

of the bank account.

So it looks like the composite command works.

And now we can start talking about a money transfer command.

Now, what is the problem with implementing a money transfer command?

The problem is the call method, the call method that’s implemented here in composite bank account command

isn’t good enough.

Why is it not good enough?

Well, imagine a situation where you’re transferring money from A to B Now let’s imagine that A has

$100.

So you request a transfer for $1,000.

Now we call a deposit or withdrawal rather, on a and it fails.

But look, look, look here we’ll do a for each.

We don’t really care whether the previous command has succeeded for the subsequent command to be called.

So obviously, in the case of a bank account transfer, transferring money, we have to add special

rules.

We have to have a different implementation of call.

So what I’m going to do here is I’ll make the call and undo methods virtual.

So call will be virtual and just for the sake of symmetry, we’ll have undo virtual as well.

What this allows us to do is it allows us to override these.

Let’s also make success virtual as well.

So now when I make a derived type, I can override this.

So we’re going to have a class called Money Transfer Command.

So this is the implementation of a composite using infrastructure that we’ve already made, namely the

base class right here.

So a money transfer command is a composite bank account command.

Now we’re going to have a constructor which is going to take the accounts from which to take the money,

the account to which to put the money and the amount of money to transfer.

So I’ll have bank account from bank account to and int amount.

So to initialize ourselves, I’ll call the add range.

Remember we inherit from a list so we can call add range here, I’ll just make an array and here we’ll

make the withdrawal and deposit command.

So first of all, we’ll have a bank account command to withdraw some money from the first account,

the amount of money you specified right here.

And the second one will be where we take the to account and we deposit some money.

So we deposit that same amount that we withdrew from the first one.

So this is how you would initialize the steps of the composite command.

Now we want to override the call method to make sure that we have consistency override call.

So remember, the idea is that we don’t want to call a subsequent method a subsequent command if the

previous command failed.

So what I’m going to do is I’ll have bank account command last equals null.

So I’ll always keep a reference to the last command that we actually invoked and then I’ll do my for

each var cmd in this.

So what I’m going to do here is I’ll first of all check whether or not I have a last.

So if last is equal to null or last succeeded, then we can perform the next command.

These are the preconditions.

Either there is no previous command or the previous command succeeded.

So here we can call the command cmd dot call and then we can set the last command to CMD.

But we also have the else case.

That’s when we know that the command has failed because it’s not null.

It doesn’t have a success flag.

So it’s failed.

So what we do is we undo this command so we don’t want to perform this command.

We undo the command and then we simply break.

We jump out of the loop and we don’t perform any additional commands because the whole chain has failed

effectively.

Okay.

So now that we have all of this, let’s actually let’s try using it.

Let’s try using this whole thing.

So I’ll leave.

Actually, let me get rid of all of this.

We’ll make a new scenario here, so I’ll make an account called from,

let’s call it from and let’s make another account too.

Now let’s suppose that the from bank account has $100 on it.

Now let’s try making a transfer command.

So here I’ll say var mtc equals new money transfer command.

So we transfer from to and let’s try transferring 100 to begin with just to see.

What’s going on.

So I will call the command and then I will print out the state of the accounts from and to.

Okay.

So this should hopefully perform the transfer.

Let’s take a look.

Okay.

So the first line here is the initialization.

When we deposited the 100 and then let’s take a look at the transfer.

So as you can see, everything is working fine.

We withdrew 100 and the balance is zero and then we deposited 100.

The balance is now 100 and these are the final balances.

So everything works.

We can also try undoing the money transfer command just so that you can see everything working.

MTC dot undo.

And then let me just duplicate these lines down here and we can run this once again and see the, the

thing coming back to the original.

So here after at this line we are done and then we try to undo and we are back to the starting balances

of 100 and zero.

So as you can see, everything is fine.

Now, really the way to test this is to try to transfer more money than you actually have in the account,

like transferring 1000, for example.

So when we do this, let me once again run this and the result should be different now.

So you see we here is the starting operation and notice there is no output before we print out the balances,

there is nothing happening.

The reason why nothing is happening is because our overridden call is very smart.

As soon as something fails, it undoes that, undoes that operation and breaks out of the whole thing.

So in this demo, I’ve shown how to implement the composite command design pattern.

It is an approach that you will see in many places and you will probably use this yourself.

It’s very convenient and the idea is that you have commands as before, But these commands follow the

design of the composite design pattern, meaning that a collection of commands by virtue of implementing

the command interface can itself be treated as a single command.

Play Play Play Stop Start Play information alert