Object Oriented Programming Patterns for Geeks
The Command Pattern
namespace ooppatterns
{
using System;
using System.Collections.Generic;
internal class Program
{
private static void Main( string[] args )
{
UserCommand UC = new UserCommand( new UserManager() );
UC.Execute( Command.Create );
UC.Status = UserStatus.Active;
UC.Execute( Command.Change );
UC.Execute( Command.Delete );
UC.Status = UserStatus.Archived;
UC.Execute( Command.Change );
UC.Undo();
UC.Undo();
UC.Undo();
Console.ReadLine();
}
}
// Command 'wrapper'
interface ICommand
{
void Execute( Command command );
void Undo();
}
enum Command
{
Nothing,
Create,
Delete,
Update,
Change
}
// This command class executes and stores previous
// operations so that they can be undone.
// It can also ensure only valid operations can
// occur against the object it controls.
class UserCommand : ICommand
{
private struct Operation
{
public Command command;
public UserStatus status;
public Operation( Command command, UserStatus status )
{
this.command = command;
this.status = status;
}
}
private Stack<Operation> _actionList = new Stack<Operation>();
private UserStatus _status = UserStatus.Null;
private UserManager _manager;
public UserStatus Status
{
get { return this._status; }
set { this._status = value; }
}
public UserManager Manager
{
get { return this._manager; }
set { this._manager = value; }
}
public UserCommand( UserManager um )
{
this._manager = um;
}
public void Execute( Command command )
{
switch ( command )
{
case Command.Create:
{
this._manager.CreateAccount();
break;
}
case Command.Update:
{
this._manager.UpdateAccount();
break;
}
case Command.Change:
{
UserStatus oldStatus = this._manager.Status;
this._manager.ChangeStatus( this._status );
this._status = oldStatus;
break;
}
default:
{
Console.WriteLine( "You can not execute this command! : {0}",
command.ToString() );
return;
}
}
this._actionList.Push( new Operation( command, this._status ) );
}
public void Undo()
{
if ( this._actionList.Count > 0 )
{
Operation tmp = this._actionList.Pop();
switch ( tmp.command )
{
case Command.Update:
{
Console.Write( "Undoing Operation: " );
this._manager.UpdateAccount();
break;
}
case Command.Change:
{
Console.Write( "Undoing Operation: " );
this._manager.ChangeStatus( tmp.status );
break;
}
default:
{
Console.WriteLine( "You can not undo this command! : {0}"
, tmp.command.ToString() );
return;
}
}
}
}
}
// Subsystem
enum UserStatus
{
Null,
Active,
Query,
Locked,
Archived
}
class UserManager
{
private UserStatus _status;
public UserStatus Status
{
get { return this._status; }
}
public void CreateAccount()
{
Console.WriteLine( "User has been Created" );
}
public void DeleteAccount()
{
Console.WriteLine( "User has been Deleted" );
}
public void UpdateAccount()
{
Console.WriteLine( "User has been updated" );
}
public void ChangeStatus( UserStatus status )
{
Console.WriteLine( "User Status Was '{0}'. Changed to '{1}'",
this._status.ToString(), status.ToString() );
this._status = status;
}
}
}