Table of Contents

Factory Pattern API Reference

Complete API documentation for the Factory pattern in PatternKit.

Namespace

using PatternKit.Creational.Factory;

Factory<TKey, TOut>

Immutable factory mapping keys to parameterless creators.

public sealed class Factory<TKey, TOut>

Type Parameters

Parameter Description
TKey Key type for lookup
TOut Output type created

Delegates

public delegate TOut Creator();

Static Methods

Method Returns Description
Create(IEqualityComparer<TKey>? comparer = null) Builder Create builder with optional comparer

Instance Methods

Method Returns Description
Create(TKey key) TOut Create by key, throws if missing
TryCreate(TKey key, out TOut value) bool Safe creation, returns false if missing

Exceptions

Method Exception Condition
Create InvalidOperationException No mapping for key and no default

Example

var factory = Factory<string, IService>
    .Create(StringComparer.OrdinalIgnoreCase)
    .Map("serviceA", () => new ServiceA())
    .Map("serviceB", () => new ServiceB())
    .Default(() => new FallbackService())
    .Build();

var service = factory.Create("servicea"); // ServiceA (case-insensitive)

Factory<TKey, TOut>.Builder

Builder for configuring the factory.

public sealed class Builder

Methods

Method Returns Description
Map(TKey key, Creator creator) Builder Register key-to-creator mapping
Default(Creator creator) Builder Set default creator
Build() Factory<TKey, TOut> Build immutable factory

Semantics

  • Last mapping wins: Calling Map with the same key replaces the previous
  • Default is optional: Without default, missing keys throw
  • Snapshot: Build() captures current state; further modifications don't affect built factories

Factory<TKey, TIn, TOut>

Factory with input parameter for creators.

public sealed class Factory<TKey, TIn, TOut>

Type Parameters

Parameter Description
TKey Key type for lookup
TIn Input type passed to creators
TOut Output type created

Delegates

public delegate TOut Creator(in TIn input);

Static Methods

Method Returns Description
Create(IEqualityComparer<TKey>? comparer = null) Builder Create builder

Instance Methods

Method Returns Description
Create(TKey key, in TIn input) TOut Create with input
TryCreate(TKey key, in TIn input, out TOut value) bool Safe creation

Example

var math = Factory<string, int, int>
    .Create()
    .Map("double", static (in int x) => x * 2)
    .Map("square", static (in int x) => x * x)
    .Map("negate", static (in int x) => -x)
    .Default(static (in int x) => x)
    .Build();

var doubled = math.Create("double", 5);  // 10
var squared = math.Create("square", 4);  // 16
var identity = math.Create("unknown", 7); // 7 (default)

Factory<TKey, TIn, TOut>.Builder

Builder for factory with input.

public sealed class Builder

Methods

Method Returns Description
Map(TKey key, Creator creator) Builder Register mapping
Default(Creator creator) Builder Set default
Build() Factory<TKey, TIn, TOut> Build factory

Thread Safety

Component Thread-Safe
Builder No - single-threaded configuration
Factory<TKey, TOut> Yes - immutable after build
Factory<TKey, TIn, TOut> Yes - immutable after build
Create Yes - dictionary read only
TryCreate Yes - dictionary read only

Implementation Notes

  • Single dictionary lookup per Create call
  • No LINQ, reflection, or allocations in hot path
  • in TIn parameter avoids struct copies

Complete Example

using PatternKit.Creational.Factory;

// Define types
public interface IFormatter
{
    string Format(object data);
}

public class JsonFormatter : IFormatter
{
    public string Format(object data) => JsonSerializer.Serialize(data);
}

public class XmlFormatter : IFormatter
{
    public string Format(object data) => XmlSerialize(data);
}

public class CsvFormatter : IFormatter
{
    public string Format(object data) => ToCsv(data);
}

// Create factory
public class FormatterFactory
{
    private readonly Factory<string, IFormatter> _factory;

    public FormatterFactory()
    {
        _factory = Factory<string, IFormatter>
            .Create(StringComparer.OrdinalIgnoreCase)
            .Map("json", static () => new JsonFormatter())
            .Map("xml", static () => new XmlFormatter())
            .Map("csv", static () => new CsvFormatter())
            .Default(static () => new JsonFormatter()) // JSON as fallback
            .Build();
    }

    public IFormatter GetFormatter(string format) =>
        _factory.Create(format);

    public bool TryGetFormatter(string format, out IFormatter formatter) =>
        _factory.TryCreate(format, out formatter);
}

// Usage
var factory = new FormatterFactory();
var json = factory.GetFormatter("JSON");     // JsonFormatter
var xml = factory.GetFormatter("xml");       // XmlFormatter
var fallback = factory.GetFormatter("yaml"); // JsonFormatter (default)

if (factory.TryGetFormatter("csv", out var csv))
{
    var output = csv.Format(data);
}

See Also