DESIGN PATTERNS SAGA #18: REAL WORLD SITUATIONS WITH FLYWEIGHT

There are some situations in software development in which we need to improve performance. This is possible with the use of Cache. Imagine a lot of the same objects being created and wasting memory. The Flyweight pattern was created to avoid this problem and optimize performance.

Flyweight_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

1 – POJO: This is the object we will keep in the Cache.

class Product {
	private final String name;

	public Product(String name) {
		this.name = name;
	}

	public String toString() {
		return name;
	}
}

2 – Factory (Cache): Basically this class is responsible to create the caches.

lookup(String productName): It checks if the product is contained in the map. If it is, we will return the product. If not, we will put the product on the map and return the product.

public class Portfolio {
	private Map<String, Product> products = new HashMap<String, Product>();

	/**
	 * Factory method Pattern
	 */
	public Product lookup(String productName) {
		if (!products.containsKey(productName))
			products.put(productName, new Product(productName));
		return products.get(productName);
	}

	public int totalProductsMade() {
		return products.size();
	}
}

3 – Object composer: It just composes the information from the product to execute the order.

public class Order {
	private final int orderNumber;
	private final Product product;

	Order(int orderNumber, Product product) {
		this.orderNumber = orderNumber;
		this.product = product;
	}

	void processOrder() {
		System.out.println("Ordering " + product +
				" for order number " + orderNumber);
	}
}

4 – Executor: Here is where the action happens.

void executeOrder(String productName, int orderNumber): It orchestrates the input in the map. If the product is in the map already, it will return the same object. If not, it will put the new information in the map and return it.

void process(): It will process all the orders and remove every product.

int getTotalProducts(): It will get the total of the registered products.

public class InventorySystem {

	private final Portfolio portfolio = new Portfolio();
	private final List<Order> orders = new CopyOnWriteArrayList<Order>();

	void executeOrder(String productName, int orderNumber) {
		Product product = portfolio.lookup(productName);
		Order order = new Order(orderNumber, product);
		orders.add(order);
	}

	void process() {
		for (Order order : orders) {
			order.processOrder();
			orders.remove(order);
		}
	}

	int getTotalProducts() {
		return portfolio.totalProductsMade();
	}
}

5 – Unit Tests: Let’s see if the cache is working!

public void flyweightTest(): At first we will invoke the executeOrder method from the InventorySystem and process it. When the products are added it automatically removes the duplication. In the end, we check if there are 3 products and the test passes.

public void flyweightJavaApiExampleTest(): There is something curious about Wrappers of Numbers in Java. When we use an Integer between -127 and 128 there is a Cache that maintains those numbers in order to avoid wasted memory.

public class FlyweightTest {

	@Test
	public void flyweightTest() {
		InventorySystem inventory = new InventorySystem();

		inventory.executeOrder("AlienWare laptop", 2500);
		inventory.executeOrder("SkullCandy HeadPhones", 150);
		inventory.executeOrder("Playstation 5", 500);
		inventory.executeOrder("SkullCandy HeadPhones", 130);
		inventory.executeOrder("AlienWare laptop", 3000);
		inventory.executeOrder("Playstation 5", 600);

		inventory.process();

		Assert.assertEquals(3, inventory.getTotalProducts());
	}

	@Test
	public void flyweightJavaApiExampleTest() {
		Integer firstInt = Integer.valueOf(5);

		Integer secondInt = Integer.valueOf(5);

		Integer thirdInt = Integer.valueOf(10);

		Assert.assertTrue(firstInt == secondInt);
		Assert.assertFalse(secondInt == thirdInt);
	}

}

Summary of actions:

  1. Created the POJO to keep in the Cache.
  2. Created the auxiliary classes to make the Flyweight pattern work.
  3. Created the map from the POJO to get rid of duplication.
  4. Map created from the POJO without duplications.

To practice the Flyweight pattern you can create another POJO and your own implementation to avoid duplication. Practice TDD with this example!

 

DESIGN PATTERNS SAGA #18: REAL WORLD SITUATIONS WITH FLYWEIGHT

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s