mirror of
https://github.com/farcasclaudiu/design_pattens.git
synced 2026-06-29 03:01:33 +03:00
WIP creational patterns
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace design_patterns.creational.facadebuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// this sample covers the case when we have multiple builders
|
||||
/// for the same class, that we want to chain
|
||||
/// </summary>
|
||||
public class FacadeBuilderSample
|
||||
{
|
||||
public static async Task Run() {
|
||||
Console.WriteLine("Creational - Facade Builder");
|
||||
|
||||
var product = new ProductBuilder()
|
||||
.Info
|
||||
.WithName("New Product")
|
||||
.WithDetails("product details")
|
||||
.Price
|
||||
.WithPrice(67.12m)
|
||||
.WithDiscountLevel1(4)
|
||||
.WithDiscountLevel2(12)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("product: " + product.ToString());
|
||||
|
||||
// sample with implicit operator casting
|
||||
Product product2 = new ProductBuilder()
|
||||
.Info
|
||||
.WithName("New Product 2")
|
||||
.WithDetails("product details 2")
|
||||
.Price
|
||||
.WithPrice(23.11m)
|
||||
.WithDiscountLevel1(5)
|
||||
.WithDiscountLevel2(10);
|
||||
|
||||
Console.WriteLine("product: " + product2.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public class Product {
|
||||
// first section handled by a builder
|
||||
public string Name { get; set; }
|
||||
public string Details { get; set; }
|
||||
|
||||
// second section handled by another builder
|
||||
public decimal Price { get; set; }
|
||||
public int DiscountPercentLevel1 { get; set; }
|
||||
public int DiscountPercentLevel2 { get; set; }
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Name} : {Details} : {Price} : {DiscountPercentLevel1} : {DiscountPercentLevel2}";
|
||||
}
|
||||
}
|
||||
|
||||
// this acts as a facade
|
||||
public class ProductBuilder
|
||||
{
|
||||
protected Product instance = new Product();
|
||||
|
||||
public ProductInfoBuilder Info => new ProductInfoBuilder(instance);
|
||||
public ProductPriceBuilder Price => new ProductPriceBuilder(instance);
|
||||
|
||||
public Product Build() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static implicit operator Product(ProductBuilder pb) => pb.instance;
|
||||
}
|
||||
|
||||
public class ProductInfoBuilder : ProductBuilder {
|
||||
public ProductInfoBuilder(Product instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public ProductInfoBuilder WithName(string name) {
|
||||
this.instance.Name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProductInfoBuilder WithDetails(string details) {
|
||||
this.instance.Details = details;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class ProductPriceBuilder : ProductBuilder {
|
||||
public ProductPriceBuilder(Product instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public ProductPriceBuilder WithPrice(decimal price) {
|
||||
this.instance.Price = price;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProductPriceBuilder WithDiscountLevel1(int discount) {
|
||||
this.instance.DiscountPercentLevel1 = discount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ProductPriceBuilder WithDiscountLevel2(int discount) {
|
||||
this.instance.DiscountPercentLevel2 = discount;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace design_patterns.creational.fluentbuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Builder is a creational design pattern that
|
||||
/// lets you construct complex objects step by step.
|
||||
/// The pattern allows you to produce different types
|
||||
/// and representations of an object using the same construction code.
|
||||
///
|
||||
/// Fluent builder - limited as it cannot be extended via inheritance
|
||||
/// </summary>
|
||||
public class FluentBuilderSample
|
||||
{
|
||||
public static async Task Run() {
|
||||
Console.WriteLine("Creational - Fluent Builder");
|
||||
|
||||
var product = ProductBuilder
|
||||
.CreateProduct()
|
||||
.WithName("New Product")
|
||||
.WithCategory("Best category")
|
||||
.WithAge(30)
|
||||
.WithPrice(45.22m)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("product: " + product.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public class Product {
|
||||
public int Age { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
public string ProductName { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string Info { get; internal set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ProductName} : {Category} : {Age} : {Price}";
|
||||
}
|
||||
}
|
||||
|
||||
public interface IProductBuilder :
|
||||
IProductName,
|
||||
IProductAge,
|
||||
IProductPrice,
|
||||
IProductCategory {
|
||||
Product Build();
|
||||
}
|
||||
public interface IProductName {
|
||||
IProductBuilder WithName(string productName);
|
||||
}
|
||||
|
||||
public interface IProductAge {
|
||||
IProductBuilder WithAge(int productAge);
|
||||
}
|
||||
|
||||
public interface IProductPrice {
|
||||
IProductBuilder WithPrice(decimal productPrice);
|
||||
}
|
||||
|
||||
public interface IProductCategory {
|
||||
IProductBuilder WithCategory(string productCategory);
|
||||
}
|
||||
|
||||
public class ProductBuilderWithInfo : ProductBuilder {
|
||||
|
||||
IProductBuilder WithInfo(string info){
|
||||
this.instance.Info = info;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public abstract class ProductBuilderBase {
|
||||
|
||||
}
|
||||
|
||||
public class ProductBuilder :
|
||||
IProductBuilder
|
||||
{
|
||||
// set as protected to favor inheritance for extensibility of builder class
|
||||
protected Product instance;
|
||||
|
||||
protected ProductBuilder() {}
|
||||
public static ProductBuilder CreateProduct()
|
||||
{
|
||||
var pb = new ProductBuilder() {
|
||||
instance = new Product()
|
||||
};
|
||||
return pb;
|
||||
}
|
||||
|
||||
public Product Build()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
public IProductBuilder WithAge(int productAge)
|
||||
{
|
||||
this.instance.Age = productAge;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IProductBuilder WithCategory(string productCategory)
|
||||
{
|
||||
this.instance.Category = productCategory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IProductBuilder WithName(string productName)
|
||||
{
|
||||
this.instance.ProductName = productName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public IProductBuilder WithPrice(decimal productPrice)
|
||||
{
|
||||
this.instance.Price = productPrice;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace design_patterns.creational.functionalbuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Builder is a creational design pattern that
|
||||
/// lets you construct complex objects step by step.
|
||||
/// The pattern allows you to produce different types
|
||||
/// and representations of an object using the same construction code.
|
||||
///
|
||||
/// Functional builder - allow builder extension via extended methods
|
||||
/// </summary>
|
||||
public class FunctionalBuilderSample
|
||||
{
|
||||
public static async Task Run() {
|
||||
Console.WriteLine("Creational - Functional Builder");
|
||||
|
||||
var product = new ProductBuilder()
|
||||
.WithName("New Product")
|
||||
.WithCategory("Best category")
|
||||
.WithAge(30)
|
||||
.WithPrice(45.22m)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("product: " + product.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class FunctionalBuilderBase<T, SELF>
|
||||
where SELF : FunctionalBuilderBase<T, SELF>
|
||||
where T : new()
|
||||
{
|
||||
private readonly List<Func<T, T>> actions = new List<Func<T, T>>();
|
||||
|
||||
public SELF Apply(Action<T> action) {
|
||||
actions.Add(t => {
|
||||
action(t);
|
||||
return t;
|
||||
});
|
||||
return this as SELF;
|
||||
}
|
||||
|
||||
public T Build() {
|
||||
return actions.Aggregate(new T(), (t, f) => f(t));
|
||||
}
|
||||
|
||||
}
|
||||
public sealed class ProductBuilder : FunctionalBuilderBase<Product, ProductBuilder> {
|
||||
public ProductBuilder WithName(string name) =>
|
||||
Apply(p => p.ProductName = name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// allow extending the builder
|
||||
/// </summary>
|
||||
public static class ProductBuilderExtensions {
|
||||
public static ProductBuilder WithAge(this ProductBuilder builder, int age) =>
|
||||
builder.Apply(p => p.Age = age);
|
||||
public static ProductBuilder WithCategory(this ProductBuilder builder, string category) =>
|
||||
builder.Apply(p => p.Category = category);
|
||||
public static ProductBuilder WithPrice(this ProductBuilder builder, decimal price) =>
|
||||
builder.Apply(p => p.Price = price);
|
||||
}
|
||||
|
||||
public class Product {
|
||||
public int Age { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
public string ProductName { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string Info { get; internal set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{ProductName} : {Category} : {Age} : {Price}";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user