Add code examples, and documentation
This commit is contained in:
@@ -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>
|
||||
102
patterns/decorator/IceCreamDecorations/Program.cs
Normal file
102
patterns/decorator/IceCreamDecorations/Program.cs
Normal 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}");
|
||||
}
|
||||
}
|
||||
66
patterns/decorator/ShapeDecorations/Program.cs
Normal file
66
patterns/decorator/ShapeDecorations/Program.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
15
patterns/decorator/ShapeDecorations/Shapes/Circle.cs
Normal file
15
patterns/decorator/ShapeDecorations/Shapes/Circle.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
#region
|
||||
|
||||
using System;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ShapeDecorations.Shapes;
|
||||
|
||||
public class Circle : IShape
|
||||
{
|
||||
public void Draw()
|
||||
{
|
||||
Console.WriteLine("Drawing a circle");
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
6
patterns/decorator/ShapeDecorations/Shapes/IShape.cs
Normal file
6
patterns/decorator/ShapeDecorations/Shapes/IShape.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace ShapeDecorations.Shapes;
|
||||
|
||||
public interface IShape
|
||||
{
|
||||
void Draw();
|
||||
}
|
||||
15
patterns/decorator/ShapeDecorations/Shapes/Rectangle.cs
Normal file
15
patterns/decorator/ShapeDecorations/Shapes/Rectangle.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
#region
|
||||
|
||||
using System;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace ShapeDecorations.Shapes;
|
||||
|
||||
public class Rectangle : IShape
|
||||
{
|
||||
public void Draw()
|
||||
{
|
||||
Console.WriteLine("Drawing a Rectangle");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user