Tasarım Kalıpları: Façade (Ön Yüz) Kalıbı – I

GoF’un yapısal kalıplarından bir diğeri de Façade’dır. Bu kelime pek çok yerde “c” ile “Facade” olarak yazılmasına rağmen aslen Fransızca’da “ç” ile “Façade” olarak yazılır ve binaların ön yüzü, ön cephesi anlamına gelir. Zaten kelime yapısı itibarıyla “face” yani “yüz” ile de akrabadır.

Bu kısa açıklamdan sonra GoF’un bu kalıp ile ilgili dediklerine bir bakalım:

Intent: Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher level interface that makes the subsystem easier to use.

Amaç: Bir alt sistemdeki arayüzlere, bir birleşik arayüz sağla. Façade, alt sistemi daha kolay kullanmak için daha yüksek seviyeli bir arayüz sağlar.

Evet bu amaç açıklamasından da anlaşıldığı gibi Façade, karmaşık iş süreçlerini saklamakta kullanılan bir kalıptır. Çoğunlukla kullandığımız algoritmalar veya iş mantığı, bir süreç oluşturacak şekilde, pek çok farklı nesneden hizmet alarak ilerler. Süreç, hangi nesneden hangi durumlarda hizmet alınacağı bilgisini detayıyla ifade eder. Süreç, aynı zamanda pek çok iş kuralı ile de yönlendirilir. Böyle durumlarda client nesnelerin, süreci tüm detayıyla bilmelerini istemeyiz. Bu sıkıntılı durumu aşağıdaki örnekte rahatlıkla görebiliriz:

ClassDiagram1

Yukarıdaki yapıda görüldüğü gibi Client, bir bilgisayarı çalıştırmak için onun parçalarına tek tek ulaşıp, bir süreç halinde hepsini başlatması gereklidir. Bu çalışma şekli aşağıdaki akış diyagramında verilmiştir:

SequenceDiagram1

Böyle bir çalışma şeklinin Client nesnesini ne kadar karmaşık yaptığı ortadadır. Client nesnesinin koduna bakarsak:

package org.javaturk.dp.pattern.gof.structural.facade.computer.problem;

import org.javaturk.dp.pattern.gof.structural.facade.computer.CPU;
import org.javaturk.dp.pattern.gof.structural.facade.computer.Display;
import org.javaturk.dp.pattern.gof.structural.facade.computer.HardDrive;
import org.javaturk.dp.pattern.gof.structural.facade.computer.RAM;

public class Client {
	
	private CPU cpu;
	private RAM ram;
	private HardDrive hd;
	private Display display;

	public Client() {
		cpu = new CPU();
		ram = new RAM();
		hd = new HardDrive();
		display = new Display();
	}
	
	public void start() {
		cpu.start();
		hd.start();
		boolean kernelLoaded = ram.loadOSKernelImage();
		while(!kernelLoaded){
			ram.fixIt();
			kernelLoaded = ram.loadOSKernelImage();
		}
		
		boolean osLoaded = ram.loadOS();
		while(!osLoaded){
			ram.fixIt();
			osLoaded = ram.loadOS();
		}
		
		ram.loadDrivers();
		ram.startServices();
		display.start();
		System.out.println("Computer has started.");
	}

	public static void main(String[] args) {
		new Client().start();

	}
}

Client nesnesinin start() metodunun yukarıdaki basit örnekte bile bilgisayarın parçaları olan nesnelerle pek çok mesajlaşma içermesi ve bu nesnenin bir bilgisayarın ayağa kalkmasıyla ilgili süreci detayıyla bilmesi, gerçek bir projede iş süreçlerinden haberdar olan nesnelerin ne kadar karmaşık olabileceğini göstermeye yeter sanırım. Öte taraftan, CPU ya da RAM gibi nesnelerde ya da bilgisayarı ayağa kaldırma sürecinde yapılacak bir  değişikliğin Client’da değişikliğe sebep olacağı da aşikardır. Bu sıkıntılardan kurtulmanın yolu, diğer mühendisliklerde başarıyla yaptığımız gibi burada da arka taraftaki karmaşık sistemi saklayıp, önüne koyulacak basit bir arayüz ile yönetimini sağlamaktır. Bu basit arayüz, Façade’dır.

Arka tarafta bulunup, süreci yerine getiren nesnelerle ön taraftaki client arasına konan Façade, algoritma ya da iş mantığındaki süreci tüm detaylarını bilir. Bu şekilde bir ara nesne olarak Facade, clientı, süreci yerine getiren nesnelerden yalıtmakta kullanılır. Façade, sürecin tüm detaylarını bilir ama bu detayların hepsini arayüzünde dışarıya sunmaz, muhtemelen arayüzünde bir seferde çok iş yapacak şekilde, coarse grained metotlar sağlar Client ise bu şekilde Façade nesnesinden hizmet alır. Client bu hizmeti alırken, sürecin detaylarından etkilenmez, sürecin işlemesi için gerekli bilgileri Façade’a sağlayarak, Façade’ın süreci çalıştırıp kendisine dönmesini bekler.

Façade gibi bir yalıtım nesnesinin kullanımı zaman zaman seçilen mimari ve teknolojilerden dolayı da faydalı hatta zorunlu olabilir. Örneğin uzak nesnelere (distributed objects) erişerek hizmet alma durumunda, bu nesnelere pek çok ufak-tefek iş yapan çağrı yapmaktansa, uzak nesnelerin önüne konulacak bir uzak Façade nesnesi ile, yapılacak uzak metot çağrılarının sayısı bir hayli azaltılabilir. Bu durumda ağ trafiği kullanımı da daha etkin hale gelir.

Bakın Façade nesnesinin kullanımıyla çözümümüz ne hale gelir:

ClassDiagram1

Bu durumda Client nesnesinin, Computer façade nesnesiyle haberleşmesi ise şöyle olur:

SequenceDiagram1

Client nesnesinin koduna bakarsak, artık son derece sade olduğunu farkederiz:

package org.javaturk.dp.pattern.gof.structural.facade.computer;

public class Client {

	public static void main(String[] args) {
		Computer computer = new Computer();
		computer.start();
	}
}


Çünkü tüm karmaşıklık ve bağımlılık Computer nesnesine kaymıştır:

package org.javaturk.dp.pattern.gof.structural.facade.computer;

public class Computer {
	private CPU cpu;
	private RAM ram;
	private HardDrive hd;
	private Display display;

	public Computer() {
		cpu = new CPU();
		ram = new RAM();
		hd = new HardDrive();
		display = new Display();
	}
	
	public void start() {
		cpu.start();
		hd.start();
		boolean kernelLoaded = ram.loadOSKernelImage();
		while(!kernelLoaded){
			ram.fixIt();
			kernelLoaded = ram.loadOSKernelImage();
		}
		
		boolean osLoaded = ram.loadOS();
		while(!osLoaded){
			ram.fixIt();
			osLoaded = ram.loadOS();
		}
		
		ram.loadDrivers();
		ram.startServices();
		display.start();
		System.out.println("Computer has started.");
	}
}

Façade ile ilgili tartışmamıza burada ara verelim. Bir sonraki yazıda biraz daha kurumsal yapılardaki kullanımından bahsedeceğiz.

Bu yazı toplam 1078 defa görüntülenmiştir.