Java Günlüğüm
Yazılım, Java, BT, azıcık felsefe, biraz mizah...
  • Udemy Eğitimleri
  • Temiz Kod
  • Tasarım Kalıpları
  • Hakkımda
  • Arşiv
RSS
22 Nisan 2015

Tasarım Kalıpları: Prototype (Prototip ya da Örnek Nesne)

Akin Kategorisiz

GoF’un nesne yaratmayla ilgili 5 kalıbından bir diğeri de Prototype’dır. Dilimize “prototip” ya da “örnek nesne” olarak çevrilebilecek olan bu kalıbın amacıyla ilgili GoF’da şu bilgiler bulunmaktadır:

Intent: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying prototype.

Amaç: Prototip bir nesneyi kullanarak yaratılacak nesneleri belirlemek ve yeni nesneleri prototipi kopyalayarak oluşturmak.

Anlaşılması son derece kolay ve tabi olan bu kalıbı özellikle karmaşık ve durumları arasında az farklar olan nesneleri yaratmada başarıyla kullanabiliriz.

Uygulamalarda sıklıkla iş sınıflarından nesneler oluştururuz. Bu nesneler zaman zaman ciddi karmaşıklıkta olurlar. Aynı tipten olan nesneleri sıklıkla farklı durumlarla yaratmak isteriz: UnAuthenticatedUser ve AuthenticatedUser gibi.

Bazen karmaşık bir nesneyi yaratıp, o nesneyi kopyalayarak yeni nesneler yaratabiliriz. Kopyalanan nesne prototip nesnedir. Bazen de karmaşık bir nesneyi, farklı durumlarla yaratmak isteriz. Yani nesnenin ilk yaratıldığında alacağı farklı durumlar ise birbirlerinden türetilebilir.

Çözüm olarak diğer nesnelerin yaratılabilmesi için oluşturulan örnek nesne ya da prototipten başlayabiliriz. Yani prototip olarak oluşturulan bir nesne, aynı türden diğer nesnelerin yaratılması için bir başlangıç noktasıdır. Dolayısıyla, yeni nesneler oluşturmak, için var olan prototipi kopyalarız (cloning). Muhtemelen prototype ile diğer nesneler arasında durum farklılıkları vardır. İstenirse bu farklı durumlar tek bir prototipten üretilen nesne üzerinde, gerekli setter metotları çağrılarak oluşturulur. İstenirse de farklı durumlar için farklı prototipler üretilir.

Örneğin aşağıdaki gibi örnek amacıyla yapılmış olduğundan basit yapıyı ele alalım.

ClassDiagram1

Örnek kodlar da aşağıdaki gibi olacaktır.

package org.javaturk.dp.pattern.gof.creational.prototype.simple;

public abstract class Customer implements Cloneable {
	protected int id;
	protected String address;
	protected String phone;
	boolean authenticated;

	public Customer(int id, String address, String phone) {
		this.id = id;
		this.address = address;
		this.phone = phone;
		authenticated = false;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public boolean isAuthenticated() {
		return authenticated;
	}

	public void setAuthenticated(boolean authenticated) {
		this.authenticated = authenticated;
	}
	
	@Override
	public String toString() {
		return "Customer [id=" + id + ", address=" + address + ", phone="
				+ phone + ", authenticated=" + authenticated + "]";
	}

	@Override
	public Customer clone() {
		Customer customer = null;
		try {
			customer = (Customer) super.clone();
		} catch (CloneNotSupportedException e) {
			System.out.println("Problem when cloning the object: " + e.getMessage());
			e.printStackTrace();
		}
		return customer;
	}
}

Görüldüğü gibi nesnenin “clone()” metodu override edilmiştir.

Benzer şekilde yapıdaki diğer iki nesne de şöyledir:

package org.javaturk.dp.pattern.gof.creational.prototype.simple;

import java.util.Date;

public class IndividualCustomer extends Customer{
	private String firstName;
	private String lastName;
	private Date dob;
	
	public IndividualCustomer(int id, String address, String phone,
			String firstName, String lastName, Date dob) {
		super(id, address, phone);
		this.firstName = firstName;
		this.lastName = lastName;
		this.dob = dob;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public Date getDob() {
		return dob;
	}

	public void setDob(Date dob) {
		this.dob = dob;
	}

	@Override
	public String toString() {
		return "IndividualCustomer [firstName=" + firstName + ", lastName="
				+ lastName + ", dob=" + dob + ", id=" + id + ", address="
				+ address + ", phone=" + phone + ", authenticated="
				+ authenticated + "]";
	}
}
package org.javaturk.dp.pattern.gof.creational.prototype.simple;


public class CorporateCustomer extends Customer {

	private String corporateName;
	private double discount;

	public CorporateCustomer(int id, String address, String phone,
			String corporateName, double discount) {
		super(id, address, phone);
		this.corporateName = corporateName;
		this.discount = discount;
	}

	public String getCorporateName() {
		return corporateName;
	}

	public void setCorporateName(String corporateName) {
		this.corporateName = corporateName;
	}

	public double getDiscount() {
		return discount;
	}

	public void setDiscount(double discount) {
		this.discount = discount;
	}

	@Override
	public String toString() {
		return "CorporateCustomer [corporateName=" + corporateName
				+ ", discount=" + discount + ", id=" + id + ", address="
				+ address + ", phone=" + phone + ", authenticated="
				+ authenticated + "]";
	}
}


Bu durumda client kodumuz da basitçe şöyle olacaktır:

package org.javaturk.dp.pattern.gof.creational.prototype.simple;

import java.util.Date;

public class Test {

	public static void main(String[] args) {
		IndividualCustomer unAuthenticatedCoskunCustomerPrototype = new IndividualCustomer(1,
				"Cumhuriyet Cad. No 28 Beşiktaş Istanbul", "2128399041",
				"Selim", "Coskun", new Date());
		System.out.println(unAuthenticatedCoskunCustomerPrototype);
		
		
		IndividualCustomer authenticatedAhmetCoskun = (IndividualCustomer) unAuthenticatedCoskunCustomerPrototype.clone();
		authenticatedAhmetCoskun.setId(2);
		authenticatedAhmetCoskun.setFirstName("Ahmet");
		authenticatedAhmetCoskun.setAuthenticated(true);
		System.out.println(authenticatedAhmetCoskun);
		
		
		CorporateCustomer unAuthenticatedGECustomerPrototype = new CorporateCustomer(100, "Manolya Cad. No 5 Sariyer Istanbul", "2124199047", "GE", 0.25);
		System.out.println(unAuthenticatedGECustomerPrototype);

	}
}
Bu basit uygulamadan da görüldüğü gibi, karmaşık nesneler, bir örnek nesneden clonelanarak oluşturulup,  gerekirse olması gereken duruma getirilebilir.

Okuyuculara ödev olarak aşağıdaki durumu verebiliriz:

	public JTUser execute(RegistrationForm form, 
          HttpServletRequest request, Locale locale) throws JTException {

		String uid = utils.generateUUID();
		String salt = utils.generateSalt(32);
		String accountId = utils.generateUUID();

		JTUser user = new JTUser(
				form.getEmail().trim(), null, true, true, true, true,
				AuthorityUtils.NO_AUTHORITIES, // spring security fields
				uid, formorm.getEmail().trim(), salt, form.getName().trim(),
				form.getSurname().trim(), null, accountId, true,
				true, form.getWelcomeMessage().trim(), true,
				new Date(), null);

		user.setStatus(JTConstants.PENDING);

		String servletPath = request.getServletPath();
		if (executeInner(form, locale, user)) {
		     auditLogDao.insert(new AuditLog(user.getUid(), user.getUsername(),
					utils.getRemoteIp(), utils.getSid(),
					AuditType.REGISTRATION, AuditSubtype.PENDING,
					ResponseCode.SUCCESS, new Date(), null));

		     authenticateFastRegisterUser(form, request);
		}

		return user;

Yukarıdaki kodu prototype kalıbıyla nasıl iyileştirebiliriz? Kodda JTUser oluşturulurken pek çok boolean parametre geçildiği görülüyor. Muhtemelen sistemde farklı JTUser nesneleri farklı boolean değerlerle oluşturuluyor. Bu durumda prototype kalıbı kullanışlı görünüyor.

Benzer durum AuditLog nesnesi için de geçerli midir?

Prototype kalıbının artısı, Factory ya da Abstract Factory kalıplarında var olan miras mekanizmasını kullanmamasıdır. Çünkü yeni nesneler sadece var olan prototipten üretilirler, ama factorylerde her nesne için ayrı bir üretici sınıf vardır. Bu yüzden derin factory hiyerarşisinden kaçmak için Prototype kalıbını kullanabilirsiniz.

Factory Method ve Abstract Factory nesne oluştururken Prototype kalıbını kullanabilir. Prototype, Composite ve Decorator kalıplarında sıklıkla kullanılır.

Toplam görüntülenme sayısı: 2817

7 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
22 Nisan 2015

Java EE Programlama Eğitiminin İlk Dersinin Videosu

Akin Eğitim ve Seminer

Arkadaşlar, bu hafta başladığımız “Java EE Programlama” eğitiminin ilk dersinin videosunu Youtube’da paylaştım. Buradan da izleyebilirsiniz.

http://www.youtube.com/embed?listType=playlist&list=UUgKObzoknvY3t-XR_8jlk8g

Keyifli seyirler.

Toplam görüntülenme sayısı: 887

6 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
20 Nisan 2015

Tasarım Kalıpları: Abstract Factory Kalıbı (Soyut Üretici)

Akin Java, Tasarım Kalıpları, Yazılım Modelleme

Nesne yaratma kalıplarından bir diğeri de Abstract Factory’dir. Soyut üretici olarak da dilimize çevrilebilecek olan bu kalıbın amacıyla ilgili GoF’da şu bilgiler bulunmaktadır:

Intent:  Provide an interface for creating families of related or dependent objects without specifying their concrete classes. Factory Method lets a class defer instantiation to subclasses.

Amaç: Birbirleriyle ilgili ya da bağımlı nesne ailelerini, nesnelerin somut sınıflarını belirtmeden yaratmak için bir arayüz sağlamak. Factory Method bir sınıfın nesnesinin yaratılmasını, alt sınıflara ertelemesine izin verir.

Factory Method ile Abstract Factory kalıpları genelde karıştırılır. Factory Method tek nesne, Abstract Factory ise tek nesne yerine, nesne ailesi oluşturmak üzere kullanılan bir kalıptır. Abstract Factory bir sınıftır, Factory Method ise bir metottur. Abstract Factory, birden fazla Factory Method kullanarak oluşturulabilir. Abstract Factory, genelde birbirleriyle ilgili nesne ailelerini ya da gruplarını oluşturmakta kullanılır. Dolayısıyla Abstract Factory üzerinde ailenin her ferdi için ayrı bir Factory Method bulunur.

Yukarıdaki modeldeki kod örneklerine bakarsak, Component arayüzü aşağıdaki gibidir:

package org.javaturk.dp.pattern.gof.creational.abstractFactory.gui;

public interface Component {
	public void paint();
}

Bileşenlerden olan Button sınıfı ise abstract olup aşağıdaki gibidir:

package org.javaturk.dp.pattern.gof.creational.abstractFactory.gui;

public abstract class Button implements Component{
    public abstract void paint();
}

Button‘un bir alt sınıfı olan OSXButton ise şöyledir:

package org.javaturk.dp.pattern.gof.creational.abstractFactory.gui;

public class OSXButton extends Button {
    public void paint() {
        System.out.println("Painting an OSX Button!");
    }
}

Diğer tarafta ise AbstractFactory’nin sınıfları bulunur. İlki bir arayüz olan GUIFactory‘dir:

package org.javaturk.dp.pattern.gof.creational.abstractFactory.gui;

interface GUIFactory {
    public Component createButton();
    
    public Component createList();
    
    public Component createTable();
}

GUIFactory‘nin bir gerçekleştirmesi ise OSXFactory’dir.

package org.javaturk.dp.pattern.gof.creational.abstractFactory.gui;

public class OSXFactory implements GUIFactory {

    public Button createButton() {
        return new OSXButton();
    }

	@Override
	public List createList() {
		return new OSXList();
	}

	@Override
	public Table createTable() {
		return new OSXTable();
	}
}

Bu durumda Client kodumuz da şöyle olacaktır:

package org.javaturk.dp.pattern.gof.creational.abstractFactory.gui;

class Client {
    public Client(GUIFactory factory){
        Component button = factory.createButton();
        button.paint();
        
        Component list = factory.createList();
        list.paint();
        
        Component table = factory.createTable();
        table.paint();
    }
}

Abstract Factory kalıbı, ürün aileleri ve onları üreten nesnelerle ilgili sistematik bir isimlendirme sağlar. Sisteme yeni bir nesnenin (ScrollBar) katılması durumunda hem Abstract Factory’e hem de alt sınıf olan üreticilerine (OSXFactory ve WinFactory) gerekli factory metotlarının (createScrollBar()) eklenmesi gereklidir. Yeni bir aile (XWindows) eklenmesi durumunda ise her nesnenin o aileye ait alt sınıfı (XWindowsButton, …) ile üretici alt sınıfının (XWindowsFactory) sisteme eklenmesi gereklidir.

Java APIlerinde pek çok Abstract Factory kullanımı vardır:

  • javax.xml.parsers.DocumentBuilderFactory newDocumentBuilder()
  • javax.xml.transform.TransformerFactory newTransformer()
  • javax.xml.xpath.XPathFactory newInstance()

Abstract Factory, Factory Method’u sıklıkla kullanılır. Factory Method bir metot iken, Abstract Factory bir sınıftır. Dolayısıyla Abstract Factory bir üst soyutlama yapısı sağlar. Factory Method bir nesne için bir yaratma yöntemi sağlarken, Abstract Factory bir nesne için birden fazla yaratma yöntemi sağlar. 

Ayrıca Abstract Factory, Factory Method yanında Builder ve Prototype da kullanılır.

Toplam görüntülenme sayısı: 2849

7 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
20 Nisan 2015

Tasarım Kalıpları: Adapter Kalıbı

Akin Tasarım Kalıpları

Adapter, dilimize adaptör olarak geçmiş olan kavramdır ve GoF’un yapısal kalıplarındandır. GoF’da bu kalıbın amacı şöyle fiade ediliyor:

Intent: Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.

Amaç: Bir sınıfın arayüzünü, bir başka sınıfın beklediği arayüze çevir. Adaptör, uyumsuz arayüzleri sebebiyle çalışamayacak sınıfların bir arada çalışmalarını sağlar.

Adaptör, yapısal kalıpların en basitidir. Sıklıkla, farklı yapılarda geliştirilmiş sınıfları bir arada kullanmak isteriz. Sınıfların farklı yapıda olmaları, kullanım açısından bakıldığında temelde farklı arayüze sahip olmaları anlamına gelir. Farklı arayüze sahip sınıfları, ortak bir arayüz noktasında birleştirmek için adaptörler kullanılır. Bu anlamda adaptör kullanımı her türlü mühendislik disiplininde ve günlük hayatta sıklıkla başvurduğumuz yöntemlerdendir.

Örneğin bir arayüz geliştirip ona bir kaç alt sınıfta gerçekleştirmeler sağladınız. Sonra bir başka yerden farklı bir gerçekleştirme daha buldunuz ve onu da bu arayüzün altında kullanmak istiyorsunuz. Yapacağınız şey, arayüzünüz ile yeni sınıf arasına bir adaptör koymaktır. Bu durumu bir örnekle ele alalım:  Diyelim ki ABD’ye bir düreliğine gidiyorsunuz ve orada satın almak istemediğiniz traş makinası gibi size özel bir elektrikli aleti de yanınızda götürüyorsunuz. Bu durumda elektrikle ilgili bir uyumsuzluk yaşayacaksınız. Bu hal aşağıda modellenmiştir. Bu durumda Türk elektrikli ev aletlerini ABD’de nasıl çalıştırırız?

Bu durumu çözmenin yöntemi, PowerSource arayüzünü gerçekleştiren ama aynı zamanda USPowerSource ile de konuşabilen bir adaptör yaratmaktır: USTurkishPowerAdapter Bu durumda TurkishHomeAppliance nesneleri USTurkishPowerAdapter üzerinden USPowerSource kullanarak çalışabileceklerdir. Bu durumda şöyle bir modele ulaşırız.

ClassDiagram2

Örnek olarak USTurkishPowerAdapter adaptörü koduna da bakabiliriz.

package org.javaturk.dp.pattern.gof.structural.adapter.electricity.powerAdapter;

import org.javaturk.dp.pattern.gof.structural.adapter.electricity.PowerSource;
import org.javaturk.dp.pattern.gof.structural.adapter.electricity.us.USPowerSource;

public class USTurkishPowerAdapter implements PowerSource {
	private USPowerSource usPowerSource;
	
	public USTurkishPowerAdapter(USPowerSource usPowerSource){
		this.usPowerSource = usPowerSource;
		convert110To220(usPowerSource);
	}

	@Override
	public void providePowerAt220V() {
		usPowerSource.providePowerAt110V();
	}

	@Override
	public void turnOn() {
		usPowerSource.pushSwitch();
	}

	@Override
	public void turnOff() {
		usPowerSource.pushSwitch();
	}
	
	private void convert110To220(USPowerSource usPowerSource){
		System.out.println("USTurkishPowerAdapter: Converting from USPowerSource to provide 220V");
		// Do something here so that we can change USPowerSource :)
	}
}

Bazen adaptörler, uyumsuz nesneyi uyumlu hale getirmekten daha çok iş yapabilirler. Bu gibi durumlarda adaptör, uyumsuz nesneye gitmeden kendisi bazı hizmetler sağlayabilir. Örneğin USTurkishPowerAdapter adaptörü güvenlik amacıyla gücü TurkishHomeAppliance nesnesine iletmeden önce algıladı güç ile ilgili voltaj ve frekans gibi bilgileri gösterebilir. Bu anlamda adaptörün ne kadar iş yaptığı tamamen uyumsuzluğun büyüklüğüyle alakalıdır.

Peki size bir soru: USHomeApplicance nesnesini Türkiye’de nasıl çalıştırabiliriz? USTurkishPowerAdapter nesnesini nasıl değiştirelim ki iki yönlü adaptör görevi görsün ve USHomeApplicance nesneleri de TurkishPowerSource ile çalışabilsin?

Adaptör kalıbı, işimize yarayacak ama istediğimiz arayüze sahip olmayan nesnenin kullanılabilir hale getirir. Bunu da istediğimiz arayüze sahip olmayan nesnenin arayüzünü değiştirerek yapar. Artık o nesnenin yeni arayüzü adaptör nesnesi tarafından belirlenir. Adaptör bu anlamda uyumsuz nesnenin wrapperı olmuştur.

Toplam görüntülenme sayısı: 4194

10 Bunu beğendim 🙂
Tweet
Follow me
Tweet to @kaldiroglu
«< 16 17 18 19 20 >»

Günlüğüme Hoşgeldiniz

Bu günlükte, Yazılım Mühendisliği, Bilgi Teknolojileri, Java, kişisel gelişim ve zaman zaman da diğer konulardaki düşüncelerimi sizlerle paylaşacağım. Umarım beğenir ve hoşça vakit geçirirsiniz.

Her türlü düşüncenizi, yorum olsun, beğeni ya da eleştiri olsun, bana iletmenizi rica ediyorum sizden. Ayrıca bana akin@javaturk.org adresinden ya da Twitter'dan ulaşabilirsiniz. Videolarıma da buradan ulaşabilirsiniz.

Teşekkür ederim.

Akın Kaldıroğlu

Rahat Okumak İçin

A Decrease font size. A Reset font size. A Increase font size.

Sosyal Medya

  • Twitter
  • Facebook
  • LinkedIn
  • Youtube

Son Twitlerim

→ Takip Etmek İçin

Abone Olun

Emalinizi girerek yazılardan haberdar olun.
Loading

Son Yazılarım

  • Udemy Eğitimlerim Üzerine
  • (başlıksız)
  • Clean Code / Temiz Kod Eğitimi Udemy’de
  • Java ile Nesne-Merkezli Programlamaya Giriş Eğitimi Udemy’de
  • Selsoft Video Eğitimleri
  • Spring ile Kurumsal Yazılım Geliştirme
  • Corona Günlerinde Design Patterns
  • Corona Günlerinde Java
  • JDK 10 ve “var” Özelliği
  • Onur Özcan
  • Analist ve İş Bilgisi
  • Farklı Dillerin Bakış Açısıyla Nesne-Merkezli Programlama
  • Java Nedir?
  • Bilgi Teknolojilerinde Yetenek Yönetimi – II: Tanımlar ve Eleştiriler – I
  • Alelade Hikayeler – II: Bir Başka Performans Problemi

Popüler Yazılar ve Sayfalar

  • Java’ya Nasıl Başlarım? Java’yı Nasıl Öğrenirim? – I
  • Nasıl Yazılımcı Olalım? – II: Hangi Bölümü Okuyalım?
  • Oracle’ın Java SE Sertifikaları: OCA, OCP ve OCM
  • Java Kurulumu ve İlk Programımız
  • İş Analisti İş Tanımı
  • Java Tutorial ya da Kendi Kendine Java Öğren
  • Nasıl Yazılımcı Olalım? – I: Üniversiteli mi Alaylı mı?
  • Tasarım Kalıpları
  • Java’ya Nasıl Başlarım? Java’yı Nasıl Öğrenirim?
  • UML Nedir?

Yazı Kategorileri

Yazı Takvimi

Haziran 2025
P S Ç P C C P
 1
2345678
9101112131415
16171819202122
23242526272829
30  
« May    

Yazı Arşivi

Blogroll

  • Binnur Kurt'un Günlüğü
  • Ender'in Java Blogu
  • Erdem Seherler
  • Kızımın Günlüğü
  • Kurumsal Java
  • Levent Karagöl
  • Levent'in Java Blogu
  • Mert Can Akkan’s java tips,options, news…
  • Yaşar Safkan
  • Yasin Saygılı
  • Yazı Dünyası

Yazı Etiketleri

analiz Bilmek C Desen design pattern EJB Eğitim Fortran Hibernate Java Java'ya nasil baslarim Java dersleri Java EE Java Persistence API Java SE Java Sertifika Java Öğren Java öğreniyorum Java öğrenmek JPA Kalıp Kurumsal Java nesne nesne-merkezli No Silver Bullet object object-oriented Oracle Java Certifications pattern performans programlama programlama dilleri programlama nedir sertifika singleton tasarım tasarım deseni tasarım desenleri tasarım şablonu yazılım yazılım geliştirme Yazılım Mühendisliği yazılımın doğası yazılımın zorlukları Şablon

↑

© Java Günlüğüm 2025
Powered by WordPress • Themify WordPress Themes
 

Yorumlar Yükleniyor...