Problem : 

Ödeme aldığımız bir uygulamamız olduğunu varsayalım. Bu uygulama üzerinde şimdilik X, Y ve Z bankalarından ödeme alıyoruz. İleride bu banka sayısı artabilir ya da azalabilir. Esnek bir yapı kurmamız gerekli.

Kullanıcının girdiği bilgilere göre hangi bankanın işlem görmesi gerektiğinin kararının verilmesi bir çok koşul oluşturuyor. Yeni bir banka ödeme sistemi geldiğinde diğerlerinin etkilenmesi büyük bir problem yaratıyor.

Çözüm :

Ödeme işlemi sırasında kullanıcının bilgilerine göre hangi bankanın ödeme alacağına karar verecek tek nokta belirlemek oldukça faydalı olacaktır.

Ödeme ekranı sadece tek nokta ile haberleşecek, yeni bir banka ödemesi eklendiğinde tek bir noktadan eklenip, tek bir noktadan çıkartılabilecektir.

Product yerine Payment olduğunu düşünün

Öncelikle tüm bankaların ortak kullanacağı bir kod arayüzü belirlemeliyiz.

public interface IPayment
{
   IPayOutputModel Pay(IPayInputModel payInputModel);
}

Tüm bankaların “IPayment” arayüzünü implementation yapması gerekecektir. Belirtilen Input ve Output karşılanması gerekir.

X, Y ve Z bankalarımız vardı. Biz bunlardan bir tanesini oluşturarak başlayalım.

public class XBankPayment : IPayment
{
public IPayOutputModel Pay(IPayInputModel payInputModel)
{
XBankPayInputModel inputModel = (XBankPayInputModel)payInputModel;
//pay..
return new YBankPayOutputModel
{
BankName = typeof(XBankPayment).Name,
TransactionId = nameof(XBankPayment) + inputModel.OrderNumber
};
}
}

//pay.. olarak belirttiğimiz bölümde bankaya gidip parayı çektiğimizi düşünelim. Geriye döndüğümüz bankName değerinide test işlemlerimizde kullanacağız. Burada her banka kendine özgü bir şekilde TransactionId değeri oluşturabiliyor.


Bu somut nesnelerden Y ve Z içinde yaptığımızı varsayalım. Bundan sonra artık bu banka ödemelerinin tek noktada birleştirmesini sağlayacağız. Yani FactoryMethod yapacağız.

FactoryMethod’un bankaları anlayabilmesi için bir değer belirlememiz gerekiyor. Bu değeri parametrik olarak bir ortam dosyasından, veri tabanından gibi yerlerden alabiliriz.

Aldığımız veriye göre reflection yapabiliriz. Reflection çalışma zamanında performans kaybı yarattığı için swich case tercih edeceğiz.

public static class PaymentFactoryMethod
{
public static IPayment InitializePayment(string cardNumber)
{
//Cards starting with number 1 XBank
//Cards starting with number 2 YBank
//Cards starting with number 3 ZBank
IPayment payment = cardNumber switch
{
string s when s.StartsWith("1") => new XBankPayment(),
string s when s.StartsWith("2") => new YBankPayment(),
string s when s.StartsWith("3") => new ZBankPayment(),
_ => new XBankPayment(),
};
return payment;
}
}

“PaymentFactoryMethod” static olarak “InitializePayment” methodu içeriyor. Bu method girilen kart numarasına göre hangi bankanın ödeme alacağına karar veriyor.

Böylece yeni bir ödeme sistemi geldiğinde oluşturduğumux “NewBankPayment” nesnesini yeni bir case olarak ekleyebilirim. Ya da kaldırılan banka varsa var olan case işlemini silerek tek bir noktadan banka ödemelerini yönetebilirim.

Repo url : https://github.com/gsmtcnr/DesignPattern.Creational.FactoryMethod

Leave a Reply

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir