Skip to content

Commit 943f7e2

Browse files
committed
Added command pattern
1 parent 083b77f commit 943f7e2

10 files changed

Lines changed: 188 additions & 0 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
6+
namespace SoftwarePatterns.Core.Command
7+
{
8+
public class CommandFactory : ICommandFactory
9+
{
10+
private IEnumerable<Type> availableCommand;
11+
public string CommandName { get; private set; }
12+
public string Description { get; private set; }
13+
14+
public ICommand MakeCommand(string name)
15+
{
16+
var commandType = FindRequestedCommand(name);
17+
18+
if (commandType != null)
19+
{
20+
return (ICommand)Activator.CreateInstance(commandType,null);
21+
}
22+
return new NotFoundCommand();
23+
}
24+
25+
private Type FindRequestedCommand(string name)
26+
{
27+
var command = AvailableCommand.FirstOrDefault(type => String.Equals(type.Name.Replace("Command", ""), name, StringComparison.InvariantCultureIgnoreCase));
28+
return command;
29+
}
30+
31+
public IEnumerable<Type> AvailableCommand
32+
{
33+
get
34+
{
35+
return availableCommand ?? (availableCommand = GetAvailableCommands());
36+
}
37+
}
38+
39+
private static IEnumerable<Type> GetAvailableCommands()
40+
{
41+
var list = Assembly.GetExecutingAssembly()
42+
.GetTypes()
43+
.Where(type => type.GetInterfaces().Contains(typeof (ICommand)))
44+
.ToList();
45+
46+
return list;
47+
}
48+
}
49+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Command
4+
{
5+
public interface ICommand
6+
{
7+
void Execute();
8+
}
9+
10+
public class NotFoundCommand : ICommand
11+
{
12+
public void Execute()
13+
{
14+
Console.WriteLine("Command not found");
15+
}
16+
}
17+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
5+
namespace SoftwarePatterns.Core.Command
6+
{
7+
public interface ICommandFactory
8+
{
9+
ICommand MakeCommand(string name);
10+
IEnumerable<Type> AvailableCommand { get; }
11+
}
12+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
In the command pattern we use an object to represent and encapsulate all the information needed to call a method at a later time.
2+
3+
We have a client which executes commands these commands useually have a receiver object that the command call to do the actual work. There is also an optional invoker object that the command can be
4+
passed to in order to perform command book keeping.
5+
6+
Traits:
7+
The command must be completely self contained it should never get any arguments from the client
8+
Excellent for maintaining open closed principle
9+
10+
Usage scenario:
11+
12+
Logging
13+
Undo
14+
Validation
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Command
4+
{
5+
public class ShipOrderCommad : ICommand
6+
{
7+
public void Execute()
8+
{
9+
Console.WriteLine("Ship the order");
10+
}
11+
}
12+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
3+
namespace SoftwarePatterns.Core.Command
4+
{
5+
public class UpdateQuantityCommand : ICommand
6+
{
7+
public int NewQuantity { get; set; }
8+
9+
private const int oldQuantity = 5;
10+
11+
public void Execute()
12+
{
13+
//simulate updating db
14+
Console.WriteLine("Database updated");
15+
16+
//simulate logging
17+
Console.WriteLine("LOG: Updated order quantity from {0} to {1}", oldQuantity, NewQuantity);
18+
}
19+
}
20+
}

‎src/SoftwarePatterns.Core/SoftwarePatterns.Core.csproj‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@
6868
<Compile Include="ChainOfResponsability\IExpenseApprover.cs" />
6969
<Compile Include="ChainOfResponsability\IExpenseHandler.cs" />
7070
<Compile Include="ChainOfResponsability\IExpenseReport.cs" />
71+
<Compile Include="Command\CommandFactory.cs" />
72+
<Compile Include="Command\ICommand.cs" />
73+
<Compile Include="Command\ICommandFactory.cs" />
74+
<Compile Include="Command\ShipOrderCommad.cs" />
75+
<Compile Include="Command\UpdateQuantityCommand.cs" />
7176
<Compile Include="EnumerationClass\EmployeeType.cs" />
7277
<Compile Include="EnumerationClass\Enumeration.cs" />
7378
<Compile Include="Extensions.cs" />
@@ -78,8 +83,10 @@
7883
<Content Include="Bridge\ReadMe.txt" />
7984
<Content Include="Builder\ReadMe.txt" />
8085
<Content Include="ChainOfResponsability\ReadMe.txt" />
86+
<Content Include="Command\ReadMe.txt" />
8187
<Content Include="EnumerationClass\ReadMe.txt" />
8288
</ItemGroup>
89+
<ItemGroup />
8390
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
8491
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
8592
Other similar extension points exist, see Microsoft.Common.targets.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using SoftwarePatterns.Core.Command;
2+
using Xunit;
3+
4+
namespace SoftwarePatterns.Tests.Command
5+
{
6+
public class CommandFactoryTests
7+
{
8+
public class MakeCommandMethod
9+
{
10+
[Fact]
11+
public void ShouldReturnNotFoundCommandWhenCommandNameWrong()
12+
{
13+
var factory = new CommandFactory();
14+
var command = factory.MakeCommand("Barry");
15+
16+
Assert.Equal(typeof(NotFoundCommand), command.GetType());
17+
}
18+
19+
[Fact]
20+
public void ShouldReturnCommandWhenCorrectNameProvided()
21+
{
22+
var factory = new CommandFactory();
23+
var command = factory.MakeCommand("UpdateQuantity");
24+
25+
Assert.Equal(typeof(UpdateQuantityCommand), command.GetType());
26+
}
27+
}
28+
}
29+
}

‎src/SoftwarePatterns.Tests/SoftwarePatterns.Tests.csproj‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<Compile Include="Bridge\StandardFormatterTests.cs" />
6969
<Compile Include="Builder\EmpolyeeBuilderTests.cs" />
7070
<Compile Include="ChainOfResponsability\ExpenseHandlerChainTests.cs" />
71+
<Compile Include="Command\CommandFactoryTests.cs" />
7172
<Compile Include="Properties\AssemblyInfo.cs" />
7273
</ItemGroup>
7374
<ItemGroup>

‎src/SoftwarePatterns/Program.cs‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using SoftwarePatterns.Core;
45
using SoftwarePatterns.Core.Adapter;
56
using SoftwarePatterns.Core.Bridge;
67
using SoftwarePatterns.Core.Builder;
78
using SoftwarePatterns.Core.ChainOfResponsability;
9+
using SoftwarePatterns.Core.Command;
810
using SoftwarePatterns.Core.EnumerationClass;
911

1012
namespace SoftwarePatterns
@@ -93,6 +95,31 @@ class Program
9395

9496
#endregion
9597

98+
#region Command
99+
100+
public static void Main(string[] args)
101+
{
102+
var factory = new CommandFactory();
103+
104+
var commands = factory.AvailableCommand;
105+
106+
Console.WriteLine("Commands:");
107+
commands.ForEach(type => Console.WriteLine(type.Name));
108+
Console.WriteLine();
109+
110+
Console.WriteLine("What command do you want to run?");
111+
112+
var arguments = Console.ReadLine();
113+
114+
var command = factory.MakeCommand(arguments);
115+
116+
command.Execute();
117+
118+
Console.ReadLine();
119+
}
120+
121+
#endregion
122+
96123
#region Chain of responsability
97124

98125
//public static void Main()

0 commit comments

Comments
 (0)