avatar

Interfaces (Arayüz, Arabirim)
Java & React Eğitimi

02/05/2021
ORHAN ARI

Interface  kelime anlamı olarak “arayüz, arabirim” manasına gelmektedir. Interface Classlara veya struct’lara  rehberlik (kılavuzluk) eden (ne yapacağını söyleyen) yapılardır. Aynı zamanda Soyutlama (Abstraction) yapmak için kullanırız. Aynı şekilde soyutlamanın OOP‘nin 4 ana başlığınından bir tanesidir.

Logger Class (Base Class):

public class Logger {
	public void log() {
		System.out.println("Ortak konfigurasyon");
	}
}

FileLogger Class içerisinde Logger extend etme:

public class FileLogger extends Logger{
	// Base'deki log bloğunun çalışmasını istemiyoruz ve üzerine yazarak, buradaki void'de yer alan kodlarımızı çalıştırıyoruz.
	// Override, sadece extend edilen yerde yani base'deki kodu ezdiğimizi belirtiyoruz, bir işlevi yok.
	@Override
	public void log() {
		System.out.println("Dosya loglandı");
	}
}

Buraya kadar olan kısım, inheritance örnekleriydi. Şimdi gelelim interfaces'lere.

Logger Interface:

public interface Logger {
	void log(String message);
}

Bir önceki inheritance örneklerinde extend işleminden bahsediyorduk. Şimdi ise implement işlemi yapacağız.

Implements, “interface” uygulamak için kullanılan terimdir. Yerine getirmek, uygulamak anlamında kullanılmaktadır. “Interface” sınıfında belirtilen metotları kullanacağımızı belirtmiş oluruz ve bu “interface” sınıfında tanımlanmış olan metotları kullanmak zorundayızdır.

Hadi şimdi implement edelim.

FileLogger Class:

public class FileLogger implements Logger{

	@Override
	public void log(String message) {
		System.out.println("Dosyaya loglandı: " + message);
	}
	
}

Buraya kadar her şey tamam. Implement de ettik, şimdi sırada bunları kullanmak var.

CustomerManager Class:

	public void add(Customer customer) {
		System.out.println("Müşteri eklendi: " + customer.getFirstName());
		
		FileLogger logger = new FileLogger();
		logger.log(customer.getFirstName() + " dosyaya loglandı");
	}

Hadi dosyaya loglama işlemini yaptık ama demezler mi veritabanına da logla diye? İşte asıl iş burada başlıyor. Dependency Injection uygulamamız gerekiyor. Yani kodu bağımlı halden kurtarmalıyız.

Dependency Injection uygulayarak; bir sınıfının bağımlı olduğu nesneden bağımsız hareket edebilmesini sağlayabilir ve kod üzerinde olası geliştirmelere karşın değişiklik yapma ihtiyacını ortadan kaldırabiliriz.

Hemen CustomerManager Class'ımıza gelip bir private Logger tanımlayıp, peşine constructor oluşturuyoruz:

	private Logger logger; //Tanımlama
	
	public CustomerManager(Logger logger) { //Constructor oluşturma
		this.logger = logger;
	}

	public void add(Customer customer) {
		System.out.println("Müşteri eklendi: " + customer.getFirstName());
		
		//FileLogger logger = new FileLogger();
		//logger.log(customer.getFirstName() + " dosyaya loglandı");
		
		//Artık loglama işlemini yapabiliriz:
		this.logger.log(customer.getFirstName());
	}

Burası da tamam ama bunları nasıl kullanacağız? Geliyoruz Main'e:

Customer engin = new Customer(1, "Engin", "Demiroğ"); //Müşteri oluşturuyoruz

CustomerManager customerManager = new CustomerManager(new FileLogger()); //Müşteri yönetimi ve loglama işlemleri
customerManager.add(engin);

Şeklinde kullanabiliyoruz. Peki bu yapı nasıl çalışıyor?

  1. Log işlemi yapmak için Logger interface tanımlamasını private yaparak, constructor oluşturuyoruz.
  2. CustomerManager içerisindeki add metodunun içerisinde ekleme işlemlerini simüle ettikten sonra log işlemi yapıyoruz.
  3. Log işlemini gerçekleştirebilmek için Main içerisinde CustomerManager tanımlaması yaptıktan sonra içerisine herhangi bir kayıt türü ekliyoruz.
  4. Belirttiğimiz türdeki class'a gidiliyor ve @Override metodumuz çalışıyor.

 

Peki birden fazla alana loglama yapmak istersek, o zaman ne yapacağız?
Anahtar kelime: Array.

Çok basit. CustomerManager içerisindeki Logger tanımlamamızı

private Logger[] loggers;

şeklinde oluşturmamız yeterli.

Şimdi CustomerManager içerisinde loglama işlemini gerçekleştirelim:

		//this.logger.log(customer.getFirstName());
		for(Logger logger : loggers) {
			logger.log(customer.getFirstName());
		}

Main'deki değişikliklerimiz de şu şekilde:

Logger[] loggers = {new SmsLogger(), new EmailLogger(), new FileLogger()};
CustomerManager customerManager = new CustomerManager(loggers);

Yalnız düşünsenize, CustomerManager içerisinde yer alan döngüleri belki binlerce satırda kullanacağız. Bunun yerine araç görevi görecek, sıklıkla kullandığımız yapıları, hızlıca kullanabileceğimiz kodlar yazabiliyoruz.

Bu yapıda da amacımız, bunu statik bir metod haline getirip o şekilde kullandırmak.

Bunun için bir class daha oluşturalım; Utils Class:

public class Utils {
	
	public static void runLoggers(Logger[] loggers, String message) {
		for(Logger logger : loggers) {
			logger.log(message);
		}
	}
	
}

Bu Utils'i kullanabilmek için CustomerManager içerisinde:

Utils utils = new Utils();
utils.runLoggers(loggers, customer.getFirstName());

şeklinde bir tanımlama yapmamız gerekir.

Utils, bizim sıklıkla kullandığımız, araç görevi görecek olan sınıflarımızdır. Biz, new işlemi yapmak istemeden gerçekleştirmek istiyorsak, Utils içerisindeki void'in hemen önüne static eklememiz yeterlidir.

Artık üstteki runLoggers'ı, direkt sınıfın ismini belirterek çağırmamız yeterli olacaktır:

Utils.runLoggers(loggers, customer.getFirstName());

 

https://halil-sahin.com/interface-nedir/
https://medium.com/codable/interfacelerin-mantigi-nedir-1-hikayeli-f9b960228328
http://yazilimcity.net/java-implements-nedir-ne-ise-yarar-nasil-kullanilir/
https://gokhana.medium.com/dependency-injection-nedir-nas%C4%B1l-uygulan%C4%B1r-kod-%C3%B6rne%C4%9Fiyle-44f4b0d576e4

 

Yorumlar Yorum Yap

Son Yazılar