Add code examples, and documentation

This commit is contained in:
Aaron Po
2026-08-12 00:03:32 -04:00
commit 77c16e69f6
79 changed files with 4458 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,102 @@
public interface IIceCream
{
void Prepare();
decimal GetPrice();
}
public class ChocolateIceCream : IIceCream
{
public void Prepare()
{
Console.WriteLine("Preparing a chocolate ice cream.");
}
public decimal GetPrice()
{
return 2.50m; // base price for chocolate ice cream
}
}
public class VanillaIceCream : IIceCream
{
public void Prepare()
{
Console.WriteLine("Preparing a vanilla ice cream.");
}
public decimal GetPrice()
{
return 2.00m; // base price for vanilla ice cream
}
}
public abstract class IceCreamDecorator(IIceCream decorated) : IIceCream
{
protected IIceCream _decorated = decorated;
public abstract void Prepare();
public abstract decimal GetPrice();
}
public class SprinkleDecorator(IIceCream decorated)
: IceCreamDecorator(decorated)
{
public override void Prepare()
{
// call the base first
_decorated.Prepare();
Console.WriteLine("Adding sprinkles!");
}
public override decimal GetPrice()
{
return _decorated.GetPrice() + 0.50m; // add price for sprinkles
}
}
public class ChocolateSyrupDecorator(IIceCream decorated)
: IceCreamDecorator(decorated)
{
public override void Prepare()
{
// call the base prepare first
_decorated.Prepare();
Console.WriteLine("Adding chocolate syrup!");
}
public override decimal GetPrice()
{
return _decorated.GetPrice() + 0.75m; // add price for chocolate syrup
}
}
public class CaramelSyrupDecorator(IIceCream decorated)
: IceCreamDecorator(decorated)
{
public override void Prepare()
{
// call the base prepare first
_decorated.Prepare();
Console.WriteLine("Adding caramel syrup!");
}
public override decimal GetPrice()
{
return _decorated.GetPrice() + 0.75m; // add price for caramel syrup
}
}
internal class Program
{
static void Main(string[] args)
{
decimal price = new CaramelSyrupDecorator(
new ChocolateSyrupDecorator(
new SprinkleDecorator(
new ChocolateIceCream()
)
)
).GetPrice();
Console.WriteLine($"Total price: {price:C}");
}
}

View File

@@ -0,0 +1,66 @@
#region
using System;
using ShapeDecorations.Shapes;
using ShapeDecorations.Shapes.Decorators;
#endregion
namespace ShapeDecorations;
internal class Program
{
private static void Main(string[] args)
{
// scoped to allow for re-use of variable names
{
// First create a concrete shape, since we need one to be able to decorate anything
var circle = new Circle();
circle.Draw();
Console.WriteLine();
// Now we decorate the shape with a red color
var red = new RedColor(circle);
red.Draw();
Console.WriteLine();
// Since the decorator itself is an IShape, we can further decorate it
var blueBorder = new BlueBorder(red);
blueBorder.Draw();
Console.WriteLine();
// And can continue to decorate each ShapeDecorator with as many decorator classes as we like
var huge = new HugeSize(blueBorder);
huge.Draw();
Console.WriteLine();
}
{
// Always must start with a concrete IShape implementation
var rect = new Rectangle();
rect.Draw();
Console.WriteLine();
// Note that the order in which we decorate doesn't matter
var blueBorder = new BlueBorder(rect);
blueBorder.Draw();
Console.WriteLine();
var huge = new HugeSize(blueBorder);
huge.Draw();
Console.WriteLine();
var red = new RedColor(huge);
red.Draw();
Console.WriteLine();
}
}
}

View File

@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<RootNamespace>ShapeDecorations</RootNamespace>
<AssemblyName>ShapeDecorations</AssemblyName>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,15 @@
#region
using System;
#endregion
namespace ShapeDecorations.Shapes;
public class Circle : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a circle");
}
}

View File

@@ -0,0 +1,25 @@
#region
using System;
#endregion
namespace ShapeDecorations.Shapes.Decorators;
/// <summary>
/// See the RedColor class for details on the implementation
/// </summary>
public class BlueBorder : ShapeDecorator
{
/// <summary>
/// See the RedColor class for details on the implementation
/// </summary>
public BlueBorder(IShape decorated)
: base(decorated) { }
public override void Draw()
{
_decorated.Draw();
Console.WriteLine("\tWith a blue border");
}
}

View File

@@ -0,0 +1,26 @@
#region
using System;
#endregion
namespace ShapeDecorations.Shapes.Decorators;
public class HugeSize : ShapeDecorator
{
/// <summary>
/// See the RedColor class for details on the implementation
/// </summary>
/// <param name="decorated">
/// The IShape (whtether concrete IShape or concrete
/// ShapeDecorator) to be decorated
/// </param>
public HugeSize(IShape decorated)
: base(decorated) { }
public override void Draw()
{
_decorated.Draw();
Console.WriteLine("\tThat is enourmous in size");
}
}

View File

@@ -0,0 +1,32 @@
#region
using System;
#endregion
namespace ShapeDecorations.Shapes.Decorators;
public class RedColor : ShapeDecorator
{
/// <summary>
/// Public ctor. Calls the base class with the passed IShape, thus decorating
/// it.
/// Implementation is left empty, as the base class does all the work needed.
/// </summary>
/// <param name="decorated"></param>
public RedColor(IShape decorated)
: base(decorated) { }
/// <summary>
/// Performs the actual drawing logic, but first calls the decorated member,
/// adding its own logic afterwards.
/// </summary>
public override void Draw()
{
// First calls decorated member
_decorated.Draw();
// Then adds additional drawing logic
Console.WriteLine("\tWhich is red in color");
}
}

View File

@@ -0,0 +1,33 @@
namespace ShapeDecorations.Shapes.Decorators;
public abstract class ShapeDecorator : IShape
{
/// <summary>
/// Maintains a reference to the shape which it decorates
/// this allows implementors to add additional steps to the "drawing" process.
/// Marked "protected" so that inheriting classes have access to it.
/// </summary
protected IShape _decorated;
/// <summary>
/// Acceps a reference to any IShape.
/// Since the ShapeDecorator itself IS an IShape, this
/// decorator can also decorate other decorators
/// However, since a ShapeDecorator has to be instantiated with an existing
/// IShape,
/// at some point in the chain of decoration, there must be a concrete shape
/// (specifically, a concrete IShape that was createad without having another
/// IShape passed to it)
/// </summary>
/// <param name="decorated"></param>
public ShapeDecorator(IShape decorated)
{
_decorated = decorated;
}
/// <summary>
/// Marking this abstract satisfies the implementation of IShape,
/// but forces inheriting classes to implement their own drawing logic
/// </summary>
public abstract void Draw();
}

View File

@@ -0,0 +1,6 @@
namespace ShapeDecorations.Shapes;
public interface IShape
{
void Draw();
}

View File

@@ -0,0 +1,15 @@
#region
using System;
#endregion
namespace ShapeDecorations.Shapes;
public class Rectangle : IShape
{
public void Draw()
{
Console.WriteLine("Drawing a Rectangle");
}
}