using System.Collections.Generic;
//Decorator pattern is very powerful pattern which can be used for supplementing the inheritance relationship with
//composition based relationship. The basic idea is Attaching additional responsibilities to an object dynamically.
//Decorators provide a flexible alternative to subclassing for extending functionality and it can be implemented
//on several different ways.
//This sample program presented here show that it can be done through Generic and Interface.
//The classes and/or objects participating in this pattern are:
//1. Generic Abstract Decorator
//2. Generic Concrete Decorator
//3. Abstract Component
//4. Concrete Component
namespace Generic.DecoratorPattern
{
// Generic Abstract Decorator
abstract class Decorator<T> : ComputerItem where T : ComputerItem, new()
{
protected readonly T computerItem = new T();
// Constructor
public Decorator(T computerItem)
{
this.computerItem = computerItem;
}
public override void DisplayReport()
{
computerItem.DisplayReport();
}
}
// Generic Concrete Decorator
class Saleable<T> : Decorator<T> where T : ComputerItem, new()
{
protected List<string> Buyers = new List<string>();
// Constructor
public Saleable(T computerItem) : base(computerItem)
{
}
public void SaleItem(string name)
{
Buyers.Add(name);
computerItem.NumStocks--;
}
public void ReturnItem(string name)
{
Buyers.Remove(name);
computerItem.NumStocks++;
}
public override void DisplayReport()
{
base.DisplayReport();
foreach (string buyer in Buyers)
{
Console.WriteLine(" Buyer: " + buyer);
}
}
}
interface IComputerItem
{
void DisplayReport();
}
// Abstract Component
abstract class ComputerItem : IComputerItem
{
private string brand;
public string Brand
{
get { return brand; }
set { brand = value; }
}
private string type;
public string Type
{
get { return type; }
set { type = value; }
}
private int numStocks;
public int NumStocks
{
get { return numStocks; }
set { numStocks = value; }
}
public abstract void DisplayReport();
}
// Concrete Component
class Desktop : ComputerItem
{
public Desktop()
{ }
public Desktop(string brand, string type, int numStocks)
{
this.Brand = brand;
this.Type = type;
this.NumStocks = numStocks;
}
public override void DisplayReport()
{
Console.WriteLine("\n----- Desktop ----- ");
Console.WriteLine(" Brand: {0}", Brand);
Console.WriteLine(" Type: {0}", Type);
Console.WriteLine(" # Stocks: {0}", NumStocks);
}
}
// Concrete Component
class Laptop : ComputerItem
{
public Laptop()
{ }
public Laptop(string brand, string type, int numStocks)
{
this.Brand = brand;
this.Type = type;
this.NumStocks = numStocks;
}
public override void DisplayReport()
{
Console.WriteLine("\n----- Laptop ----- ");
Console.WriteLine(" Brand: {0}", Brand);
Console.WriteLine(" Type: {0}", Type);
Console.WriteLine(" # Stocks: {0}", NumStocks);
}
}
class Program
{
static void Main()
{
// Create desktop
Desktop desktop = new Desktop("HPP", "XM600", 32);
desktop.DisplayReport();
// Create laptop
Laptop laptop = new Laptop("ASUSS", "F3MAP0", 9);
laptop.DisplayReport();
Console.WriteLine("\nMaking laptop saleable:");
Saleable<Laptop> saleLaptop = new Saleable<Laptop>(laptop);
saleLaptop.SaleItem("Customer #1");
saleLaptop.SaleItem("Customer #2");
saleLaptop.SaleItem("Customer #3");
saleLaptop.DisplayReport();
Console.Read();
}
}
}