"Enter"a basıp içeriğe geçin

Kategori: Design Patterns

Merge Sorting

Merge Sorting (Birleştirme Sıralaması), “böl ve fethet” (divide and conquer) prensibine dayanan bir sıralama algoritmasıdır. Bu algoritma, bir diziyi ikiye böler, her bir yarıyı ayrı ayrı sıralar ve ardından sıralı yarıları birleştirir. Merge Sort, kararlı bir algoritmadır ve en kötü durumda bile O(n log n) zaman karmaşıklığına sahiptir, bu da onu oldukça verimli bir sıralama algoritması yapar. Java dili ile yazılmış bubble sorting algoritma örneğini aşağıda görebilirsiniz.

public static void mergeSorting(int[] arr) {
        if (arr.length < 2) {
            return;
        }
        int mid = arr.length / 2;
        int[] left = new int[mid];
        int[] right = new int[arr.length - mid];

        // Sol ve sağ diziyi oluştur
        System.arraycopy(arr, 0, left, 0, mid);
        System.arraycopy(arr, mid, right, 0, arr.length - mid);

        // Sol ve sağ yarıyı sıralama
        mergeSorting(left);
        mergeSorting(right);

        // Birleştirme
        merge(arr, left, right);
    }

    private static void merge(int[] arr, int[] left, int[] right) {
        int i = 0, j = 0, k = 0;
        while (i < left.length && j < right.length) {
            arr[k++] = (left[i] <= right[j]) ? left[i++] : right[j++];
        }
        while (i < left.length) {
            arr[k++] = left[i++];
        }
        while (j < right.length) {
            arr[k++] = right[j++];
        }
    }
public static void main(String [] args) {
        int[] array = { 24, 16, 35, 34, 10 };
        mergeSorting(array);
}

Resim Referansı: https://en.m.wikipedia.org/wiki/File:Merge-sort-example-300px.gif

Yorum Bırak

Counting Sorting

Counting Sorting, belirli bir aralıktaki tam sayıların sıralanması için kullanılan, karşılaştırma tabanlı olmayan bir sıralama algoritmasıdır. Algoritma, her sayının kaç kez geçtiğini sayarak çalışır ve bu sayımlara dayanarak sıralama işlemi gerçekleştirilir. Counting Sort, lineer zaman karmaşıklığına sahip olabilir, ancak yalnızca belirli bir aralıktaki sayılar üzerinde etkili çalışır. En iyi durum, en kötü durum ve ortalama durum: O(n + k), burada n dizi eleman sayısı, k ise elemanların alabileceği değerlerin aralığıdır (en büyük değere kadar). Java dili ile yazılmış bubble sorting algoritma örneğini aşağıda görebilirsiniz.

public static void countingSorting(int[] arr) {
        int n = arr.length;
        int max = Arrays.stream(arr).max().getAsInt();
        int[] count = new int[max + 1];
        Arrays.fill(count, 0);
        for (int i = 0; i < n; i++) {
            count[arr[i]]++;
        }
        for (int i = 1; i <= max; i++) {
            count[i] += count[i - 1];
        }
        int[] output = new int[n];
        for (int i = n - 1; i >= 0; i--) {
            output[count[arr[i]] - 1] = arr[i];
            count[arr[i]]--;
        }
        for (int i = 0; i < n; i++) {
            arr[i] = output[i];
        }
    }
public static void main(String [] args) {
        int[] array = { 24, 16, 35, 34, 10 };
        countingSorting(array);
}

Resim Referansı: https://gabrielghe.github.io/university/2016/03/09/counting-sort

Yorum Bırak

Bubble Sorting

Bubble Sorting, bitişik elemanları karşılaştırarak çalışır ve gerektiğinde yer değiştirir. En büyük eleman her adımda listenin sonuna “kabarcık” gibi çıkar. Basit ama genellikle verimsizdir ve O(n^2) sürede çalışmaktadır. Java dili ile yazılmış bubble sorting algoritma örneğini aşağıda görebilirsiniz.

public static void bubbleSorting(int[] arr) {
        int n = arr.length;
        boolean swapped;
        for (int i = 0; i < n-1; i++) {
            swapped = false;
            for (int j = 0; j < n-i-1; j++) {
                if (arr[j] > arr[j+1]) {
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                    swapped = true;
                }
            }
            if (!swapped)
                break;
        }
    }
public static void main(String [] args) {
        int[] array = { 24, 16, 35, 34, 10 };
        bubbleSorting(array);
}

Resim Referansı: http://www.xybernetics.com/techtalk/SortingAlgorithmsExplained/SortingAlgorithmsExplained.html

Yorum Bırak

Adapter Design Pattern

Adapter Design Pattern: Bir sınıfın arayüzünü, beklenen bir arayüze çevirir. Farklı arayüzlere sahip sınıfların birlikte çalışmasını sağlar. Örnek verecek olursak;

public interface Database {

    void select(String data);

    void insert(String data);

    void update(String data);

    void delete(String data);
}
public class SqlDatabase implements Database{
    @Override
    public void select(String data) {
        System.out.println("Selecting data from SQL database with query : "+ data);
    }

    @Override
    public void insert(String data) {
        System.out.println("Inserting data into SQL database : "+ data);
    }

    @Override
    public void update(String data) {
        System.out.println("Updating data in SQL database : "+ data);
    }

    @Override
    public void delete(String data) {
        System.out.println("Deleting data from SQL database : "+ data);
    }
}
public class MongoDatabase {
    public void findDocument(String jsonQuery) {
        System.out.println("Finding document in MongoDB with query: " + jsonQuery);
    }

    public void insertDocument(String json) {
        System.out.println("Inserting document into MongoDB: " + json);
    }

    public void updateDocument(String json) {
        System.out.println("Updating document in MongoDB:" + json);
    }

    public void deleteDocument(String json) {
        System.out.println("Deleting document from MongoDB:" + json);
    }
}
public class MongoToSqlAdapter implements Database {

    private MongoDatabase mongoDatabase;

    public MongoToSqlAdapter(MongoDatabase mongoDatabase) {
        this.mongoDatabase = mongoDatabase;
    }

    @Override
    public void select(String data) {
        mongoDatabase.findDocument(data);
    }

    @Override
    public void insert(String data) {
        mongoDatabase.insertDocument(data);
    }

    @Override
    public void update(String data) {
        mongoDatabase.updateDocument(data);
    }

    @Override
    public void delete(String data) {
        mongoDatabase.deleteDocument(data);
    }
}
  public static void main(String[] args) {
        // SQL database operation
        Database sqlDatabase = new SqlDatabase();
        sqlDatabase.insert("SqlDatabase Data");
        sqlDatabase.update("SqlDatabase Data");
        sqlDatabase.delete("SqlDatabase Data");
        sqlDatabase.select("SELECT * FROM SqlDatabase Table");

        // MongoDB database operation
        MongoDatabase mongoDatabase = new MongoDatabase();
        Database mongoToSqlAdapter = new MongoToSqlAdapter(mongoDatabase);
        mongoToSqlAdapter.insert("Mongo Data");
        mongoToSqlAdapter.update("Mongo Data");
        mongoToSqlAdapter.delete("Mongo Data");
        mongoToSqlAdapter.select("SELECT * FROM mongoTable");
   }

Örnekte, MongoToSqlAdapter sınıfı, MongoDatabase sınıfını Database arayüzüne uyarlayarak MongoDB’nin SQL veritabanı gibi kullanılmasını sağlıyor. Bu sayede, her iki database türüyle uyumlu hale gelmiş oluyor.

Yorum Bırak

Structural Design Patterns

Structural Design Patterns (Yapısal tasarım desenleri), yazılım sistemlerinin yapısını organize etmek ve nesneler arasındaki ilişkileri ve etkileşimleri yönetmek için kullanılan kalıplardır. Bu patternler, sistemin daha esnek, genişletilebilir ve bakımının kolay olmasını sağlar. Kullanılan structural design patternler:

  1. Adapter Pattern: Bir sınıfın arayüzünü, beklenen bir arayüze çevirir. Farklı arayüzlere sahip sınıfların birlikte çalışmasını sağlar.
  2. Bridge Pattern: Uygulama ve implementasyonu birbirinden ayırarak, her ikisinin de bağımsız olarak değiştirilebilmesini sağlar.
  3. Composite Pattern: Nesneleri ağaç yapısında gruplandırarak, tekil nesneler ve nesne gruplarını aynı şekilde işlememizi sağlar.
  4. Decorator Pattern: Bir nesneye dinamik olarak yeni işlevler eklemeye olanak tanır. Ayrıca, alt sınıflar (class) oluşturma ihtiyacını ortadan kaldırır.
  5. Facade Pattern: Karmaşık bir sistemin daha basit bir arayüzünü sunar. Böylece, sistemin kullanımını ve anlaşılmasını kolaylaştırır.
  6. Flyweight Pattern: Çok sayıda küçük nesneye sahip olduğunuzda bellek kullanımını optimize etmek için kullanılır. Ortak alt nesneleri paylaşarak bellekten tasarruf sağlar.
  7. Proxy Pattern: Başka bir nesneye erişimi kontrol etmek için kullanılan bir vekil nesne sağlar. Bu, nesneye erişimi kontrol etmemize, geciktirmemize veya değiştirmemize olanak tanır.

Bu structural design patternler ile yazılım geliştiricilerine daha sürdürülebilir, esnek ve ölçeklenebilir yazılım sistemleri tasarlama konusunda yardımcı olur. Her biri, belirli bir türden problemi çözmek için  belirli bir şablon sağlar.

Yorum Bırak

Behavioral Design Patterns

Behavioral Patterns (Davranışsal Desenler), nesneler arasındaki etkileşim ve sorumlulukları yönetme ile ilgili problemleri ele alır. Bu desenler, bir yazılım sisteminde nesnelerin nasıl bir araya gelip nasıl birlikte çalışacağını belirlemeye yardımcı olur. Kullanılan behavioral design patternler:

  1. Observer Pattern (Gözlemci Deseni): Bir nesne durumunda bir değişiklik olduğunda, bağımlı nesnelerin otomatik olarak güncellenmesini sağlar. Birincil nesne, değişiklikleri gözlemleyen ve bağımlı nesnelere haber veren bir “gözleyici” olarak işlev görür.
  2. Strategy Pattern (Strateji Deseni):  Algoritmaları birbirinden bağımsız olarak tanımlar ve değiştirilebilir hale getirir. Strateji deseni, farklı algoritmaların kullanılması gereken durumlarda kullanışlıdır ve nesne, çalışma zamanında farklı bir algoritmayı seçebilir.
  3. Command Pattern (Komut Deseni): Bir eylemi bir nesne olarak temsil eder ve bu eylemi erteleyebilir, sıraya koyabilir veya geri alabiliriz. Komut deseni, istemcilerin komutları nesne olarak işleyebilmelerini sağlar ve komutların geri alınmasını, sıralanmasını veya kaydedilmesini kolaylaştırır.
  4. Chain of Responsibility Pattern (Sorumluluk Zinciri Deseni): Bir isteği işleyebilecek bir dizi nesne oluşturur ve her bir nesne, isteği işleyip işlememesine karar verir. İsteği işleyebilecek bir nesne bulunana kadar zincir boyunca ilerlenir. Bu pattern, isteği işleyecek nesnenin dinamik olarak belirlenmesi gerektiği durumlarda kullanılır.
  5. Interpreter Pattern (Yorumlayıcı Deseni): Bir dilin sözdizimini yorumlamak için kullanılır. Yorumlayıcı deseni, belirli bir dilin sentaksını analiz eden ve bu dilin ifadelerini yürüten bir yorumlayıcı sınıfını tanımlar.
  6. Iterator Pattern (Yineleyici Desen): Bir koleksiyonun elemanlarına sırayla erişmek için kullanılır. Yineleyici deseni, koleksiyonun iç yapısını gizler ve koleksiyonun üzerinde dolaşmayı kolaylaştırır.
  7. Mediator Pattern (Aracı Deseni): Nesneler arasındaki iletişimi merkezi bir noktaya taşır ve bu aracı nesne aracılığıyla iletişimi yönetir. Bu sayede, nesneler arasındaki bağımlılıkları azaltır ve birbirlerini doğrudan referans almadan iletişim kurmalarını sağlar.
  8. Memento Pattern (Anı Deseni): Bir nesnenin iç durumunu kapsüller ve daha sonra geri yükleme için kullanılabilir. Bu sayede, bir nesnenin önceki durumlarına geri dönülebilir.
  9. Visitor Pattern (Ziyaretçi Deseni): Bir nesne üzerinde farklı işlemleri uygulamak için kullanılır ve nesnenin yapısını değiştirmeden yeni işlevselliği ekler. Bu desen, özellikle nesne yapısında değişiklik yapmak istemiyorsanız ve farklı işlemleri uygulamak için bir yol arıyorsanız kullanışlıdır.
  10. State Pattern (Durum Deseni): Bir nesnenin davranışını durum değişikliklerine göre değiştirir. Bir nesnenin iç durumunu temsil eden ayrı durum sınıfları oluşturulur ve nesnenin durumu değiştiğinde farklı davranışlar tetiklenir.

Behavioral design patternler, nesneler arasındaki etkileşimi düzenler ve sistemdeki davranışları yönetir. Hangi desenin kullanılacağı, projenin gereksinimlerine ve tasarım hedeflerine bağlı olarak değişecektir.

Yorum Bırak

Prototype Design Pattern

Prototype Design Pattern: Mevcut bir nesnenin klonlanması ile yeni bir nesne oluşturmayı sağlar. Bu pattern, nesnelerin türetilmesi maliyetli veya zor olduğunda kullanışlıdır. Özellikle, büyük nesne oluşturma maliyeti varsa veya nesnelerin durumu dinamik olarak değişiyorsa kullanışlı olabilir.

Kısacası bir nesnenin kopyasını almak için kullanılır. Nesnelerin belirli bir durumunu koruyarak yeni nesneler oluşturmayı sağlar. Bu, nesnenin yapısını veya içeriğini bilmeden yeni bir nesne oluşturmak için kullanışlıdır. Örnek verecek olursak;

public interface ProtoType {
    ProtoType clone();
}
public class ConcretePrototype implements ProtoType {
    private Integer value;

    public ConcretePrototype(Integer value) {
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

    public void setValue(Integer value) {
        this.value = value;
    }

    @Override
    public ProtoType clone() {
        return new ConcretePrototype(this.value);
    }
}
   public static void main(String[] args) {
        // ProtoType Design Pattern
        protoTypeDesignPattern();
    }

    private static void protoTypeDesignPattern() {
        ConcretePrototype prototype = new ConcretePrototype(10);
        ConcretePrototype clone = (ConcretePrototype) prototype.clone();

        System.out.println("Original value : "+ prototype.getValue()); // output: 10
        System.out.println("Clone value : "+ clone.getValue()); // output: 10

        prototype.setValue(20);

        System.out.println("Original value after update : "+ prototype.getValue());  // output: 20
        System.out.println("Clone value after update : "+ clone.getValue());  // output: 10
    }

Örnekte, Prototype arayüzü, klonlama işlemini gerçekleştirmek için bir clone methodu içermektedir. ConcretePrototype classı, klonlanacak somut bir prototipi temsil eder ve clone methodunu çağırılır. Main sınıfında, bir prototip nesnesi oluşturup, bu nesnenin bir kopyası alınır. Ardından, orijinal ve kopya nesnelerin değerleri gösterir. Orijinal nesnenin değeri değiştirildiğinde, kopya nesnenin değeri değişmez çünkü kopya, orijinalin durumunu klonlama sırasında aldı. Bu örnek, Prototype design patternin nasıl çalıştığını göstermektedir.

Yorum Bırak

Builder Design Pattern

Builder Design Pattern: Karmaşık nesnelerin adım adım oluşturulmasını sağlar. Nesne oluşturma süreci, adım adım yönlendirilir ve nesne oluşturmayı karmaşık bir yapıdan ayırır. Builder design patterni, nesnelerin farklı bileşenlerinin aynı oluşturulma sürecini kullanarak farklı nesne varyasyonlarını oluşturmak için kullanışlıdır.

Örnek verecek olursak; bir bilgisayar nesnesi oluşturmak için Builder Design Patternini kullanalım. Bilgisayar classında, işlemci, RAM, depolama alanı gibi oluşturacak şekilde tasarlayalım.

public class Computer {

    private String processor;
    private Integer ram;
    private Integer storage;

    public void setProcessor(String processor) {
        this.processor = processor;
    }

    public void setRam(Integer ram) {
        this.ram = ram;
    }

    public void setStorage(Integer storage) {
        this.storage = storage;
    }

    public void show() {
        System.out.println("Processor: " + processor);
        System.out.println("RAM: " + ram + " GB");
        System.out.println("Storage : " + storage + " GB SSD");
    }
}

public interface ComputerBuilder {
    void buildProcessor();
    void buildRam();
    void buildStorage();
    Computer getResult();
}


public class DesktopBuilder implements ComputerBuilder {

    private Computer computer;

    public DesktopBuilder() {
        computer = new Computer();
    }

    @Override
    public void buildProcessor() {
        computer.setProcessor("Intel Core i7");
    }

    @Override
    public void buildRam() {
        computer.setRam(16);
    }

    @Override
    public void buildStorage() {
        computer.setStorage(512);
    }

    @Override
    public Computer getResult() {
        return computer;
    }
}


public class ComputerAssembler {

    private ComputerBuilder builder;
    public ComputerAssembler(ComputerBuilder builder) {
        this.builder = builder;
    }

    public void assembleComputer() {
        builder.buildProcessor();
        builder.buildRam();
        builder.buildStorage();
    }
}

    public static void main(String[] args) {
        // Builder Design Pattern
        builderDesignPatter();
    }

     private static void builderDesignPatter() {
        ComputerBuilder desktopBuilder = new DesktopBuilder();
        ComputerAssembler assembler = new ComputerAssembler(desktopBuilder);
        assembler.assembleComputer();

        Computer desktop = desktopBuilder.getResult();
        desktop.show();
    }

Bu örnekte, Computer sınıfı, oluşturulacak bilgisayar nesnesini temsil etmektedir.. ComputerBuilder arayüzü, bu nesnenin parçalarını oluşturmak için methodları tanımladık. DesktopBuilder sınıfı, masaüstü parçalarını oluşturan somut bir builder sınıfıdır. ComputerAssembler sınıfı, builder nesnesini kullanarak bilgisayar nesnesinin nasıl oluşturulacağını gösterir. Main classında, builder design pattern kullanarak bir masaüstü bilgisayar oluşturup, sonuç gösteriyor. Bu örnek, builder design patternin karmaşık nesnelerin oluşturulması için nasıl kullanılabileceğini göstermiş olduk.

Yorum Bırak

Abstract Factory Design Pattern

Abstract Factory Design Pattern: Bir nesne ailesi oluşturmak için soyut bir arayüz sağlar. Ardından, bu arayüzü uygulayan farklı fabrika sınıfları, farklı nesne ailelerini oluşturabilir. Bu pattern ile ilgili nesne gruplarının bir arada kullanılması gerektiği durumlarda kullanılır ve sistemlerin daha kolay genişletilmesini sağlar.

Örnek olarak; bir mobilya üretim uygulamasını düşünelim. Bu uygulamada, farklı mobilya parçalarının üretimi için Abstract Factory Design Patterni kullanabiliriz.

public interface Chair {
    void sitOn();
}
public class WoodenChair implements Chair{
    @Override
    public void sitOn() {
        System.out.println("Ahşap sandelyeye oturdu.");
    }
}
public class MetalChair implements Chair {
    @Override
    public void sitOn() {
        System.out.println("Metal sandelyeye oturdu.");
    }
}
public interface Table {
    void putOn();
}
public class WoodenTable implements Table {
    @Override
    public void putOn() {
        System.out.println("Ahşap masaya bir şey koydu.");
    }
}
 public class MetalTable implements Table {
    @Override
    public void putOn() {
        System.out.println("Metal masaya bir şey koydu.");
    }
}
public interface FurnitureFactory {
    Chair createChair();
    Table createTable();
}
public class WoodenFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new WoodenChair();
    }

    @Override
    public Table createTable() {
        return new WoodenTable();
    }
}
public class MetalFurnitureFactory implements FurnitureFactory{
    @Override
    public Chair createChair() {
        return new MetalChair();
    }

    @Override
    public Table createTable() {
        return new MetalTable();
    }
}
private static void createFurniture(FurnitureFactory factory) {
        Chair chair = factory.createChair();
        Table table = factory.createTable();

        chair.sitOn();
        table.putOn();
    }
private static void abstractFactoryDesignPatter(){
        createFurniture(new WoodenFurnitureFactory());
        createFurniture(new MetalFurnitureFactory());
    }

public static void main(String[] args) {
        // Abstract Factory Design Pattern
        abstractFactoryDesignPatter();
    }

Bu örnekte, Chair ve Table arayüzleri iki farklı mobilya parçasını temsil ediyor. Ahşap ve metal için farklı somut mobilya parçaları bu arayüzlere uyguladık. FurnitureFactory arayüzü, bu mobilya parçalarını oluşturmak için gerekli methodları tanımladık. WoodenFurnitureFactory ve MetalFurnitureFactory gibi classlarda, belirli bir malzeme tipi için ilgili mobilya parçalarını oluşturduk. En son adımda, Main sınıfında, farklı malzeme tipleri için mobilya setleri oluşturmak için soyut fabrika desenini kullanarak bu desenin nasıl kullanılacağını göstermiş olduk.

Yorum Bırak

Factory Method Design Pattern

Factory Method Design Pattern: Bir arayüz sağlar ve alt sınıfların bu arayüzü uygulayarak nesneleri oluşturmasını sağlar. Bu sayede, nesne oluşturma işlemi istemciden gizlenir. Böylelikle alt sınıfların nesne oluşturma mantığını değiştirmesi kolaylaşır. Factory Method, nesnelerin oluşturulmasıyla ilgili kararların alt sınıflara devredilmesi gerektiği durumlarda kullanılır.

Bir senaryo için bir örnek düşünelim: bir e-ticaret uygulaması. Bu uygulamada, farklı ürün kategorileri için ürün oluşturma işlemlerini Factory Method tasarım deseni ile gerçekleştirebiliriz.

public interface Product {
    void display();
}
public class Laptop implements Product{
    @Override
    public void display() {
        System.out.println("Laptop: Dell Precision 3520");
    }
}
public class Phone implements Product{
    @Override
    public void display() {
        System.out.println("Telefon: Iphone 15 Prox Max");
    }
}
public abstract class ProductFactory {
    abstract Product createProduct();

    public void processOrder() {
        Product product = createProduct();
        product.display();
    }
}
public class LaptopFactory extends ProductFactory{
    @Override
    Product createProduct() {
        return new Laptop();
    }
}
public class PhoneFactory extends ProductFactory{
    @Override
    Product createProduct() {
        return new Phone();
    }
}
public class Main {
    public static void main(String[] args) {
        // Factory Method Design Pattern
        factoryMethodDesignPattern();
    }
  
    private static void factoryMethodDesignPattern() {
        ProductFactory phoneFactory = new PhoneFactory();
        ProductFactory laptopFactory = new LaptopFactory();
        phoneFactory.processOrder();
        laptopFactory.processOrder();
    }
}

Bu örnekte, Product arayüzü telefon ve laptop ürünlerini temsil ettik. Phone ve Laptop ürünler için arayüzü uyguladık. ProductFactory sınıfından, Factory Method (createProduct) oluşturup, bu sınıfın alt sınıflarına (PhoneFactory ve LaptopFactory) bu methodları uyguladık. Ana işlem processOrder metodu, Factory Method’u çağırarak bir ürün oluşturup ve onunla ilgili bilgileri gösterdik. Main sınıfında, farklı ürünleri sipariş ederek ve bilgileri görüntüleyerek bu desenin nasıl kullanılacağını görmüş olduk.

Yorum Bırak