sobota, 28 lipca 2012

[Wzorce projektowe] Repository

Analogia z życia:

Chcąc wypożyczyć książki udajemy się do biblioteki. Osoby pracujące tam pomagają nam znaleźć interesujące nas pozycje, podają z magazynu egzemplarze, które nas interesują oraz wstawiają te, które chcemy oddać. W przypadku bibliotek samoobsługowych musielibyśmy wiedzieć o tym, w jaki sposób wyszukiwać i gdzie fizycznie szukać konkretnych egzemplarzy.



Zastosowanie:

Wszędzie tam, gdzie mamy do czynienia z dostępem do danych : połączenia SQL, pobieranie danych z plików, czy webserwisów. Wzorzec repozytorium zapewnia enkapsulację kodu odpowiadającego za połączenie ze źródłem danych w taki sposób. Jest to zatem warstwa pośrednia pomiędzy buissness logic, a źródłem danych, co ułatwia np. testowanie. Wzorzec często występuję w parze z wzorcem Unit of Work odpowiadającym za zatwierdzanie lub wycofywanie zmian.

Zasada działania:

Wprowadza się obiekt repozytorium udostępniający pewne API. W skład API wchodzą takie metody, jak dodawanie encji, usuwanie czy przeszukiwanie kolekcji encji. Bazowe API może być generycznym interfejsem, z którego dziedziczą konkretne repozytoria.

Przykład implementacyjny:

public interface IEntity
    {
        int Id { get; set; }
    }

    public class Customer : IEntity 
    {
        public string Name { get; set; }
        public string Mail { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public int Id { get; set; }
    }
public interface IRepository<T>
        where T : IEntity
    {
        void Add(T instance);
        void Remove(T instance);
        IEnumerable<T> Find(Predicate<T> predicate);
    }

    public class CustomerRepository : IRepository<Customer>
    {
        private List<Customer> _entities;

        private int _count;

        public CustomerRepository()
        {
            try
            {
               LoadDataFromXml();
            }
            catch (Exception)
            {
               Console.WriteLine("Unable to load data");
            }
        }

        public void LoadDataFromXml()
        {
            _entities = new List<Customer>();
            XDocument doc = XDocument.Load("Records.xml");
            var list = doc.Elements("records").Elements("record");
            foreach (var element in list)
            {
                IEnumerable<XElement> properties = element.Elements();
                var customer = new Customer();
                customer.Id = _count++;
                customer.Name = properties.ElementAt(0).Value;
                customer.Mail = properties.ElementAt(1).Value;
                customer.Address = properties.ElementAt(2).Value;
                customer.City = properties.ElementAt(3).Value;
                _entities.Add(customer);
                }
        }

        public void Add(Customer instance)
        {
            instance.Id = _count++;
            _entities.Add(instance);
        }

        public void Remove(Customer instance)
        {
            _entities.Remove(instance);
        }

        public IEnumerable<Customer> Find(Predicate<Customer> predicate)
        {
            return _entities.Where(customer => predicate(customer));
        }
    }
class Program
    {
        static void Main(string[] args)
        {
            IRepository<Customer> repository = new CustomerRepository();

            var results = repository.Find(c => c.City.StartsWith("C"));
            foreach (Customer customer in results)
            {
                Console.WriteLine(customer.City);
            }

            repository.Add(new Customer()
                               {
                                   Name = "Jonnie Walker",
                                   Address = "Elm Street 12/9",
                                   Mail = "jwalker@mit.edu",
                                   City = "NY"
                               });

            Console.ReadKey();
        }
    }

Brak komentarzy:

Prześlij komentarz