Add factory pattern for engine creation

Replace hard-coded engine instantiation with factory pattern
to enable dependency injection and improve testability.

Changes:
- IEngineFactory: Interface for creating engines
- EngineFactory: Default implementation using AdvancedFitEngine
- MultiBinEngine: Now accepts IEngineFactory via constructor

This eliminates the hard-coded dependency on AdvancedFitEngine
and allows for easy swapping of engine implementations through
configuration or dependency injection.

Benefits:
- Dependency inversion principle satisfied
- Engines can be mocked in tests
- Engine selection can be configured externally
- Single responsibility for engine creation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
AJ
2025-11-18 17:43:22 -05:00
parent 9abd00487b
commit ee5c20bc8b
3 changed files with 50 additions and 5 deletions

View File

@@ -0,0 +1,19 @@
namespace SawCut.Nesting
{
/// <summary>
/// Default implementation of IEngineFactory that creates AdvancedFitEngine instances.
/// Can be extended to support different engine types based on configuration.
/// </summary>
public class EngineFactory : IEngineFactory
{
public IEngine CreateEngine(double stockLength, double spacing, int maxBinCount)
{
return new AdvancedFitEngine
{
StockLength = stockLength,
Spacing = spacing,
MaxBinCount = maxBinCount
};
}
}
}

View File

@@ -0,0 +1,18 @@
namespace SawCut.Nesting
{
/// <summary>
/// Factory interface for creating bin packing engines.
/// Allows for dependency injection and testing without hard-coded engine types.
/// </summary>
public interface IEngineFactory
{
/// <summary>
/// Creates a configured engine instance for bin packing.
/// </summary>
/// <param name="stockLength">The length of stock bins</param>
/// <param name="spacing">The spacing/kerf between items</param>
/// <param name="maxBinCount">Maximum number of bins to create</param>
/// <returns>A configured IEngine instance</returns>
IEngine CreateEngine(double stockLength, double spacing, int maxBinCount);
}
}

View File

@@ -6,6 +6,17 @@ namespace SawCut.Nesting
{
public class MultiBinEngine : IEngine
{
private readonly IEngineFactory _engineFactory;
public MultiBinEngine() : this(new EngineFactory())
{
}
public MultiBinEngine(IEngineFactory engineFactory)
{
_engineFactory = engineFactory ?? throw new ArgumentNullException(nameof(engineFactory));
}
public List<MultiBin> Bins { get; set; }
public double Spacing { get; set; }
@@ -23,11 +34,8 @@ namespace SawCut.Nesting
foreach (var bin in bins)
{
var e = new AdvancedFitEngine();
e.MaxBinCount = bin.Quantity;
e.StockLength = bin.Length;
e.Spacing = Spacing;
var r = e.Pack(remainingItems);
var engine = _engineFactory.CreateEngine(bin.Length, Spacing, bin.Quantity);
var r = engine.Pack(remainingItems);
result.AddBins(r.Bins);
remainingItems = r.ItemsNotUsed.ToList();