MERHABA! Bugün tasarım modellerini incelemeye devam edeceğiz ve fabrika yöntem modelini tartışacağız.
Ne olduğunu ve bu kalıbın hangi görevler için uygun olduğunu öğreneceksiniz. Bu tasarım modelini pratikte ele alacağız ve yapısını inceleyeceğiz. Her şeyin net olduğundan emin olmak için aşağıdaki konuları anlamanız gerekir:
Hangi sonuçlara varabiliriz?
Yukarıdaki diyagram, fabrika yöntemi modelinin genel yapısını göstermektedir. Burada başka ne önemlidir?

- Java'da kalıtım.
- Java'da soyut yöntemler ve sınıflar
Fabrika yöntemi hangi sorunu çözer?
Tüm fabrika tasarım kalıplarının iki tür katılımcısı vardır: yaratıcılar (fabrikaların kendileri) ve ürünler (fabrikalar tarafından yaratılan nesneler). Şu durumu hayal edin: CodeGym markalı arabalar üreten bir fabrikamız var. Çeşitli gövde türlerine sahip araba modellerinin nasıl oluşturulacağını bilir:- sedanlar
- istasyon vagonları
- darbeler
- CodeGym sedanları
- CodeGym istasyon vagonları
- CodeGym kupaları
- OneAuto sedanlar
- OneAuto istasyon vagonları
- OneAuto kupaları
Fabrika modeli hakkında biraz
Daha önce küçük bir sanal kahve dükkanı yaptığımızı hatırlatayım. Basit bir fabrikanın yardımıyla farklı kahve türlerinin nasıl yapıldığını öğrendik. Bugün bu örneği yeniden işleyeceğiz. Basit fabrikasıyla kahvehanemizin nasıl göründüğünü hatırlayalım. Bir kahve dersimiz vardı:
public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Ve fabrikamızın üretebileceği belirli kahve türlerine karşılık gelen birkaç alt sınıf:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Sipariş vermeyi kolaylaştırmak için bir sıralama oluşturduk:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Kahve fabrikasının kendisi şöyle görünüyordu:
public class SimpleCoffeeFactory {
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappuccino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
Ve son olarak, kahve dükkanının kendisi şuna benziyordu:
public class CoffeeShop {
private final SimpleCoffeeFactory coffeeFactory;
public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
Basit bir fabrikayı modernize etmek
Kahvehanemiz çok iyi gidiyor. O kadar ki genişletmeyi düşünüyoruz. Yeni yerler açmak istiyoruz. Cesur ve girişimciyiz, bu yüzden sıkıcı kahve dükkanlarını mahvetmeyeceğiz. Her mağazanın özel bir dokunuşu olmasını istiyoruz. Buna göre, başlangıç olarak iki lokasyon açacağız: bir İtalyan ve bir Amerikan. Bu değişiklikler sadece iç tasarımı değil, sunulan içecekleri de etkileyecek:- İtalyan kahve dükkanında, özel öğütme ve kavurma ile sadece İtalyan kahve markalarını kullanacağız.
- Amerika lokasyonu daha büyük porsiyonlara sahip olacak ve her siparişte marshmallow sunacağız.
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Ama şimdi 8'e sahip olacağız:
public class ItalianStyleAmericano extends Coffee {}
public class ItalianStyleCappucino extends Coffee {}
public class ItalianStyleCaffeLatte extends Coffee {}
public class ItalianStyleEspresso extends Coffee {}
public class AmericanStyleAmericano extends Coffee {}
public class AmericanStyleCappucino extends Coffee {}
public class AmericanStyleCaffeLatte extends Coffee {}
public class AmericanStyleEspresso extends Coffee {}
Mevcut iş modelini korumak istediğimiz için, orderCoffee(CoffeeType type)
yöntemin mümkün olduğunca az değişikliğe uğramasını istiyoruz. Ona bir göz atın:
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
Hangi seçeneklerimiz var? Fabrika yazmayı zaten biliyoruz, değil mi? Hemen akla gelen en basit şey, iki benzer fabrika yazmak ve ardından istenen uygulamayı kahvehanemizin kurucusuna iletmek. Bunu yaparak kahvehanenin sınıfı değişmeyecektir. İlk olarak, yeni bir fabrika sınıfı yaratmalı, basit fabrikamızı devralmalı ve ardından yöntemi geçersiz kılmalıyız createCoffee(CoffeeType type)
. İtalyan tarzı kahve ve Amerikan tarzı kahve yapmak için fabrikaları yazalım:
public class SimpleItalianCoffeeFactory extends SimpleCoffeeFactory {
@Override
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
public class SimpleAmericanCoffeeFactory extends SimpleCoffeeFactory{
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
Artık istediğimiz fabrika uygulamasını CoffeeShop'a geçirebiliriz. Farklı kahve dükkanlarından kahve sipariş etme kodunun nasıl görüneceğine bakalım. Örneğin, İtalyan tarzı ve Amerikan tarzı kapuçino:
public class Main {
public static void main(String[] args) {
/*
Order an Italian-style cappuccino:
1. Create a factory for making Italian coffee
2. Create a new coffee shop, passing the Italian coffee factory to it through the constructor
3. Order our coffee
*/
SimpleItalianCoffeeFactory italianCoffeeFactory = new SimpleItalianCoffeeFactory();
CoffeeShop italianCoffeeShop = new CoffeeShop(italianCoffeeFactory);
italianCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
/*
Order an American-style cappuccino
1. Create a factory for making American coffee
2. Create a new coffee shop, passing the American coffee factory to it through the constructor
3. Order our coffee
*/
SimpleAmericanCoffeeFactory americanCoffeeFactory = new SimpleAmericanCoffeeFactory();
CoffeeShop americanCoffeeShop = new CoffeeShop(americanCoffeeFactory);
americanCoffeeShop.orderCoffee(CoffeeType.CAPPUCCINO);
}
}
Her birine istediğimiz fabrikayı geçirerek iki farklı kahvehane oluşturduk. Bir yandan amacımıza ulaştık ama diğer yandan... Bu durum girişimcilerin pek hoşuna gitmiyor nedense... Hadi bakalım sorun neymiş. Birincisi, fabrikaların bolluğu. Ne? Şimdi her yeni lokasyon için kendi fabrikasını kurmamız ve buna ek olarak bir kahvehane kurarken ilgili fabrikanın müteahhide geçtiğinden emin olmamız mı gerekiyor? İkincisi, hala basit bir fabrika. Sadece biraz modernize edildi. Ama yeni bir model öğrenmek için buradayız. Üçüncüsü, farklı bir yaklaşım mümkün değil mi? Kahve hazırlama ile ilgili tüm konuları gündeme getirebilsek harika olurdu.CoffeeShop
Aynı anda çeşitli kahve stilleri yapmak için yeterli esnekliği korurken, kahve oluşturma ve sipariş verme süreçlerini birbirine bağlayarak sınıf. Cevap evet, yapabiliriz. Buna fabrika yöntemi tasarım modeli denir.
Basit bir fabrikadan fabrika yöntemine
Görevi olabildiğince verimli bir şekilde çözmek için:createCoffee(CoffeeType type)
Yöntemi sınıfa geri döndürüyoruzCoffeeShop
.- Bu yöntemi soyut hale getireceğiz.
- Sınıfın
CoffeeShop
kendisi soyut hale gelecektir. - Sınıfın
CoffeeShop
çocuk sınıfları olacaktır.
CoffeeShop
uygulayan sınıfın soyundan başka bir şey değildir . createCoffee(CoffeeType type)
Şimdi, her seferinde bir adım. Adım 1. Coffee
Sınıfı özetleyin. Farklı ürünlerden oluşan iki ailemiz var. Yine de, İtalyan ve Amerikan kahvelerinin ortak bir ataları vardır: sınıf Coffee
. Soyutlamak uygun olacaktır:
public abstract class Coffee {
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
Adım 2. CoffeeShop
Soyut bir yöntemle soyut createCoffee(CoffeeType type)
yapın
public abstract class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = createCoffee(type);
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
protected abstract Coffee createCoffee(CoffeeType type);
}
Adım 3. Soyut kahve dükkanının soyundan gelen bir İtalyan kahve dükkanı oluşturun. createCoffee(CoffeeType type)
İtalyan tariflerinin özelliklerini dikkate alarak içindeki yöntemi uyguluyoruz .
public class ItalianCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee (CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new ItalianStyleAmericano();
break;
case ESPRESSO:
coffee = new ItalianStyleEspresso();
break;
case CAPPUCCINO:
coffee = new ItalianStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new ItalianStyleCaffeLatte();
break;
}
return coffee;
}
}
Adım 4. Amerikan tarzı kahve dükkanı için de aynısını yapıyoruz.
public class AmericanCoffeeShop extends CoffeeShop {
@Override
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new AmericanStyleAmericano();
break;
case ESPRESSO:
coffee = new AmericanStyleEspresso();
break;
case CAPPUCCINO:
coffee = new AmericanStyleCappuccino();
break;
case CAFFE_LATTE:
coffee = new AmericanStyleCaffeLatte();
break;
}
return coffee;
}
}
Adım 5. Amerikan ve İtalyan lattelerinin nasıl görüneceğine bakın:
public class Main {
public static void main(String[] args) {
CoffeeShop italianCoffeeShop = new ItalianCoffeeShop();
italianCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
CoffeeShop americanCoffeeShop = new AmericanCoffeeShop();
americanCoffeeShop.orderCoffee(CoffeeType.CAFFE_LATTE);
}
}
Tebrikler. Örnek olarak kahve dükkanımızı kullanarak fabrika yöntemi tasarım modelini az önce uyguladık.
Fabrika yöntemlerinin arkasındaki ilke
Şimdi neye sahip olduğumuzu daha ayrıntılı olarak ele alalım. Aşağıdaki diyagram sonuçta ortaya çıkan sınıfları göstermektedir. Yeşil bloklar yaratıcı sınıfları, mavi bloklar ise ürün sınıflarıdır.
- Tüm ürünler soyut sınıfın uygulamalarıdır
Coffee
. - Tüm yaratıcılar, soyut sınıfın uygulamalarıdır
CoffeeShop
. - İki paralel sınıf hiyerarşisi görüyoruz:
- Ürünlerin hiyerarşisi. İtalyan torunlarını ve Amerikan torunlarını görüyoruz
- Yaratıcıların hiyerarşisi. İtalyan torunlarını ve Amerikan torunlarını görüyoruz
- Üst sınıf, hangi belirli ürünün ( ) oluşturulacağı
CoffeeShop
hakkında hiçbir bilgiye sahip değildir .Coffee
- Üst
CoffeeShop
sınıf, belirli bir ürünün yaratılmasını soyundan gelenlere devreder. - Sınıfın her soyundan gelen, kendi özelliklerine uygun olarak
CoffeeShop
bir fabrika yöntemi uygular .createCoffee()
Diğer bir deyişle, üretici sınıflarının uygulamaları, üretici sınıfının özelliklerine göre belirli ürünler hazırlar.
Bir fabrika yönteminin yapısı

- Creator sınıfı, fabrika yöntemi dışında ürünlerle etkileşime giren tüm yöntemleri uygular.
- Soyut
factoryMethod()
yöntem, sınıfın tüm torunları tarafından uygulanmalıdırCreator
. - Sınıf , ürünü doğrudan oluşturan yöntemi
ConcreteCreator
uygular .factoryMethod()
- Bu sınıf, belirli ürünler oluşturmaktan sorumludur. Bu ürünlerin oluşturulması hakkında bilgi içeren tek sınıf budur.
- Tüm ürünler ortak bir arayüz uygulamalıdır, yani ortak bir ürün sınıfının torunları olmalıdır. Bu, ürünleri kullanan sınıfların bunlar üzerinde belirli uygulamalar yerine soyutlamalar olarak çalışabilmeleri için gereklidir.
GO TO FULL VERSION