Fly-Weight Design Pattern

Merhaba, yine creational bir patternden bahsedeceğim. Bir önceki yazıda prototype patterninden bahsetmiştim. Design pattern yazı serisinin bitmesine çok az kaldı yani son birkaç pattern kaldı.

Çok fazla uzatmadan anlatmak gerekirse fly-weight pattern bize ram den tasarruf etmemizi sağlıyor. Nasıl yani dediğinizi duyar gibiyim 🙂 Şöyle ki bir oyun tasarladığınızı düşünün , oyunda bir orman var ve siz bu ormanın içinde yüzlerce ağaç oluşturmak istiyorsunuz. Bu işlemi her bir ağaç için bellekte bir nesne oluşturacak şekilde yaparsanız ram i çok yormuş olursunuz. İşte bu gibi durumlarda fly-weight pattern devreye giriyor.

Bu pattern i sadece eğer programınız , ram e zor uyum sağlayabilecek büyük objectleri desteklemesi gerekiyorsa kullanılır.

package flyweight;

public class Soldier {
	
	protected int x;
	protected int y;
	protected SoldierType type;
	
	public Soldier(int x, int y, SoldierType type) {
		this.x = x;
		this.y = y;
		this.type = type;
	}
	
	public void draw() {
		System.out.println("Soldier object has been drawn");
		System.out.println("Coordinates: "+x +","+ y);
		System.out.println("Rank: "+ type.rank);
		System.out.println("Weapon: "+ type.weapon);
	}
}
package flyweight;

public class SoldierType {
	
	protected String weapon;
	protected String rank;
	
	public SoldierType(String weapon, String rank) {
		this.weapon = weapon;
		this.rank = rank;
	}
}
package flyweight;

import java.util.HashMap;
import java.util.Map;

public class SoldierFactory {
	
	private static Map<String,SoldierType> soldierTypes = new HashMap<>();
	
	public static SoldierType getSoldierExtrinsics(String weapon,String rank) {
		
		SoldierType type = soldierTypes.get(rank);
		if(type ==null) {
			type = new SoldierType(weapon, rank);
			soldierTypes.put(rank, type);
		}
		return type;
	}

}
package flyweight;

import java.util.ArrayList;

public class Army {
	
	protected ArrayList<Soldier> soldiers = new ArrayList<Soldier>();
	
	public void addSoldier(int x, int y,String weapon,String rank) {
		 SoldierType ex = SoldierFactory.getSoldierExtrinsics(weapon, rank);
		 Soldier soldier = new Soldier(x,y,ex);
		 soldiers.add(soldier);
	}
}
package flyweight;

public class Test {

	static String[] weapons = { "AK-47", "Maverick", "Gut Knife", "Desert Eagle" };

	public static void main(String[] args) {

		int soldierSize = 100;
		int soldierType = 3;

		Army army = new Army();

		for (int i = 0; i < Math.floor(soldierSize / soldierType); i++) {
			army.addSoldier(getRandom(), getRandom(), getRandomWeapon(), "Sergeant");
			army.addSoldier(getRandom(), getRandom(), getRandomWeapon(), "Corporal");
			army.addSoldier(getRandom(), getRandom(), getRandomWeapon(), "Specialist");
		}
		
		for (Soldier s : army.soldiers) {
			System.out.println("--------------");
			s.draw();
		}
	}

	public static int getRandom() {
		return (int) Math.floor(Math.random() * 100);
	}

	public static String getRandomWeapon() {
		int random = (int) Math.floor(Math.random() * weapons.length);
		return weapons[random];
	}

}

Bu pattern de bilinmesi gereken iki kavram var.

Extrinsic

Diğer bir değişle unique state yada mutable(değiştirilebilir).

Intrinsic

Repeating state yani inmutable.

Yukardaki örnekte ise soldier nesnesinin özelliklerini 2 classa böldüm. Birinde koordinatlar var , diğerinde ise repeating eden şeyler var. Örnekte rank özelliğine göre ölçütlendirme yapıyor. Çıktılar aşağıdaki gibidir.