Gof.DesignPatterns 2.0.2

dotnet add package Gof.DesignPatterns --version 2.0.2
                    
NuGet\Install-Package Gof.DesignPatterns -Version 2.0.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Gof.DesignPatterns" Version="2.0.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Gof.DesignPatterns" Version="2.0.2" />
                    
Directory.Packages.props
<PackageReference Include="Gof.DesignPatterns" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Gof.DesignPatterns --version 2.0.2
                    
#r "nuget: Gof.DesignPatterns, 2.0.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Gof.DesignPatterns@2.0.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Gof.DesignPatterns&version=2.0.2
                    
Install as a Cake Addin
#tool nuget:?package=Gof.DesignPatterns&version=2.0.2
                    
Install as a Cake Tool

Gof.DesignPatterns

Gof.DesignPatterns is a .NET class library of generic abstractions for a subset of the Gang of Four (GoF) design patterns — those that can be expressed as reusable interfaces (and a few abstract bases).

The package is intended to speed up application code by giving you a shared vocabulary and type-safe contracts. You still write the domain-specific implementations. It is not a complete GoF catalog and not a drop-in replacement for a textbook “one class per pattern” sample.

Supported targets: netstandard2.0, netstandard2.1, net8.0, net9.0, net10.0 (C# 14, nullable reference types enabled).

Content

Disclaimer

Code and opinions in this repository are the author’s personal work, created in spare time. They do not represent the views of any employer and are not affiliated with, supported by, or funded by any employer.

↑ Back to Content

Installation

Latest stable package: Gof.DesignPatterns 2.0.2 on NuGet.

dotnet add package Gof.DesignPatterns --version 2.0.2

Package Manager:

Install-Package Gof.DesignPatterns -Version 2.0.2

↑ Back to Content

What this library provides

Surface Role
DesignPatterns Synchronous interfaces (IStrategy, IAdapter, …)
DesignPatterns.Implementation Shared bases: SingletonBase<T>, DistributiveBuilderBase<T>, CompositeBase, ChainOfResponsibilityBase<TResult, TOperation>
DesignPatterns.Concurrent Async counterparts (ExecuteAsync / HandleAsync / Task-based APIs)

Included patterns

  • Creational: Abstract Factory, Builder, Prototype, Factory Method, Singleton
  • Structural: Adapter, Bridge, Composite
  • Behavioral: Chain of Responsibility, Command, Strategy, Visitor

Patterns without a generic abstraction in this repo (for example Observer or Decorator) are intentionally omitted.

↑ Back to Content


Creational patterns

Creational patterns isolate how objects are created so callers depend on contracts rather than concrete construction.

↑ Back to Content

Abstract Factory

Intent. Provide an interface for creating objects without binding callers to concrete types. In the GoF book, a factory typically exposes several methods that create a family of related products.

In this library. IAbstractFactory<TResult> and IAbstractFactory<TResult, TInput> model one product role per interface. The non-generic IAbstractFactory.Create<TResult, TInput> is a type-parameterized factory: the caller chooses both types at the call site. For a textbook family (for example CreateButton() + CreateScrollBar()), define your own interface with one member per product.

using DesignPatterns;

public sealed class Company
{
    public required string Name { get; init; }
}

public sealed class CompanyFactory : IAbstractFactory<Company, string>
{
    public Company Create(string operationData) => new() { Name = operationData };
}

IAbstractFactory<Company, string> factory = new CompanyFactory();
Company company = factory.Create("Contoso");

↑ Back to Content

Builder

Intent. Separate construction of a complex object from its representation so the same process can produce different results.

In this library. IBuilder<TResult> is a single Build() step. IDistributiveBuilder<TResult> (and DistributiveBuilderBase<TResult>) registers an ordered list of mutations. With safely: true, a mutation that throws is skipped instead of aborting the chain.

using DesignPatterns;
using DesignPatterns.Implementation;

public sealed class Order
{
    public string Customer { get; set; } = "";
    public decimal Total { get; set; }
}

public sealed class StaticReportBuilder : IBuilder<string>
{
    public string Build() => "monthly-report";
}

var order = new DistributiveBuilderBase<Order>()
    .AddMutation(o => o.Customer = "Ada")
    .AddMutation(o => o.Total = 19.99m)
    .Build();

↑ Back to Content

Prototype

Intent. Create new objects by copying a prototypical instance rather than constructing from scratch.

In this library. IPrototype<TThis>.Clone() — you decide shallow vs deep copy.

using DesignPatterns;

public sealed class Document : IPrototype<Document>
{
    public required string Title { get; init; }

    public Document Clone() => new() { Title = Title };
}

var original = new Document { Title = "Spec" };
Document copy = original.Clone();

↑ Back to Content

Factory Method

Intent. Define an interface for creating an object, and let subclasses (or implementations) decide the concrete type.

In this library. IFactoryMethod<TResult>.Instantiate().

using DesignPatterns;

public sealed class Widget { }

public sealed class WidgetFactory : IFactoryMethod<Widget>
{
    public Widget Instantiate() => new Widget();
}

Widget widget = new WidgetFactory().Instantiate();

↑ Back to Content

Singleton

Intent. Ensure a type has one shared instance and a single access point.

In this library. ISingleton<TThis>.GetInstance() and SingletonBase<TThis> (where TThis : new()). The instance is stored in a static field (eager, thread-safe via .NET type initialization). The new() constraint means the language cannot forbid new TThis(); treat GetInstance() as the intended entry point. GetInstance is an instance method: construct a throwaway host and ask it for the shared instance.

using DesignPatterns.Implementation;

public sealed class ConfigurationStore : SingletonBase<ConfigurationStore>
{
    public string Environment { get; set; } = "Production";
}

var first = new ConfigurationStore().GetInstance();
var second = new ConfigurationStore().GetInstance();
// first and second are the same object

↑ Back to Content


Structural patterns

Structural patterns compose classes and objects into larger structures without making them rigid.

↑ Back to Content

Adapter

Intent. Convert one interface into another so otherwise incompatible types can work together.

In this library. IAdapter<TSource, TResult>.Adapt(TSource) converts a separate source object. IAdapter<TResult>.Adapt() is for the case where the implementing type is the source and adapts itself.

using DesignPatterns;

public sealed record Customer(string Name);
public sealed record Company(string CompanyName);

public sealed class CustomerToCompanyAdapter : IAdapter<Customer, Company>
{
    public Company Adapt(Customer source) => new(source.Name);
}

Company company = new CustomerToCompanyAdapter().Adapt(new Customer("Ada"));

Self-adapting form:

using DesignPatterns;

public sealed class LegacyCustomer : IAdapter<Company>
{
    public required string Name { get; init; }

    public Company Adapt() => new(Name);
}

Company adapted = new LegacyCustomer { Name = "Ada" }.Adapt();

The DesignPatterns.Concurrent namespace mirrors both shapes with IAdapter<TResult>.AdaptAsync() and IAdapter<TSource, TResult>.AdaptAsync(TSource).

↑ Back to Content

Bridge

Intent. Split an abstraction from its implementation so the two can vary independently.

In this library. IBridge<TImplementation> exposes Implementer. Domain operations on the abstraction delegate to that implementer.

using DesignPatterns;

public interface IRenderEngine
{
    string RenderCircle(int radius);
}

public sealed class SvgRenderEngine : IRenderEngine
{
    public string RenderCircle(int radius) => $"<circle r=\"{radius}\" />";
}

public sealed class CircleBridge : IBridge<IRenderEngine>
{
    public CircleBridge(IRenderEngine implementer, int radius)
    {
        Implementer = implementer;
        Radius = radius;
    }

    public IRenderEngine Implementer { get; }
    public int Radius { get; }

    public string Draw() => Implementer.RenderCircle(Radius);
}

string svg = new CircleBridge(new SvgRenderEngine(), 10).Draw();

↑ Back to Content

Composite

Intent. Compose objects into a tree and treat leaves and nodes uniformly.

In this library. IComposite (Add, Remove, Clear, IsComposite) and CompositeBase (in-memory list). IsComposite() is true when the node has children.

using DesignPatterns;

public sealed class Node(string name) : CompositeBase
{
    public string Name { get; } = name;
}

var root = new Node("Root");
var child = new Node("Child");
root.Add(child);
bool hasChildren = root.IsComposite(); // true
root.Remove(child);

↑ Back to Content


Behavioral patterns

Behavioral patterns assign responsibilities and shape communication between objects.

↑ Back to Content

Chain of Responsibility

Intent. Pass a request along a chain of handlers until one handles it.

In this library. IChainOfResponsibility<TResult, TOperation> and ChainOfResponsibilityBase<TResult, TOperation>. Each handler has at most one successor. AddNextHandler registers the next link and returns that next handler so you can continue chaining from the tail. RegisterNext replaces the current successor.

using DesignPatterns.Implementation;

public sealed class PositiveHandler : ChainOfResponsibilityBase<string, int>
{
    public override string Handle(int operationData)
    {
        if (operationData > 0) return "Positive";
        return Next is not null ? Next.Handle(operationData) : "Unknown";
    }
}

public sealed class NegativeHandler : ChainOfResponsibilityBase<string, int>
{
    public override string Handle(int operationData)
    {
        if (operationData < 0) return "Negative";
        return Next is not null ? Next.Handle(operationData) : "Unknown";
    }
}

var head = new PositiveHandler();
head.AddNextHandler(new NegativeHandler());
string sign = head.Handle(-3); // "Negative"

↑ Back to Content

Command

Intent. Encapsulate a request as an object so you can parameterize, queue, or log operations.

In this library. ICommand (Execute()), ICommand<TResult>, and ICommand<TResult, TExecutor> (execute against a collaborator).

using DesignPatterns;

public sealed class Ledger
{
    public int Balance { get; set; }
}

public sealed class CreditCommand : ICommand<Ledger, int>
{
    private readonly Ledger _ledger;

    public CreditCommand(Ledger ledger) => _ledger = ledger;

    public Ledger Execute(int amount)
    {
        _ledger.Balance += amount;
        return _ledger;
    }
}

var ledger = new CreditCommand(new Ledger()).Execute(50);

↑ Back to Content

Strategy

Intent. Encapsulate algorithms and make them interchangeable inside a context.

In this library. IStrategy, IStrategy<TResult>, and IStrategy<TResult, TData>.

using DesignPatterns;

public sealed class UpperCaseStrategy : IStrategy<string, string>
{
    public string Execute(string data) => data.ToUpperInvariant();
}

public sealed class LowerCaseStrategy : IStrategy<string, string>
{
    public string Execute(string data) => data.ToLowerInvariant();
}

IStrategy<string, string> strategy = new UpperCaseStrategy();
string text = strategy.Execute("GoF");

↑ Back to Content

Visitor

Intent. Add operations to a type hierarchy without modifying the element types, via double dispatch (Accept / Visit).

In this library. IAcceptor / IVisitor and IAcceptor<TResult> / IVisitor<TResult>. Concrete acceptors typically dispatch to a more specific visitor interface when available.

using System;
using DesignPatterns;

public sealed class StringAcceptor(string value) : IAcceptor<string>
{
    public string Value { get; } = value;

    public string Accept(IVisitor<string> visitor) => visitor.Visit(this);
}

public sealed class UpperCaseVisitor : IVisitor<string>
{
    public string Visit(IAcceptor<string> acceptor) => acceptor switch
    {
        StringAcceptor s => s.Value.ToUpperInvariant(),
        _ => throw new NotSupportedException(acceptor.GetType().Name)
    };
}

string result = new StringAcceptor("gof").Accept(new UpperCaseVisitor());

↑ Back to Content


Concurrent APIs

DesignPatterns.Concurrent mirrors the same pattern set with asynchronous methods (Task / Task<T>). Use these when the work is I/O-bound or already async in your application.

using DesignPatterns.Concurrent;

public sealed class UpperCaseStrategy : IStrategy<string, string>
{
    public Task<string> ExecuteAsync(string data)
        => Task.FromResult(data.ToUpperInvariant());
}

string text = await new UpperCaseStrategy().ExecuteAsync("GoF");

There is also a concurrent ChainOfResponsibilityBase under DesignPatterns.Concurrent.Implementation.

Worked examples used by the test suite live under src/DesignPatterns.Tests/Examples.

↑ Back to Content

Agent skill

Tool-agnostic instructions for applying these abstractions (pattern map, caveats, when not to use the package) live in SKILL.md. Point any coding assistant at that file when implementing or reviewing GoF usage with this library.

↑ Back to Content

Resources

↑ Back to Content

Contributing

Issues and pull requests are welcome: improvements to existing abstractions, additional examples, or documentation fixes.

↑ Back to Content

License

This project is licensed under the Apache License 2.0. See LICENSE.md for the full text.

↑ Back to Content

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.2 125 9/14/2026
2.0.1 140 7/27/2026
1.2.0 277 10/28/2025
1.1.1 249 4/12/2025
1.1.0 1,410 12/13/2023
1.0.4 427 3/7/2023
1.0.3 416 3/7/2023
1.0.2 389 3/7/2023
1.0.1 3,173 6/21/2021
1.0.0 902 5/31/2020

2.0.2
* Added self-adapting Adapter abstractions: IAdapter<TResult>.Adapt() and DesignPatterns.Concurrent.IAdapter<TResult>.AdaptAsync(), for types that adapt themselves instead of a separate source object.
* Reviewed and corrected the XML documentation of every public interface and member, including malformed tags on the Factory Method and Builder abstractions, the previously undocumented IPrototype<TThis>.Clone(), missing type parameter and return descriptions, and inconsistencies between the synchronous and concurrent counterparts.

The package contains abstractions for the following GoF Design Patterns:
Creational patterns provide various object creation mechanisms, which increase flexibility and reuse of existing code.
* Abstract Factory
* Builder
* Prototype
* Factory Method
* Singleton
Structural patterns explain how to assemble objects and classes into larger structures while keeping these structures flexible and efficient.
* Adapter
* Bridge
* Composite
Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.
* Chain Of Responsibility
* Command
* Strategy
* Visitor