---
title: Strateji
source: 'https://academia.sh/tr/kurslar/tasarim-kaliplari/strateji'
course: 'Tasarım Kalıpları'
language: tr
updated: '2026-08-17T18:10:38+00:00'
license: 'CC BY-SA 4.0'
---

# Strateji

Ücret hesaplama algoritmasının çağrı yerine gömüldüğü tasarım ile tarifenin parametre olarak geçildiği tasarımın karşılaştırılması: tek koşumda denenebilen algoritma sayısı, yeni tarife eklendiğinde düzenlenen dosya ve satır sayısı, kalıbın bedeli olarak eklenen dosya sayısı ve çağrı yerinden izlenmesi gereken olası gövde sayısı.

Yapısal kalıplar nesnelerin nasıl birleştirileceğini düzenledi: bağdaştırıcı uyumsuz iki
arayüzü köprüledi, dekoratör davranışı katmanladı, bileşik ağacı tek biçim ele aldı, vekil
ise araya girip çağrıyı **aynı arayüzle** ilerisine geçirdi. Vekilde araya giren nesnenin işi
çağrıyı geçirmekti; hesabın kendisi değişmiyordu. Sıradaki soru birleşme değil: aynı arayüzün
arkasındaki **hesabın kendisi** çalışma zamanında değiştirilebilir mi?

Ücretlendirme kitaplığında bu somut bir istektir. Aynı gönderi kümesi standart tarifeyle,
ekspres tarifeyle ve hacimden türetilen ücretli ağırlık tarifesiyle fiyatlanmak istenir; üçü
de aynı koşumda, aynı veriyle. **Strateji** (strategy) kalıbı bunu, algoritmayı bir nesneye
alıp çağrı yerine parametre olarak geçirerek yapar. Koşul zinciri, arama tablosu ve çok
biçimlilik arasındaki seçim Temiz Kod ve Programlama Paradigmaları kurslarında ölçülmüştü; bu
derste ölçülen şey başka: **hangi dosyaların düzenlenmesi gerektiği** ve **tek koşumda kaç
algoritmanın yan yana durabildiği**.

## İki Tasarım

Ortak veri her iki sürümde aynıdır. Tutarlar kuruş cinsindendir, ağırlık kilogram, hacim
desimetreküp.

```sh
mkdir -p gomulu strateji
```

```js
// veri.mjs — ucretlendirilecek gonderiler (agirlik kg, hacim dm3, tutarlar kurus)
export const GONDERILER = [
  { kod: "GN-1", agirlik: 2, hacim: 8, bolge: "1" },
  { kod: "GN-2", agirlik: 6, hacim: 60, bolge: "2" },
  { kod: "GN-3", agirlik: 14, hacim: 20, bolge: "3" },
  { kod: "GN-4", agirlik: 1, hacim: 3, bolge: "2" },
  { kod: "GN-5", agirlik: 22, hacim: 180, bolge: "3" },
];
```

Birinci tasarımda formül, onu çağıran modülün ithal ettiği tek gövdenin içindedir. Toplu
fiyatlama hangi algoritmayı çalıştırdığını seçmez; ithal satırı seçmiştir.

```js
// gomulu/ucret.mjs — tarife formulu govdenin icinde sabit
const BOLGE_KATSAYI = { "1": 100, "2": 130, "3": 175 };

export function ucret(gonderi) {
  const ham = 2500 + 420 * Math.ceil(gonderi.agirlik);
  return Math.max(Math.round((ham * BOLGE_KATSAYI[gonderi.bolge]) / 100), 3900);
}
```

```js
// gomulu/toplu.mjs — toplu fiyatlama; algoritma ithalle sabitlenmis
import { ucret } from "./ucret.mjs";

export const topluUcret = (gonderiler) =>
  gonderiler.map((g) => ({ kod: g.kod, tutar: ucret(g) }));
```

İkinci tasarımda her tarife kendi dosyasında bir nesnedir. Nesnelerin tek ortak sözleşmesi
`ucret(gonderi)` yöntemidir; paylaştıkları tek veri bölge katsayılarıdır.

```js
// strateji/bolge.mjs — bolge katsayilari, tarifelerin paylastigi tek veri
export const BOLGE_KATSAYI = { "1": 100, "2": 130, "3": 175 };
export const bolgele = (ham, bolge) => Math.round((ham * BOLGE_KATSAYI[bolge]) / 100);
```

```js
// strateji/tarife-standart.mjs
import { bolgele } from "./bolge.mjs";

export const standart = {
  ad: "standart",
  ucret(gonderi) {
    return Math.max(bolgele(2500 + 420 * Math.ceil(gonderi.agirlik), gonderi.bolge), 3900);
  },
};
```

```js
// strateji/tarife-ekspres.mjs
import { bolgele } from "./bolge.mjs";

export const ekspres = {
  ad: "ekspres",
  ucret(gonderi) {
    return Math.max(bolgele(4000 + 640 * Math.ceil(gonderi.agirlik), gonderi.bolge), 6500);
  },
};
```

```js
// strateji/tarife-hacimsel.mjs — ucretli agirlik hacimden turetilir
import { bolgele } from "./bolge.mjs";

export const hacimsel = {
  ad: "hacimsel",
  ucret(gonderi) {
    const ucretliAgirlik = Math.max(Math.ceil(gonderi.agirlik), Math.ceil(gonderi.hacim / 5));
    return Math.max(bolgele(2500 + 420 * ucretliAgirlik, gonderi.bolge), 3900);
  },
};
```

```js
// strateji/toplu.mjs — tarife parametre olarak gelir
export const topluUcret = (gonderiler, tarife) =>
  gonderiler.map((g) => ({ kod: g.kod, tutar: tarife.ucret(g) }));
```

Toplu fiyatlama artık hiçbir tarifeyi ithal etmiyor. Bildiği tek şey, aldığı nesnenin bir
`ucret` yöntemi taşıdığıdır.

## Tek Koşumda Kaç Algoritma

İlk ölçü, aynı süreçte aynı veriye kaç ayrı algoritmanın uygulanabildiğidir. Sürücü betik
iki sürümü de çağırır.

```js
// kosum.mjs — tek kosumda kac tarife denenebiliyor
import { GONDERILER } from "./veri.mjs";
import { topluUcret as gomuluToplu } from "./gomulu/toplu.mjs";
import { topluUcret as stratejiToplu } from "./strateji/toplu.mjs";
import { standart } from "./strateji/tarife-standart.mjs";
import { ekspres } from "./strateji/tarife-ekspres.mjs";
import { hacimsel } from "./strateji/tarife-hacimsel.mjs";

const yaz = (etiket, satirlar) =>
  console.log(`${etiket.padEnd(18)} ${satirlar.map((s) => `${s.kod}=${s.tutar}`).join(" ")}`);

const gomuluSonuc = [gomuluToplu(GONDERILER)];
yaz("gomulu", gomuluSonuc[0]);

const stratejiSonuc = [standart, ekspres, hacimsel].map((t) => {
  const satirlar = stratejiToplu(GONDERILER, t);
  yaz(`strateji/${t.ad}`, satirlar);
  return satirlar;
});

console.log(`gomulu   : tek kosumda denenen tarife = ${gomuluSonuc.length}`);
console.log(`strateji : tek kosumda denenen tarife = ${stratejiSonuc.length}`);
```

```
gomulu             GN-1=3900 GN-2=6526 GN-3=14665 GN-4=3900 GN-5=20545
strateji/standart  GN-1=3900 GN-2=6526 GN-3=14665 GN-4=3900 GN-5=20545
strateji/ekspres   GN-1=6500 GN-2=10192 GN-3=22680 GN-4=6500 GN-5=31640
strateji/hacimsel  GN-1=3900 GN-2=9802 GN-3=14665 GN-4=3900 GN-5=30835
gomulu   : tek kosumda denenen tarife = 1
strateji : tek kosumda denenen tarife = 3
```

Bir ve üç. Gömülü sürümde ikinci bir tarifeyi denemenin yolu kaynağı düzenleyip süreci
yeniden başlatmaktır; üç tarifeyi karşılaştıran bir rapor üç ayrı koşum ve arada iki
düzenleme demektir. Strateji sürümünde üç sonuç aynı süreçte yan yana durur, bu yüzden
karşılaştırma raporu bir işlev çağrısıdır. Çıktının ilk iki satırının aynı olması ölçümün
geçerlilik koşuludur: strateji sürümü standart tarifede gömülü sürümle birebir aynı tutarı
üretiyor, yani karşılaştırılan iki tasarım aynı davranışı taşıyor.

## Dördüncü Tarife Eklendiğinde

İkinci ölçü değişim maliyetidir. Ekonomik adında dördüncü bir tarife isteniyor: tabanı 1800,
kademesi 300, asgari ücreti 3200. İki ağaç kopyalanır ve istek ikisine de uygulanır. Gömülü
sürümde gövdenin kendisi ve onu çağıran modülün imzası; strateji sürümünde tek bir yeni
dosya.

```sh
cp -r gomulu gomulu-yeni
cp -r strateji strateji-yeni

cat > gomulu-yeni/ucret.mjs <<'SON'
// gomulu/ucret.mjs — tarife formulu govdenin icinde sabit
const BOLGE_KATSAYI = { "1": 100, "2": 130, "3": 175 };

export function ucret(gonderi, mod = "standart") {
  const taban = mod === "ekonomik" ? 1800 : 2500;
  const kademe = mod === "ekonomik" ? 300 : 420;
  const asgari = mod === "ekonomik" ? 3200 : 3900;
  const ham = taban + kademe * Math.ceil(gonderi.agirlik);
  return Math.max(Math.round((ham * BOLGE_KATSAYI[gonderi.bolge]) / 100), asgari);
}
SON

cat > gomulu-yeni/toplu.mjs <<'SON'
// gomulu/toplu.mjs — toplu fiyatlama; algoritma ithalle sabitlenmis
import { ucret } from "./ucret.mjs";

export const topluUcret = (gonderiler, mod) =>
  gonderiler.map((g) => ({ kod: g.kod, tutar: ucret(g, mod) }));
SON

cat > strateji-yeni/tarife-ekonomik.mjs <<'SON'
// strateji/tarife-ekonomik.mjs — var olan dosyalara dokunulmadi
import { bolgele } from "./bolge.mjs";

export const ekonomik = {
  ad: "ekonomik",
  ucret(gonderi) {
    return Math.max(bolgele(1800 + 300 * Math.ceil(gonderi.agirlik), gonderi.bolge), 3200);
  },
};
SON

for k in gomulu strateji; do
  duzenlenen=$(diff -rq "$k" "$k-yeni" | grep -c '^Files')
  eklenen=$(diff -rq "$k" "$k-yeni" | grep -c '^Only in')
  satir=$(diff -r -u "$k" "$k-yeni" | grep '^[+-][^+-]' | grep -vc '^[+-]//')
  echo "$k: duzenlenen dosya=$duzenlenen  yeni dosya=$eklenen  duzenlenen satir=$satir"
done
echo "dosya sayisi: gomulu=$(ls gomulu | wc -l | tr -d ' ')  strateji=$(ls strateji | wc -l | tr -d ' ')"
echo "cagri yerinden olasi govde: gomulu=1  strateji=$(grep -l 'ucret(gonderi)' strateji/tarife-*.mjs | wc -l | tr -d ' ')"
```

```
gomulu: duzenlenen dosya=2  yeni dosya=0  duzenlenen satir=13
strateji: duzenlenen dosya=0  yeni dosya=1  duzenlenen satir=0
dosya sayisi: gomulu=2  strateji=5
cagri yerinden olasi govde: gomulu=1  strateji=3
```

Gömülü sürümde iki dosya ve on üç satır düzenlendi; bu satırların bir kısmı çalışan
tarifelerin de geçtiği gövdedir, yani dördüncü tarifeyi eklerken ilk üçünün davranışı riske
girer. Strateji sürümünde düzenlenen dosya sıfırdır. Açık–kapalı ilkesinin ölçüsü tam olarak
budur ve strateji kalıbı bu ilkeyi tarife ekseninde sağlar.

## Kalıbın Bedeli

Aynı çıktının son iki satırı bedeli veriyor. Dosya sayısı 2'den 5'e çıktı: üç tarife dosyası
ve paylaşılan bölge modülü. Bedelin ikinci kalemi okuma maliyetidir. Gömülü sürümde `ucret`
çağrısından tek bir gövdeye gidilir; strateji sürümünde `tarife.ucret(g)` çağrısından
statik olarak üç ayrı gövdeye gidilebilir. Hangisinin çalıştığını anlamak için nesnenin nerede
üretildiğine, yani çağrı zincirinin bir üst basamağına bakmak gerekir. Bu, bir dolaylılık
basamağıdır ve sayısı üçtür.

Denge şöyle kurulur: tarife sayısı arttıkça düzenlenen satır sayısı gömülü sürümde büyür,
strateji sürümünde sıfır kalır; dosya sayısı ise gömülü sürümde sabit kalır, strateji
sürümünde tarife başına bir artar. İki eğrinin kesiştiği yer kalıbın karşılığını verdiği
eşiktir. Tek tarifesi olan bir kitaplıkta strateji kalıbı üç dosya ve bir dolaylılık basamağı
ekler, karşılığında sıfır kazanç verir; bu durumun ölçümü konunun son dersindedir.

## Özet

- Strateji kalıbı, bir hesabı ayrı bir nesneye alıp çağrı yerine parametre olarak geçirir;
  ölçülen kazanç, algoritmanın çalışma zamanında değiştirilebilmesidir.
- Aynı veri üzerinde tek koşumda denenebilen algoritma sayısı gömülü sürümde 1, strateji
  sürümünde 3 çıktı; strateji sürümü standart tarifede birebir aynı tutarları üretti.
- Dördüncü tarife eklendiğinde gömülü sürümde 2 dosya ve 13 satır düzenlendi, strateji
  sürümünde 0 dosya düzenlendi ve 1 dosya eklendi.
- Bedel iki kalemdir: dosya sayısı 2'den 5'e çıktı ve çağrı yerinden statik olarak izlenmesi
  gereken olası gövde sayısı 1'den 3'e yükseldi.
- Kalıp, tarife sayısı arttıkça karşılığını verir; tek gerçekleştirimde eklenen dosya ve
  dolaylılık karşılıksız kalır.

## Sonraki Adım

Tarife nesnesi bir hesabı taşıyor ve çağıran onu doğrudan çağırıyor: bağ tek yönlü ve
açıktır. Kitaplığın başka bir yerinde ise ilişki ters yönde kuruluyor. Bir teslimatın durumu
değiştiğinde günlük satırı yazılması, müşteriye bildirim düşülmesi, ölçüm sayacının
artırılması ve faturalama kaydının güncellenmesi gerekiyor. Bu dört işi teslimat modülünün
kendisi çağırırsa teslimat dördünü de ithal etmek zorunda kalır ve beşinci iş eklendiğinde
yine düzenlenir. Sonraki ders bu durumu giden bağ sayısı ve ithal kapanışı boyutuyla ölçer,
sonra bildirimi tersine çevirip aynı sayıları yeniden hesaplar.
