Repository Pattern

This pattern is for separating business code from data access. It provides separation of concerns and better testability.

Sample generic repository interface can look like this:

public interface IRepository
{
	IQueryable Find(Expression<Func> predicate);
	void Add(T entity);
	void Remove(T entity);
}

Command Pattern

Command pattern allows you to encapsulate a command as an object.

Interface ICommand has only one method: Execute. In this place you can also put Undo method if you would like to have this kind of functionality.

    public interface ICommand
    {
        void Execute();
    }

I would like to have possibitity to register person for some kind of training. To do this I am creating RegisterForTrainingCommand class that implements ICommand interface.

 
    public class RegisterForTrainingCommand : ICommand
    {
        private readonly ITraining _training;
        private readonly IPerson _person;

        public RegisterForTrainingCommand(ITraining training, IPerson person)
        {
            _training = training;
            _person = person;
        }

        public void Execute()
        {
            _training.Register(_person);
        }
    }

Once I have possibility to register for training I can also create command for paying for training.

    public class PayForTrainingCommand : ICommand
    {
        private readonly ITraining _training;
        private readonly IPerson _person;
        private readonly decimal _amount;

        public PayForTrainingCommand(ITraining training, IPerson person, decimal amount)
        {
            _training = training;
            _person = person;
            _amount = amount;
        }

        public void Execute()
        {
            _training.Pay(_person, _amount);
        }
    }

Now, I am creating Invoker class which is responsibility for executing all passing commands.

    public class Invoker
    {
        private readonly List _commands;

        public Invoker(List commands)
        {
            _commands = commands;
        }

        public void ExecuteCommands()
        {
            _commands.ForEach(x=>x.Execute());
        }
    }

We need an implementation of Traning class as well as Person class

    public class Training : ITraining
    {
        public string Name { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public decimal Price { get; set; }

        public void Register(IPerson person)
        {
            Console.WriteLine("{0} {1} has been registered for training {2}", person.FirstName, person.LastName, Name);
        }

        public void Pay(IPerson person, decimal amount)
        {
            Console.WriteLine("{0} {1} has been payed {2} for training {3}", person.FirstName, person.LastName, amount, Name);
        }
    }
public class Person : IPerson
    {
        public int Id { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }
    }

The main application looks like this

    class Program
    {
        static void Main(string[] args)
        {
            var vsTraining = new Training { Name = "Visual Studio 2012" };
            var sqlTraining = new Training {Name = "Microsoft SQL 2012"};

            var personKowalski = new Person {Id = 1, FirstName = "Jan", LastName = "Kowalski"};
            var personNowak = new Person {Id = 2, FirstName = "Krzysztof", LastName = "Nowak"};

            var commands = new List
            {                   
                new RegisterForTrainingCommand(vsTraining, personKowalski),
                new RegisterForTrainingCommand(sqlTraining, personNowak),
                new PayForTrainingCommand(sqlTraining, personNowak, 2200.99M)
            };

            var invoker = new Invoker(commands);
            invoker.ExecuteCommands();
        }
    }

Decorator Pattern

Zastosowanie wzorca Decorator na przykładzie produktu i ofert specjalnych.
Wzorzec ten pozwala nam na dynamiczną zmianę/rozszerzanie zachowania istniejących klas.

    public abstract class Item
    {
        public abstract int Id { get; set; }

        public abstract string Name { get; set; }

        public abstract decimal Price { get; set; }
    }

Klasa Product dziedziczy z naszej abstrakcyjnej klasy Item.

    public class Product : Item
    {
        public override int Id { get; set; }

        public override string Name { get; set; }

        public override decimal Price { get; set; }
    }

Definicja abstrakcyjnej klasy dekoratora dla typu Item, wraz z implementacją wyliczenia nowej ceny dla produktu.

    public abstract class ProductDecoratorBase : Item
    {
        private readonly Item _item;

        public decimal Discount { get; protected set; }

        public ProductDecoratorBase(Item item)
        {
            _item = item;
        }

        public override int Id
        {
            get
            {
                return _item.Id;
            }
            set
            {
                _item.Id = value;
            }
        }

        public override string Name
        {
            get
            {
                return _item.Name;
            }
            set
            {
                _item.Name = value;
            }
        }

        public override decimal Price
        {
            get
            {
                var newPrice = _item.Price - Discount;

                return newPrice < 0 ? 0 : newPrice;
            }
            set
            {
                _item.Price = value;
            }
        }
    }

Definicja klasy SpecialOffer na bazie naszego dekoratora z promocyjnym upustem w wysokości 500zł.

    public class SpecialOffer : ProductDecoratorBase
    {       
        public SpecialOffer(Item product) : base(product)
        {
            Discount = 500;   
        }               
    }

Definicja klasy WeekendSpecialOffer na bazie naszego dekoratora z promocyjnym upustem w wysokości 750zł.

    public class WeekendSpecialOffer : ProductDecoratorBase
    {        
        public WeekendSpecialOffer(Item item) : base(item) 
        {
            Discount = 750;
        }
    }

Poniżej przykład zastosowania zaimplementowanego wzorca.

    class Program
    {
        static void Main(string[] args)
        {
            //Decorator
            Item laptop = new Product { Id = 1, Name = "Laptop", Price = 2545M };

            SpecialOffer specialOfferForMouse = new SpecialOffer(laptop);
            Console.WriteLine("Special price {0}", specialOfferForMouse.Price);

            WeekendSpecialOffer weekendOffer = new WeekendSpecialOffer(laptop);
            Console.WriteLine("Special weekend price {0}", weekendOffer.Price);

            Console.WriteLine("Original price {0}", laptop.Price);
        }
    }

Wynik działania aplikacji: