JavaScript’te Tasarım Desenleri: Creational Patterns

Furkan Gulsen
4 min readOct 13, 2022

Tasarım Desenleri Nedir?

Günlük hayatta yazılımcılar kod yazarken çok sayıda hata ile karşılaşabiliyorlar ve haliyle karşılaştıkları bu sorunları çözmek için yöntemler geliştiriyorlar. Bambaşka projelerde farklı yazımcıların geliştirdiği çözümleri birbirine çok benziyor. İşte bu aşamada devreye Tasarım Desenleri giriyor.

Tasarım kalıpları, yazılım geliştiricilerin yazılım geliştirme sırasında karşılaştıkları genel sorunların çözümüdür.

Tasarım desenlerinin (Design Patterns) daha iyi anlaşılması için maddeler halinde inceleyelim:

  • Genel olarak OOP temeline dayalıdır. Fakat dilden ve teknolojiden bağımsız olarak kullanılabilir.
  • Yazılımcıların kullandığı ispatlanmış çözüm yöntemleridir.
  • Probleme yönelik uygulanan genel çözüm planlarıdır.

Tasarım Desenlerini 3 başlık altında topluyoruz:

  1. Yaratımsal Desenler (Creational Patterns)
  2. Yapısal Desenler (Structural Patterns)
  3. Davranışsal Desenler (Behavioral Patterns)

Bu yazımda Yaratımcal (Creational) Desenlerden bahsedeceğim:

Yaratımsal (Creational) Desenler

Nesnelerin oluşturulmasında ve yönetilmesinde kullanılan bir desendir. Kodun esnekliğini ve tekrar kullanılabilirliğini arttıran nesne oluşturma mekanizmaları sunarlar.

Factory Method

Tek bir nesne oluşturmak için bir arabirim tanımlar ve alt sınıfların hangi sınıfın başlatılacağına karar vermesine izin verir.

Örnek: Person adında bir class tanımlayalım.

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
}

Şimdi Factory metodumuzu ekleyelim:

class PersonFactory {
static add(name, age) {
return new Person(name, age);
}
}

Artık PersonFactory modelimizi kullanarak yeni Person nesnesi oluşturabiliriz:

const person = PersonFactory.add("furkan", 24);
console.log(person)
> Output:
>
Person { name: 'furkan', age: 24 }

Abstract Factory

Abstract Factory, aynı anda birden çok nesne ile birlikte işlem yapmak istediğimiz durumlarda kullanabileceğimiz bir tasarım desenidir.

Örnek: Person örneğinden devam edelim ve Person sınıfından türetilmiş Client adında bir tane daha sınıf yaratalım:

class Person {
consume() {}
}
class Client extends Person {
consume() {
console.log("Client")
}
}

Şimdi bunlara factory methodlar yaratalım ve abstract kullanımının nasıl olduğunu görelim:

class PersonFactory {
prepare(name)
}
class ClientFactory extends PersonFactory {
addClient() {
console.log("Client created")
return new Client();
}
}

Artık abstract factory metodumuzu kullanmanın vakti geldi:

const clientUserFact = new ClientFactory();
const person = clientUserFact.addClient();
person.consume();
> Output:
>
Client created
> Client

Builder

Bu tasarım, aynı construction kodunu kullanarak bir nesnenin farklı türlerini ve temsillerini oluşturmanıza olanak tanır.

Örnek: Klasik Person örneğimiz ile devam edelim. Burada Person nesnesini biraz değiştireceğiz:

class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}

toString() {
return (
`${this.name} is ${this.age} years old!`
)
}
}

Person nesnesinde iki adet bilgi kullanıyoruz: name ve age. Şimdi bir tane Person Builder tanımlayalım:

class PersonBuilder {
constructor(person = new Person()) {
this.person = person;
}

get age() {
return new PersonAgeBuilder(this.person);
}

get name(){
return new PersonNameBuilder(this.person);
}

build() {
return this.person;
}
}

Yukarıda nesnemizin iki adet bilgi içerdiğini söyledik. Şimdi burada o nesnelere ait builder’ları oluşturalım:

class PersonNameBuilder extends PersonBuilder {
constructor(person) {
super(person)
}

is(name) {
this.person.name = name;
return this;
}
}
class PersonAgeBuilder extends PersonBuilder {
constructor(person) {
super(person)
}

is(age) {
this.person.age = age;
return this;
}
}

Şimdi bu yazdığımız nesneleri kullanma vakti geldi:

const personBuilder = new PersonBuilder();
const person = personBuilder
.name.is("Furkan")
.age.is(24)
.build();
console.log(person.toString());

> Output:
>
Furkan is 24 years old!

Prototype

Prototype, kodunuzu sınıflarına bağımlı hale getirmeden mevcut nesneleri kopyalamanıza olanak tanıyan bir tasarım desenidir.

Örnek: Geldik yine Person nesnemize :D Burada Person nesnemiz şu şekilde olacaktır:

class Person {
constructor(name) {
this.name = name;
}

setName(name) {
this.name = name;
console.log(name.toString())
}

clone() {
return new Person(this.name)
}
}

Amaç kopyalamak dedik ve nesnemizin içerisine clone adında bir metot koyduk. Şimdi bunu kullanıp nesnemizi klonlayalım:

const person1 = new Person();
person1.setName("furkan");
const person2 = person1.clone();
person2.setName("tugay");
> Output:
> furkan
> tugay

Singleton

Singleton, bir nesnenin sadece bir örneğinin olduğundan emin olmak ve bu nesneye ihtiyacınız olduğunda kodunuzda her yerde aynı çağırılmasını sağlamak için kullanılır.

Bu aynı zamanda SOLID ilkesinde yer alan “Single Responsibility Principle” ile benzerlik göstermektedir.

Örnek: Person nesnesini kullanacağımız son örneğimize geldik.

class Person {
constructor() {
const instance = this.constructor.instance;
if(instance) {
return instance;
}
this.constructor.instance = this;
}

toString() {
console.log("Person Class");
}
}

Singleton’ın sağlanıp sağlanmadığını da bu şekilde kontrol edebiliriz:

const person1 = new Person();
const person2 = new Person();
console.log("is same: ", (person1 === person2));
person1.toString();
> Output:
> Person Class

Bu yazımda, Tasarım Desenlerinin ne olduğundan bahsettim ve Yaratımsal (Creational) Desenleri JavaScript kodlarıyla birlikte anlatmaya çalıştım.

Bu yazıya bağlı olarak iki adet daha yazı paylaşacağım. Bunlar:

  • JavaScript’te Tasarım Desenleri: Structural Patterns
  • JavaScript’te Tasarım Desenleri: Behavioral Patterns

Umarım sizin için faydalı bir yazı olmuştur. Beni desteklemek için alkışlamayı ve twitter’dan takip etmeyi unutmayınız :D

Sevgiler ve saygılar…

--

--

Furkan Gulsen
Furkan Gulsen

Written by Furkan Gulsen

🧑‍💻 As a software engineer, I write about software, artificial intelligence, productivity, and everything I know

No responses yet