C# Visitor Pattern Kullanımı - OOP Design Pattern

Visitor tasarım deseni (ziyaretçi tasarım deseni), behavioral grubuna ait bir tasarım desenidir. Uygulamada ki sınıflara yeni metotlar eklenmesini düzenleyen bir tasarım desenidir. Dofactory.com a göre kullanım sıklığı 20% civarındadır.



Yukarıda belirttiğimiz gibi uygulamaya yetni metotlar eklemesini düzenleyen bir tasarım desenidir Visitor tasarım deseni. Örneğin uygulamamıza bir metot eklemek istiyoruz bu durumda sınıfların uyguladığı arayüze ve bu arayüzü uygulayan sınıflara metot yazılır veya eklenmesi gereken sınıflara eklenir. Arayüze eklersek bu arayüzü uygulayan tüm sınıflara gerekli olsada olmasada eklemek zorunda kalırız. Bu da tasarım prensiplerine aykırı bir haraket olacaktır. Eklenmesi gereken tüm sınıflara tek tek eklersekte kodun anlaşılırlığı bozulacaktır ayrıca bakımıda zorlaşacaktır; metotta bir değişiklik yapılmak istense tüm sınıflardaki metotlar tek tek update edilmesi gerekecektir. Her yeni ihtiyaç için yeni visitor sınıfları yazıp bunu sınıfımızın kullanmasını sağlayarak bu durumları Visitor tasarım deseni ile ortadan kaldırabiliriz.


Örneğimizide şu şekilde tasarlayalım: Mesela bir tablet sınıfımız var ve bu sınıftan türeyen bazı tabletlerin wifi özelliği var bazılarının yok aynı şekilde bir kısmının 3G özelliği var bir kısmının yok. Böyle olunca tabletlerin türetildiği tablet abstract sınıfına WifiAc(), 3GAc() gibi metot tanımlamamız çok saçma olur. Çünkü Wifi özelliği olmayan bir tablette bu metodu kullanabilir olur böyle olunca. Diğer bir yöntemde wifisi olan sınıfları bulup tek tek wifi açma metodunu eklemek ama buda kodu çok anlaşılmaz hale getirecektir. Aynı zamanda sınıfımıza başka bir özellik eklemek istediğimizde yine sınıfımıza müdahale etmek zorunda kalırız. Bu durumu ortadan kaldırmak için istenilen işleri yapan visitor sınıfları yazıp Accept metodu ile bu sınıfların içerisindeki metodları istediğimiz sınıflar için çalıştırabiliriz. Örnek:

UML Diyagramı:





Kod:

    /// <summary>
    /// The 'Tablet' abstract class
    /// </summary>
    public abstract class Tablet
    {
        public string Model { get; set; }
        public string Brand { get; set; }

        public Tablet(string model, string brand)
        {
            Model = model;
            Brand = brand;
        }

        public abstract void Accept(IVisitor visitor);
    }

    /// <summary>
    /// The 'ConcreteElement' class
    /// </summary>
    public class IPad:Tablet
    {
        public IPad(string model, string brand)
            : base(model, brand)
        {
        }

        public override void Accept(IVisitor visitor)
        {
            visitor.Visit(this);
        }
    }

    /// <summary>
    /// The 'ConcreteElement' class
    /// </summary>
    public class GalaxyTab:Tablet
    {
        public GalaxyTab(string model, string brand)
            : base(model, brand)
        {
        }

        public override void Accept(IVisitor visitor)
        {
            visitor.Visit(this);
        }
    }

    /// <summary>
    /// The 'Visitor' interface
    /// </summary>
    public interface IVisitor
    {
        void Visit(Tablet tablet);
    }

    /// <summary>
    /// A 'ConcreteVisitor' class
    /// </summary>
    public class WifiVisitor:IVisitor
    {
        public void Visit(Tablet tablet)
        {
            if (tablet is IPad)
                Console.WriteLine("Ipad wifi has open.");
            else if (tablet is GalaxyTab)
                Console.WriteLine("GalaxyTab does not have wifi option.");
            else
                Console.WriteLine("This object is not a tablet.");
        }
    }

    /// <summary>
    /// A 'ConcreteVisitor' class
    /// </summary>
    public class ThreeGVisitor:IVisitor
    {
        public void Visit(Tablet tablet)
        {
            if (tablet is IPad)
                Console.WriteLine("Ipad wifi does not have 3G option.");
            else if (tablet is GalaxyTab)
                Console.WriteLine("GalaxyTab 3G has open.");
            else
                Console.WriteLine("This object is not a tablet.");
        }
    }

        static void Main(string[] args)
        {
            IPad iPad = new IPad("Ipad mini", "Apple");
            GalaxyTab galaxyTab = new GalaxyTab("Galaxy Tab", "Samsung");

            iPad.Accept(new WifiVisitor());
            galaxyTab.Accept(new WifiVisitor());

            iPad.Accept(new ThreeGVisitor());
            galaxyTab.Accept(new ThreeGVisitor());

        //bunun gibi baska visitor sınıfları yazarak sınıfımızı değiştirmeden
        //yeni metotlar çalıştırabilir hale getirebiliriz. 

            Console.ReadLine();

        }
Çıktı:






0 yorum :

Yorum Gönder