Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Singleton Pattern: Thread-Safe Lazy<T>, Static Fields and Why the DI Singleton Lifetime Is Better
If you need a single instance, the cleanest route is not the classic Singleton but registering with AddSingleton in the DI container: the single-instance guarantee stays, while global access and hidden dependencies go away. The race in a naive Singleton, the history of double-checked locking, static readonly and beforefieldinit, Lazy<T>'s exception caching, captive dependencies and shared state inside a singleton, with real output.
Factory Method and Static Factories: Delegating Creation to Subclasses or a Single Method
The GoF Factory Method leaves the choice of product to a subclass; a static factory method is a single named method that replaces a constructor, can cache and can return a hidden subtype. The factory-method-in-constructor bug and CA2214, DbConnection.CreateDbCommand, ILoggerFactory and IHttpClientFactory, Func<T>, ActivatorUtilities and keyed services in DI, and ownership of IDisposable products, with real output.
Decorator Pattern: Adding Caching, Logging and Retry Without Touching the Code
Decorator adds behavior to an object at runtime by implementing the same interface and delegating to the object inside; the order of decorators is a design decision that determines what they measure and what they protect. Adding cache, logging and retries to Bookstore's catalog, the Stream family and ownership with leaveOpen, manual DI registration and Scrutor's Decorate, DelegatingHandler and how default interface methods silently bypass a decorator.
Facade Pattern: Presenting a Complex Subsystem Through a Single Door
A facade gathers the knowledge of using several subsystems in the right order, with the right compensation steps, into one class; it gives clients an easy entry point without closing off the subsystem. A CheckoutFacade in Bookstore that coordinates stock, payment, invoicing and notification, the real code behind File.ReadAllTextAsync and GetFromJsonAsync, how Facade differs from Service Layer, Adapter and Mediator, and the god facade trap.
Strategy Pattern in Depth: Keyed Services, IEnumerable<IStrategy> and Func for Runtime Selection
Writing a strategy is easy; choosing the right one at runtime is the hard part: keyed services select by a single key, IEnumerable<IStrategy> with CanHandle looks at several properties of the object, and Dictionary<string, Func<>> selects with the least ceremony when formulas have no dependencies. How registration order silently changes prices, why keyed registrations don't show up in GetServices, and IComparer and StringComparer as strategies in the BCL.