• Anasayfa
  • Hakkımızda
  • Etkinlikler
  • Destek Verin
  • Site Haritası
  • Giriş Yap
  • Üye Ol
  • Facebook
  • Twitter
  • RSS
Yazılım Dilleri
  • Soru - Cevap
  • EĞİTİM SETİ
  • KATEGORİ
  • DUYURU
  • TEKNOLOJİ HABERLERİ

Son Sorular

  • 8/2/2020 11:38:31 PM'Basit' Yazılım Dili
  • 6/25/2020 3:18:13 PMderleme hatası
  • 12/11/2017 4:49:15 PMWindows Hizmeti Hk.
  • 4/23/2016 12:55:33 AMC programlama 2 oyun

Popüler Sorular

  • 5/27/2012 5:49:50 AMAsp.Net ile Date time alana veri ekleyemiiyorum ?
  • 4/2/2012 12:45:18 AM.exe uzantılı dosya için dijital imza nerde nasıl alınır.
  • 5/12/2012 8:44:49 AMAcil Yardım
  • 5/27/2012 1:46:51 PMveri tabanı bağlantısı
  • .Net Framework
  • 8085 Assembly
  • Active Directory
  • ADO.NET
  • Android
  • Apple IOS
  • Arduino
  • ASP.NET
  • ASP.NET MVC
  • Blackberry
  • C#.Net
  • C++
  • CCG Framework
  • CISCO
  • CSS
  • Diğer
  • Dreamweaver
  • Entity Framework
  • Exchange Server
  • Gömülü Sistemler
  • GSM Programlama
  • Güncel
  • Güvenlik
  • HTML5
  • Java
  • Javascript / JQuery
  • Jira
  • Kariyer ve İş Yaşamı
  • LibreOffice
  • LINQ
  • Linux
  • Matlab
  • Microsoft Dynamics CRM
  • Mobil Uygulama Geliştirme
  • MySQL
  • NoSQL
  • Oracle
  • OWIN
  • PFSense
  • PHP
  • Powershell
  • Python
  • Sanallastirma
  • SAP-ABAP
  • SCOM 2012
  • SEO
  • Sharepoint 2010
  • Sharepoint 2013
  • Silverlight
  • Sistem Analiz ve Tasarımı
  • SQL Server
  • Symantec
  • TFS
  • T-SQL
  • Ubuntu
  • VB.NET
  • Veritabanı Yönetim Sistemleri
  • Visual Studio
  • VMware
  • WCF
  • Web Hosting
  • Windows 8
  • Windows Azure
  • Windows Phone 7.1
  • Windows Phone 8
  • Windows Server
  • Wordpress
  • WPF
  • Xamarin
  • XNA
  • Yazılım Mühendisliği
  • Yöneylem Araştırması
  • ASP.NET MVC
  • Entity Framework
  • Javascript / JQuery
  • LINQ
  • PHP

Son Duyurular

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

IPhone 6 ve IPhone 6 Plus Teknik Özellikleri ve Fiyatı

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

DELL'in Yeni Projesi: USB Bilgisayar (Project Ophelia)

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Windows Phone Youtube Uygulaması Google ve Microsoft ile Yeniden Yapılıyor

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Android ve Apple IOS Telefonlar için Blackberry Messenger (BBM)

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

Nokia Lumia 925 Teknik Özellikleri, Lumia 928 ve 920 ile Karşılaştırması

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

LG Optimus G Pro Özellikleri ve Gözle Video Oynatma Teknolojisi

Chain of Responsibility Design Pattern

Chain of Responsibility Design Pattern nedir? Nerelerde kullanılır? Örnek uygulamalar.

10.03.2013

Yazar: Veysel Uğur KIZMAZ (Google+)

Kategori: Yazılım Mühendisliği

5782

Tasarım desenleri arasında ilk inceleyeceğimiz desen, Behavioral Patterns kategorisinde yer alan Chain of Responsibility desenidir.

Chain of Responsibility, Türkçe’de Sorumluluk Zinciri olarak geçmektedir. Bir işlemi yapabilecek birden fazla sınıftan hangisinin yapacağına karar veren tasarım desenidir. Bu konuda en güzel örnek, günlük hayatımızda kullandığımız bankamatik (otomata) sistemleridir.
 
Senaryo: Bankamatiğe para çekmeye gittiğinizde tutarı 1385 TL olarak yazdığınızı ve bankamatik içerisinde 200, 100, 50, 20, 10 ve 5 TL’lik banknotlardan yeterli miktarda olduğunu varsayalım. Makine banknotları minimum sayıda verebilmek için şu yöntemi izlemelidir:
 
  • 6 adet 200 TL
  • 1 adet 100 TL
  • 1 adet 50 TL
  • 3 adet 10 TL
  • 1 adet 5 TL
Bunun kodlamasını nasıl yapacağınızı düşündüğünüzde ilk aklınıza gelen şu olmuştur: Bir while ve birkaç if ile yapılabilir. Bu yöntemle deneyelim.
 
public class Banknot
{
    public int Adet { get; set; }
    public int Tutar { get; set; }
}
 
static void Main(string[] args)
{
    int tutar = 1385;
    List<Banknot> banknotlar = newList<Banknot>();
    if (tutar / 200 > 0)
    {
        banknotlar.Add(new Banknot
        {
            Adet = tutar / 200,
            Tutar = 200
        });
        tutar = tutar % 200;
    }
    if (tutar / 100 > 0)
    {
        banknotlar.Add(new Banknot
        {
            Adet = tutar / 100,
            Tutar = 100
        });
        tutar = tutar % 100;
    }
    if (tutar / 50 > 0)
    {
        banknotlar.Add(new Banknot
        {
            Adet = tutar / 50,
            Tutar = 50
        });
        tutar = tutar % 50;
    }
    if (tutar / 20 > 0)
    {
        banknotlar.Add(new Banknot
        {
            Adet = tutar / 20,
            Tutar = 20
        });
        tutar = tutar % 20;
    }
    if (tutar / 10 > 0)
    {
        banknotlar.Add(new Banknot
        {
            Adet = tutar / 10,
            Tutar = 10
        });
        tutar = tutar % 10;
    }
    if (tutar / 5 > 0)
    {
        banknotlar.Add(new Banknot
        {
            Adet = tutar / 5,
            Tutar = 5
        });
        tutar = tutar % 5;
    }
 
    foreach (Banknot b in banknotlar)
    {
        Console.WriteLine("Tutar: " + b.Tutar + "\tAdet: " + b.Adet);
    }
 
    Console.ReadKey();
}
 
Projeyi çalıştırdığımızda istediğimiz sonucu elde edebiliyoruz.
 
Chain of Repsonsibility Örnek Uygulama Ekran Çıktısı
 
İsterseniz if blokları içerisindeki kodlamayı bir metoda alıp parametre göndererek de işlemleri yapabilirsiniz.
 
Bu kodlama doğru çalışsa da yazılım geliştirme sırasında araya farklı kontrollerin ve işlemlerin geleceği düşünüldüğünde bir süre sonra kodlar karmaşık bir hale gelebilir. Örneğin şu senaryolar eklenebilir:
 
  • 200 TL sayısı 50’nin altına inmişse 1000 TL’den büyük tutarlarda 2 tane 200 TL’den sonra 100 TL’leri ver.
  • 200 TL sayısı 20’nin ve 100 TL sayısı 30’un altına inmişse ve 50 TL sayısı 150’nin üstünde ise 500 TL ile 1500 TL arasındaki tutarlarda 1 tane 200 TL 4 tane 100 TL’den sonra 50 TL’leri ver.
  • 200 TL sayısı 5’in, 100 TL sayısı 10’un altına inmişse ve 50 TL sayısı 100’ün üstünde, 20 TL sayısı 250’den fazla ise 200 TL ile 1000 TL arasındaki tutarlarda 200 TL verme, 1 tane 100 TL’den sonra  50 TL sayısının en fazla 10’da 1’i kadar 50 TL ver, sonra kalan bölümde 20 TL’leri ver.
Bu ve bunun gibi yüzlerce senaryo yazılması istenebilir. Eğer bunlar if blokları içerisine yazılırsa tek metod içerisinde çok karmaşık kodlar ortaya çıkacaktır ve yönetimi oldukça zor olacaktır.
 
Kodlamada karmaşıklığı önlemek için Chain of Responsibility (sorumluluk zinciri) tasarım deseni oluşturulmuştur. Örnek üzerinden ilerlersek; her banknot için bir sınıf oluşturulacak, bu sınıflar içerisinde sadece banknota özgü işlemler yapılacak, çağırıldığı yerde (bankamatikte) ek bir kod yazılmadan banknotların hiyerarşisi (hangi sırayla işlem yapacağı) birbirine bağlanacak ve tutar girilerek hangi banknottan kaç adet verilmesi gerektiği sonucu alınacaktır.
 
Öncelikle projenin sınıf diagramını inceleyelim.
 
Chain of Repsonsibility Class Diagram
 
200 TL’lik banknotlar için Para200 sınıfı, 100 TL’lik banknotlar için Para100 sınıfı, 50 TL’lik banknotlar için Para50 sınıfı, 20 TL’lik banknotlar için Para20 sınıfı, 10 TL’lik banknotlar için Para10 sınıfı, 5 TL’lik banknotlar için Para5 sınıfı oluşturulmuştur. Tüm sınıflar Banknot isimli abstract sınıftan kalıtım almıştır. Öncelikle en temel sınıf olan hesap sınıfını inceleyelim.
 
abstract class Banknot
{
    protected Banknot _banknot;
    public void Sonraki(Banknot hesap)
    {
        this._banknot = hesap;
    }
    public abstract Miktar ParaCek(int tutar);
}
 
  • _banknot değişkeninde, bir sonraki banknot bilgileri tutulmaktadır. İlk aşamada 200 TL’lik banknotlar, onrasında 100 TL’lik banknotlar kontrol edilecektir. 200 TL’den sonra 100 TL’lik banknotların kontrol edilmesi tanımlamasını Sonraki isimli metod ile gerçekleştireceğiz. Bu yöntemle 200’den sonra 100, 100’den sonra 50, 50’den sonra 20, 20’den sonra 10, 10’dan sonra 5 TL’lik banknotların kontrol edileceğini tanımlayacağız. Dikkat ettiyseniz yapı bir zincir gibi ilerliyor (adına uygun şekilde).
  • ParaCek isimli metod ile de para çekme işlemini gerçekleştireceğiz. Girilen tutar, ilgili banknotta varsa bir miktar değeri döndürecek (hangi banknottan kaç adet verilecek ve bu işlemden sonra elde ne kadar para kaldı). Örneğin 1385 TL çekilecek ise öncelikle 200 TL’lik banknotlara bakacak ve 6 tane 200 TL’lik banknot verileceğini ve verildikten sonra 185 TL’nin kaldığını belirtecek bize. Sonraki adımlarda diğer banknotlardan kaç tane verileceğini tanımlamak için kalan 185 TL’yi işleme koyacağız.

 

public class Miktar
{
    publicint Adet { get; set; }
    publicint Kalan { get; set; }
    publicint Tutar { get; set; }
}
 
Şimdi ilk banknotumuz olan 200 TL’lik banknot için Para200 sınıfını oluşturalım.
 
Para200.cs
class Para200 : Banknot
{
    public override Miktar ParaCek(int tutar)
    {
        if (tutar >= 200)
        {
            return new Miktar
            {
                Adet = tutar / 200,
                Kalan = tutar % 200,
                Tutar = 200
            };
        }
        else
        {
            return _banknot.ParaCek(tutar);
        }
    }
}
 
  • Para200 sınıfımızda, Banknot sınıfının kalıtımını aldık. Bu sayede hem ParaCek metodunu standarda uygun oluşturduk hem de Sonraki metodunu tekrar oluşturmak zorunda kalmadan Banknot sınıfının kalıtımı sayesinde kullanabileceğiz.
  • ParaCek metodunda eğer tutar (1385 TL) 200 TL’den büyük ise tutar / 200 adet (Adet = 6) 200 TL’lik (Tutar = 200) banknotlardan vereceğimizi ve kalan tutarın tutar % 200 (Kalan = 185 TL) kadar olduğunu geri döndürüyoruz. Eğer tutar 200 TL’nin altında ise bir sonraki banknota (100 TL’ye) bakmasını belirtiyoruz.
 
Benzer şekilde Para100, Para50, Para20, Para10, Para5 sınıflarını da oluşturalım.
 
Para100.cs
class Para100 : Banknot
{
    public override Miktar ParaCek(int tutar)
    {
        if (tutar >= 100)
        {
            return new Miktar
            {
                Adet = tutar / 100,
                Kalan = tutar % 100,
                Tutar = 100
            };
        }
        else
        {
            return _banknot.ParaCek(tutar);
        }
    }
}
 
Para50.cs
class Para50 : Banknot
{
    public override Miktar ParaCek(int tutar)
    {
        if (tutar >= 50)
        {
            return new Miktar
            {
                Adet = tutar / 50,
                Kalan = tutar % 50,
                Tutar = 50
            };
        }
        else
        {
            return _banknot.ParaCek(tutar);
        }
    }
}
 
Para20.cs
class Para20 : Banknot
{
    public override Miktar ParaCek(int tutar)
    {
        if (tutar >= 20)
        {
            return new Miktar
            {
                Adet = tutar / 20,
                Kalan = tutar % 20,
                Tutar = 20
            };
        }
        else
        {
            return _banknot.ParaCek(tutar);
        }
    }
}
 
Para10.cs
classPara10 : Banknot
{
    public override Miktar ParaCek(int tutar)
    {
        if (tutar >= 10)
        {
            return new Miktar
            {
                Adet = tutar / 10,
                Kalan = tutar % 10,
                Tutar = 10
            };
        }
        else
        {
            return _banknot.ParaCek(tutar);
        }
    }
}
 
Para5.cs
classPara5 : Banknot
{
    public override Miktar ParaCek(int tutar)
    {
        if (tutar >= 5)
        {
            returnnewMiktar
            {
                Adet = tutar / 5,
                Kalan = tutar % 5,
                Tutar = 5
            };
        }
        else
        {
            return _banknot.ParaCek(tutar);
        }
    }
}
 
Şimdi para çekme işlemini yapacağımız Bankamatik isimli sınıfı oluşturalım. Bu sınıfta hangi banknottan sonra hangi banknotun işleme gireceğini (zincir tanımlaması) ve para çekme işlemini yapacağız.
 
publicclassBankamatik
{
    Para200 _200 = new Para200();
    Para100 _100 = new Para100();
    Para50 _50 = new Para50();
    Para20 _20 = new Para20();
    Para10 _10 = new Para10();
    Para5 _5 = new Para5();
    Para1 _1 = new Para1();
 
    public List<Miktar> ParaCek(int tutar)
    {
        Console.WriteLine("Toplam Tutar: " + tutar);
 
        _200.Sonraki(_100);
        _100.Sonraki(_50);
        _50.Sonraki(_20);
        _20.Sonraki(_10);
        _10.Sonraki(_5);
 
        Miktar sonuc = newMiktar();
        List<Miktar> sonuclar = newList<Miktar>();
 
        do
        {
            sonuclar.Add(sonuc = _200.ParaCek(tutar));
            tutar = sonuc.Kalan;
        } while (sonuc.Kalan > 0);
 
        foreach (var s in sonuclar)
        {
            Console.WriteLine("Tutar: " + s.Tutar + "\tAdet: " + s.Adet);
        }
 
        returnnull;
    }
}
 
  • Bankamatik sınıfında global alanda Para200, Para100, Para50, Para20, Para10, Para5 değişkenlerini oluşturuyoruz (_200, _100, _50, _20, _10, _5).
  • ParaCek isimli metod içerisinde para çekme işlemini gerçekleştireceğiz. Birden fazla banknot türü verileceği için geri dönüş türünü list (List) olarak tanımladık.
  • _200.Sonraki(_100) ve diğer Sonraki metodlarının çağırıldığı kodlarda, zincir halkaları birbirine bağlanmaktadır. Yani,
    •  _200.Sonraki(_100) ile 200 TL’lik banknotlardan sonra 100 TL’lik banknotlara bakılacağı,
    • _100.Sonraki(_50) ile 100 TL’lik banknotlardan sonra 50 TL’lik banknotlara bakılacağı,
    • _50.Sonraki(_20) ile 50 TL’lik banknotlardan sonra 20 TL’lik banknotlara bakılacağı,
    • _20.Sonraki(_10) ile 20 TL’lik banknotlardan sonra 10 TL’lik banknotlara bakılacağı,
    • _10.Sonraki(_50) ile 10 TL’lik banknotlardan sonra 5 TL’lik banknotlara bakılacağı tanımlaması yapılmaktadır.
  • sonuc isimli değişkende, her bakılan banknot türünden sonra geri dönen değerler (kalan, adet ve tutar değerleri) yeniden işleme girmek için tutulmaktadır.
  • sonuclar isimli değişkende, belirtilen tutarın hangi banknotlarla verileceği bilgileri tutulmaktadır (işlemler tamamlandığında ekranda göstereceğimiz bilgiler).
  • do – while döngüsü ile tutar (ya da işleme girmiş ise kalan tutar) 0 TL’den büyük olduğu sürece yeniden işleme girmesi sağlanmaktadır. Kalan tutar 0 TL olduğu zaman döngüden çıkacak ve hangi banknottan kaç adet verilmesi gerektiği sonuclar isimli değişkende yer alacaktır.
  • sonuclar.Add metodu ile kalan tutarın işleme alınması sonucunda ilgili banknottan kaç adet verileceği bilgisi sonuclar değişkenine eklenmektedir.1
  • tutar = sonuc.Kalan işlemi ile, kalan miktarı tutar değişkenine atıyoruz ve bir sonraki döngüde bu tutarı işleme alıyoruz. Örneğin 1385 TL işleme alındığında 6 tane 200 TL banknot verileceği hesaplanacaktır. Kalan 185 TL tutar değişkenine atanarak tekrar işleme alınacak ve 1 tane 100 TL banknot verileceği hesaplanacaktır. Bu işlem sonucunda kalan 85 TL tutar değişkenine atanacak ve tekrar işleme alınacaktır. Bu şekilde tutar değişkeninin değeri (kalan değer) 0 TL olana kadar işlemler devam edecektir.
  • Son aşamada ise foreach döngüsü ile banknot değerlerini ekranda görüntülüyoruz.
İşlemlerin daha iyi anlaşılması için aşağıda algoritmanın flowchart diagramı yer almaktadır.
 
Chain of Repsonsibility FlowChart - Akış Diagramı
 
Main metodundan Bankamatik sınıfındaki ParaCek metodunu çağıralım ve parametre olarak makalenin başından beri kullandığımız 1385 TL’yi gönderelim.
 
staticvoid Main(string[] args)
{
    Bankamatik b = newBankamatik();
    b.ParaCek(1385);
 
    Console.ReadKey();
}
 
Projeyi çalıştırdığımızda ilk yaptığımız işlem sonucunun aynısını alacağız.
 
Chain of Repsonsibility Örnek Uygulama Ekran Çıktısı
 
Yepyeni makalelerde görüşmek dileğiyle :)
 
Veysel Uğur KIZMAZ
Bilgisayar Mühendisi
veysel@ugurkizmaz.com
www.ugurkizmaz.com

 

Yazar Hakkında

Veysel Uğur  KIZMAZ

Veysel Uğur KIZMAZ

www.ugurkizmaz.com

YazılımDilleri.Net projesinin lideri olan Veysel Uğur Kızmaz, Gazi Üniversitesi Bilgisayar Mühendisliği bölümü mezunudur. Bir çok projede çalışmış, yazılım alanında birçok eğitimler vermiştir. Şu an özel bir yazılım danışmanlık firmasında Sharepoint proje danışmanlığı ve proje yöneticiliği yapmaktadır. Veysel Uğur Kızmaz, dahil olduğu projelerin çeşitliliği sebebiyle farklı alanlarda uzmanlaşmıştır: .Net, Sharepoint, Java, Php, Javascript, SQL Server, Oracle, MySQL.

Sosyal Medya

ORANLAR

  • 5782izleme

Arkadaşlarınla Paylaş

  • Tweet

1 Yorum

büşra güneş

büşra güneş

30.03.2015

yukarı da çözdüğünüz örneği python programında da çözebilirmisiniz?

Yorum Yaz / Soru Sor

Lütfen yorum yazmak veya soru sormak için üye girişi yapınız.

Son Yorumlar

  • Böyle bir sayfalama ağ trafiğini hafifleti...
  • Böyle bir sayfalama ağ trafiğini hafifleti...
  • Merhaba, ellerinize sağlık çok yardımcı ol...
  • Merhaba Bu uygulama örneğinden ASP.net ...
  • Hocam Link başka sayfaya yönlendiriyor.

En Güncel Sorular

  • Bilgilendirme maili (C#.Net)
  • Power Pivot (Sharepoint 2010)
  • BigInteger, BigDecimal (Asp.Net ve Asp.Net MVC)
  • visual C# ile asp nette veritabanı islemleri (Asp.Net ve Asp.Net MVC)
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ? (Sharepoint 2010)

En Son Cevap Verilen Sorular

  • Bilgilendirme maili
  • BigInteger, BigDecimal
  • visual C# ile asp nette veritabanı islemleri
  • Share Point ile Dosya Arşiv Yönetim Sistemi yapılabilir mi ?
  • txt dosyasına veri yazma

Twitter

Takip et: @yazilim_dilleri

En Çok Okunanlar

Elif BAYRAKDAR

C# ile SQL Server Bağlantısı, Insert, Update ve Delete Sorguları

23.05.2013

  • 124113
  • 0
Hakan Keskin

C# ile Windows Service Projesi Oluşturma, Debug Etme ve Setup Hazırlama

17.12.2013

  • 71306
  • 0
batuhan avlayan

Php - Mail Gönderme (İletişim Formu)

02.09.2013

  • 51908
  • 0

Sponsorlar

KODLAB
Pluralsight
Exchange server is
Office 365
YAZILIM DİLLERİ
Yukarı Çık
  • Hakkımızda
  • Facebook
  • Twitter
  • RSS

© Yazılım Dillerinin Buluşma Noktası | Kaynak belirtildiği sürece makaleler kopyalanabilir.
YazilimDilleri.Net sitesinde yer alan kullanıcıların oluşturduğu tüm içeriklerin yayınlanması ile ilgili yasal yükümlülükler içeriği oluşturan kullanıcıya aittir, YazilimDilleri.Net hiçbir şekilde sorumlu değildir.

Kapat

Giriş Yap

Kullanıcı Adı

Şifre

Şifremi Unuttum

KULLANICI GİRİŞİ