DESIGN PATTERNS SAGA #20: REAL WORLD SITUATIONS WITH OBSERVER

Do you remember how to use the Swing API with action events? If not, refresh your memory here:

    // main method......
    someComponent.addActionListener(new ActionExample());

public class ActionExample implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        ...//code that reacts to the action...
    }
}

When using the Swing API you also use the Observer pattern maybe even without realizing it. The Observer pattern enables us to decouple the observed actions and isolate each process that must be executed. It’s clear that we will gain flexibility and cohesion.

observer_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

1 – Observer: It’s the generic abstract class that enables us to implement the Observer pattern. We will use the most powerful feature of Object Oriented programming, the Polymorphism. It’s crucial to fully master Polymorphism when using the Design Patterns.

public abstract class Observer {
	protected Subject subject;
	abstract void update();
}

2 – Subject: It orchestrates the necessary actions that must be executed when using the Observers. The Subject class contains the generic methods to be reused at the specific Subject class.

public abstract class Subject {

	private List<Observer> observers = new ArrayList<>();

	abstract void setState(String state);
	abstract String getState();

	public void attach(Observer observer) {
		observers.add(observer);
	}

	public void notifyObservers() {
		for (Observer observer : observers) {
			observer.update();
		}
	}
}

3 – Subject specialization: In this class, we are defining the specific actions to be executed by any Observer class.

public class MessageStream extends Subject {

	private Deque<String> messageHistory = new ArrayDeque<>();

	@Override
	void setState(String message) {
		messageHistory.add(message);
		this.notifyObservers();
	}

	@Override
	String getState() {
		return messageHistory.getLast();
	}
}

4 – Observers specializations: Finally the Observers’ implementations! Basically, to make everything work we add the subject in the Observers‘ constructors and invoke the addMessage method.

public class SlackClient extends Observer {

	public SlackClient(Subject subject) {
		this.subject = subject;
		subject.attach(this);
	}

	public void addMessage(String message) {
		subject.setState(message + " - sent from Slack");
	}

	@Override
	void update() {
		System.out.println("Slack Stream: " + subject.getState());
	}

} 

public class WhatsAppClient extends Observer {

	public WhatsAppClient(Subject subject) {
		this.subject = subject;
		subject.attach(this);
	}

	public void addMessage(String message) {
		subject.setState(message + " - sent from WhatsApp");
	}

	@Override
	void update() {
		System.out.println("WhatsApp Stream: " + subject.getState());
	}
}

5 – Unit Tests: Let’s see how it works. The use of the Observer pattern is pretty easy. Basically, we will instantiate the Subject specialization and pass it into the Observer specialization constructor. Then we will invoke the addMessage method and it’s done!

public class ObserverTest {

    @Test
    public void observerTest() {
        Subject subject = new MessageStream();

        WhatsAppClient whatsAppClient = new WhatsAppClient(subject);
        SlackClient slackClient = new SlackClient(subject);

        slackClient.addMessage("Another new message!");
        Assert.assertEquals("Another new message! " +
           "- sent from Slack", subject.getState());

        whatsAppClient.addMessage("Here is a new message!");
        Assert.assertEquals("Here is a new message! " +
           "- sent from WhatsApp", subject.getState());
    }

}

Summary of actions:

  1. Created the Observer abstract class
  2. Declared the Subject as a field inside the Observer abstract class
  3. Created the Subject abstract class
  4. Created the Subject specialization class
  5. Created the Observer specialization class
  6. Instantiated the Subject specialization class
  7. Created Observer specialization instances
  8. Passed the Subject instance to the Observer constructor
  9. Invoked the addMessage method from the Observers’ specialization

To practice the Observer pattern you can create another Subject or Observer. You could create a FileStreamSubject and InstagramClient, for example. It’s crucial to practice. Create at least one example and practice your programming skills using TDD!

DESIGN PATTERNS SAGA #20: REAL WORLD SITUATIONS WITH OBSERVER

DESIGN PATTERNS SAGA #19: REAL WORLD SITUATIONS WITH PROXY

To make code flexible and easy to maintain we must find a way to encapsulate and not repeat the code. What if we need to do a specific treatment every time we get an Exception? Would we repeat this code in the entire application? We could, but imagine how bad the maintenance would be. It would be much easier to use the power of the Proxy pattern. We can use Reflections in just one place and make our code extremely flexible.

A very simple example of Proxy is, for example, when the company you work for wants to block certain websites. They use Proxy to intercept non-work related sites.

proxy_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

1 – Interface: Nothing special here, it’s just the interface to invoke the Service.

public interface ContractProductService {
	public String contractProduct(Long idProduct);
}

2 – Specific Exception: Exception to be treated in the Proxy class.

public class InvalidProductException extends RuntimeException {

	private static final long serialVersionUID = -5415448783266469523L;

	@Override
	public String getMessage() {
		return "Invalid product.";
	}
}

3 – Service implementation: It’s a simulation of a product contract and a very simple verification to see how we can use the Proxy pattern.

public class ContractProductServiceImpl implements ContractProductService {

	public String contractProduct(Long idProduct) {
		if (idProduct &lt;span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			&gt;&lt;/span&gt;&lt;span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			&gt;&lt;/span&gt;&lt; 0) {
			throw new InvalidProductException();
		}

		return "Product contracted!";
	}

}

4 – Proxy: This is the main class where we intercept the method calls. The first important thing we are doing is the InvocationHandler interface implementation.

There are two crucial methods we use to intercept the methods invocations.

Object newInstance(Object obj): We are using the Proxy class from the Reflection API. When we instantiate any class by this method, it enables us to always intercept the method invocation.

Object invoke(Object proxy, Method m, Object[] args): It’s the method that will intercept the methods invocations when we use the method above. We are manipulating the actions if we get any Exception by any method invocation. We are simply using a JOptionPane to show the message that is thrown by any method invocation.

public class SecurityProxy implements InvocationHandler {

	private Object obj;

	private SecurityProxy(Object obj) {
		this.obj = obj;
	}

	public static Object newInstance(Object obj) {
		return java.lang.reflect.Proxy.newProxyInstance(obj.getClass()
                   .getClassLoader(), obj.getClass().getInterfaces(),
				new SecurityProxy(obj));
	}

	@Override
	public Object invoke(Object proxy, Method m, Object[] args)
             throws Throwable {
		Object result;
		try {
			result = m.invoke(obj, args);
		} catch (InvocationTargetException e) {
			JOptionPane.showMessageDialog(null,
                             e.getTargetException()
			     .getMessage());

			throw e.getTargetException();
		} catch (Exception exception) {
			throw new RuntimeException(exception);
		}
		return result;
	}

}

5 – Unit Tests: Let’s check out the use of the Proxy pattern now.

void proxyInvalidProductTest(): In this test we go through the InvalidProductException path. The first thing to understand is that we are creating the instance from the object by the newInstance method from the SecurityProxy class.

This is crucial because we need to get the instance from the SecurityProxy class to make the Proxy invocation work. Once we get the instance from the newInstance method then every method invocation will be intercepted.

void proxyValidProductTest(): It’s pretty similar to the method above. The method will also be intercepted but the difference is that we are passing a valid id to contract the product.

public class ProxyTest {

	public static final long INVALID_PRODUCT_ID = -1;
	public static final long VALID_PRODUCT_ID = 1;

	@Test(expected=InvalidProductException.class)
	public void proxyInvalidProductTest() {
		ContractProductService service =
                    (ContractProductService)SecurityProxy
		     .newInstance(new ContractProductServiceImpl());

		service.contractProduct(INVALID_PRODUCT_ID);
	}

	@Test
	public void proxyValidProductTest() {
		ContractProductService service =
                      (ContractProductService)SecurityProxy
		       .newInstance(new ContractProductServiceImpl());

		String result = service.contractProduct(VALID_PRODUCT_ID);

		Assert.assertEquals("Product contracted!", result);
	}
}

Summary of actions:

  1. Created a simple Service to intercept the method.
  2. Created the Proxy class.
  3. Created the newInstance method in the Proxy class.
  4. Created the invoke method that does the action in the intercepted methods.
  5. Created the instance from the Service thought the newInstance method.
  6. Intercepted and implemented the actions in the invoke method from the Proxy.

To practice the Proxy pattern you can create another rule in the invoke method or you can create another Service implementation. It’s crucial to practice. Use TDD for this example!

DESIGN PATTERNS SAGA #19: REAL WORLD SITUATIONS WITH PROXY

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

DESIGN PATTERNS SAGA #17: REAL WORLD SITUATIONS WITH DECORATOR

There are some situations in which we need high flexibility. Let’s consider that we want to create a flexible code for mixing a lot of different pizzas. We would not want to write all the possibilities without a pattern, right? For this reason, we want to use the Decorator pattern to gain flexibility, high cohesion, and low coupling.

pizza_decorator.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

1 – Generic interface (Component): It’s the interface with the method that will create all of the objects’ decorations.

public interface Pizza {
	public String make();
}

2 – Decorator: This is the class that makes things happen. It is on the top of all decorator classes and is responsible for decorating the objects.

public abstract class PizzaDecorator implements Pizza {

	protected Pizza customPizza;

	public PizzaDecorator(Pizza customPizza) {
		this.customPizza = customPizza;
	}

	public String make() {
		return customPizza.make();
	}

}

3 – Decorator classes: These are the classes that will decorate the final pizza. Basically, we will decorate the pizza with the toppings we want in a flexible way.

public class TuscanyDecorator extends PizzaDecorator {

	public DressingDecorator(Pizza customPizza) {
		super(customPizza);
	}

	public String make() {
		return customPizza.make() + addTuscany();
	}

	private String addTuscany() {
		return " + Tuscany";
	}

}

public class MozzarellaDecorator extends PizzaDecorator {

	public MozzarellaDecorator(Pizza customPizza) {
		super(customPizza);
	}

	public String make() {
		return customPizza.make() + addMozzarella();
	}

	private String addMozzarella() {
		return " + Mozzarella";
	}
}

4 – Concrete component: This is the base of the pizza (the dough), the component that will generate different kinds of pizzas.

public class SimplePizza implements Pizza {

	@Override
	public String make() {
		return "Base";
	}
}

5 – Unit Tests: It’s test time! Now we will top the pizza in the way we want. We will instantiate the toppings first and then we use the base of the pizza – always passing the object in the constructor of each decorator class. In the end, we invoke the generic make method and the pizza is done!

Also, there is the Java API example with File creation.

public class DecoratorTest {

	@Test
	public void decoratorTest() {
		Pizza pizza = new TuscanyDecorator(
				new MozzarellaDecorator(new SimplePizza()));

		Assert.assertEquals("Base + Mozzarella + Tuscany"
                    , pizza.make());
	}

	@Test
	public void decoratorJavaAPITest() throws IOException {
		File file = new File("./output.txt");
		file.createNewFile();

		OutputStream stream = new FileOutputStream(file);

		DataOutputStream dataStream = new DataOutputStream(stream);
		dataStream.writeChars("text");
		dataStream.close();
		stream.close();

		file.delete();
	}

}

Summary of actions:

  1. Created the generic interface of the Component with the make method.
  2. Created the Component class implementing the generic interface.
  3. Created the Decorator abstract class controlling the decoration.
  4. Created the Decorator concrete classes extending the Decorator.
  5. Decorated the Component joining the classes in the constructor.

To practice the Decorator pattern you can create another Component class, for example, a Sandwich and decorate your Sandwich as you wish. Be sure to use TDD (Test Driven Development).

DESIGN PATTERNS SAGA #17: REAL WORLD SITUATIONS WITH DECORATOR

DESIGN PATTERNS SAGA #16: REAL WORLD SITUATIONS WITH COMPOSITE

Composing objects without a pattern can make code really messy – code repetition happens a lot and maintenance is terrible. Fortunately, there is the Composite pattern that solves this problem completely. Using the Composite pattern we can encapsulate the code in just one place and compose the object more easily.

There are some frameworks that use the Composite pattern, such as JSF. It’s possible to reference all HTML components through the component’s classes from JSF.

This is a simple example of Web components being composed by the Composite pattern.

composite_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

1 – UIComponent generic class: Every web component will inherit UIComponent, so we will be using polymorphism with this abstract class.

There are some necessary methods to enable the composition of objects.

add(UIComponent uiComponent): Adds any component.
remove(UIComponent uiComponent): Removes any component.
toString(): Prints the components code when they are composed.

public abstract class UIComponent {

	List<UIComponent> uiComponents = new ArrayList<>();

	public UIComponent add(UIComponent uiComponent) {
		throw new UnsupportedOperationException
			("Feature not implemented at this level");
	}

	public UIComponent remove(UIComponent uiComponent) {
		throw new UnsupportedOperationException
			("Feature not implemented at this level");
	}

	public abstract String toString();

}

2 – Components classes: These are the classes that will extend UIComponent. Basically, they are the actual components.

Form: It is a component that will be composed by others. As we developers know, the form tag is vastly used in every web application, so we are going to add components inside the Form component.
InputText: We are going add InputText instances in the Form component.
LabelText: We are going to add LabelText instances in the Form component.

public class Form extends UIComponent {

	String name;

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

	@Override
	public UIComponent add(UIComponent uiComponent) {
		uiComponents.add(uiComponent);

		return uiComponent;
	}

	@Override
	public UIComponent remove(UIComponent uiComponent) {
		uiComponents.remove(uiComponent);

		return uiComponent;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder
               ("
<form name='").append(name).append("'>");
		uiComponents.forEach(
                   e -> builder.append("\n").append(e));
		builder.append("\n</form>

");
		return builder.toString();
	}
}

public class InputText extends UIComponent {

	String name;
	String value;

	public InputText(String name, String value) {
		this.name = name;
		this.value = value;
	}

	@Override
	public String toString() {
		return new StringBuilder("<inputText name='")                 .append(name).append("' value='").append(value)                 .append("'/>").toString();
	}
}

public class LabelText extends UIComponent {

	String value;

	public LabelText(String value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return new StringBuilder("<label value='")                                                                           .append(value).append("'/>").toString();
	}
}

3 – Unit Tests: Let’s use the Composite pattern now. We will instantiate and add the other components in the Form class. Then we will confirm if the Components code is correct with the assertion. There is another test with a composition of Maps showing this pattern with Java API.

public class CompositeTest {

	public static final int EXPECTED_MAP_SIZE = 3;

	@Test
	public void compositeTest() {
		Form mainForm = new Form("frmCustomer");

		LabelText lblCustomerName = new LabelText("Customer name:");
		InputText txtCustomerName = new InputText("txtCustomerName",
				"Juggy");

		LabelText lblCustomerProduct = new LabelText("Product:");
		InputText txtCustomerProduct = 
                 new InputText("txtCustomerProduct", "Alienware laptop");

		mainForm.add(lblCustomerName);
		mainForm.add(txtCustomerName);
		mainForm.add(lblCustomerProduct);
		mainForm.add(txtCustomerProduct);

		Assert.assertEquals("<label value='Customer name:'/>",
				lblCustomerName.toString());
		Assert.assertEquals("<inputText name='txtCustomerName'" 				+ " value='Juggy'/>",
				txtCustomerName.toString());
		Assert.assertEquals("<inputText name='txtCustomerProduct'" 				+ " value='Alienware laptop'/>",
				txtCustomerProduct.toString());
		Assert.assertEquals("<label value='Product:'/>",
				lblCustomerProduct.toString());
	}

	@Test
	public void javaAPICompositeTest() {
		Map<String, String> topWebComponents = new HashMap<>();

		topWebComponents.put("Component1", "HTML");
		topWebComponents.put("Component2", "InputText");

		Map<String, String> normalWebComponents = new HashMap<>();

		normalWebComponents.put("Component3", "LabelText");

		Map<String, String> container = new HashMap<>();

		container.putAll(topWebComponents);
		container.putAll(normalWebComponents);

		Assert.assertEquals(EXPECTED_MAP_SIZE, container.size());
	}

}

Summary of actions:

  1. Created the UIComponent generic class.
  2. Created add, remove and toString method inside UIComponent.
  3. Created the objects that will be inside the UIComponent.
  4. Composed the objects and printed the code.

To practice the Composite pattern you can create another Component class and add inside the Form and then print out the code to make the test pass. Be sure to use TDD (Test Driven Development).

DESIGN PATTERNS SAGA #16: REAL WORLD SITUATIONS WITH COMPOSITE

DESIGN PATTERNS SAGA #15: REAL WORLD SITUATIONS WITH STATE

When it’s necessary to maintain State from an object we can create a big code full of ifs controlling the State from the class. Certainly, this is not the right approach to solve this problem. Repetition of code is what we must avoid, we must follow the DRY (Don’t repeat yourself) principle to keep the code flexible and powerful.

state_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

Let’s first see a bad example of a “State” implementation.

1 – State Bad Example: There are two constants, OPEN and CLOSED. Whenever the openWindow or closeWindow methods are invoked all the rules will be manipulated inside them. As you can see in the code below, there is repetition.

public class AutomaticWindow {

	final static int CLOSED = 0;
	final static int OPEN = 1;

	int state = CLOSED;

	public AutomaticWindow() {
		super();
	}

	public void openWindow() {
		if (state == OPEN) {
			System.out.println("Window is already open");
		} else if (state == CLOSED) {
			System.out.println("Opening window.");
			state = OPEN;
		}
	}

	public void closeWindow() {
		if (state == OPEN) {
			System.out.println("Closing window.");
			state = CLOSED;
		} else if (state == CLOSED) {
			System.out.println("Window is already closed.");
		}
	}

	public String toString() {
		if (state == OPEN) {
			return "Window is open";
		} else {
			return "Window is closed";
		}
	}
}

Let’s now see how to use the State pattern for real! You will see the difference of a much cleaner and flexible code.

1 – State: It is the generic abstract class that handles the request from any class that must keep the State.

public abstract class State {

	public abstract void handleRequest();

}

2 – State concrete classes: They are basically the classes that extend the State class. They are responsible for changing the State to the next one in the sequence.

public class GreenTrafficLightState extends State {

	private TrafficLight trafficLight;

	public GreenTrafficLightState(TrafficLight trafficLight) {
		this.trafficLight = trafficLight;
	}

	@Override
	public void handleRequest() {
		System.out.println("Turning traffic light to yellow.");
		trafficLight.setState(trafficLight.getYellowLightState());
	}

	public String toString() {
		return "Traffic light is green.";
	}
}

public class RedTrafficLightState extends State {

	private TrafficLight trafficLight;

	public RedTrafficLightState(TrafficLight trafficLight) {
		this.trafficLight = trafficLight;
	}

	@Override
	public void handleRequest() {
		System.out.println("Turning traffic light to green...");
		trafficLight.setState(trafficLight.getGreenLightState());
	}

	public String toString() {
		return "Traffic light is on red.";
	}
}

public class YellowTrafficLightState extends State {

	private TrafficLight trafficLight;

	public YellowTrafficLightState(TrafficLight trafficLight) {
		this.trafficLight = trafficLight;
	}

	@Override
	public void handleRequest() {
		System.out.println("Turning traffic light to red.");
		trafficLight.setState(trafficLight.getRedLightState());
	}

	public String toString() {
		return "Traffic light is yellow.";
	}
}

3 – Orchestrator: This class is responsible for orchestrating the changes of the traffic lights’ State. In the constructor, we initialize all the States and we pass the same instance in the constructor to each one of the States classes. In the changeState method, we just delegate the call to the State instance variable to change the State.

public class TrafficLight {

	State red;
	State yellow;
	State green;

	State state;

	public TrafficLight() {
		red = new RedTrafficLightState(this);
		yellow = new YellowTrafficLightState(this);
		green = new GreenTrafficLightState(this);

		state = red;
	}

	public void changeState() {
		state.handleRequest();
	}

	public String toString() {
		return state.toString();
	}

	public State getGreenLightState() {
		return green;
	}

	public State getYellowLightState() {
		return yellow;
	}

	public State getRedLightState() {
		return red;
	}

	public void setState(State state) {
		this.state = state;
	}
}

4- Unit Tests: Now let’s see if the states are changing as expected. We are expecting that traffic lights change from red to green, yellow to red and so forth. In the window case, we want it to open and close.

public class StateTest {

	@Test
	public void stateTest() {
		TrafficLight trafficLight = new TrafficLight();

		trafficLight.changeState();

		trafficLight.changeState();

		trafficLight.changeState();

		trafficLight.changeState();

		Assert.assertEquals(trafficLight.state.getClass(),
				GreenTrafficLightState.class);
	}

	@Test
	public void badExampleStateTest() {
		AutomaticWindow automaticWindow = new AutomaticWindow();

		automaticWindow.openWindow();

		automaticWindow.closeWindow();

		Assert.assertEquals(automaticWindow.toString(),
				"Window is closed");
	}

}

Summary of actions:

  1. Created the State abstract generic class.
  2. Created the State classes that extend the State class.
  3. Implemented the handleRequest method from the State class.
  4. Created the TrafficLight class to manipulate the States.
  5. Created the changeState method in the TrafficLight class.

To practice the State Pattern you can create another State class with another scenario, for example changing any light state or anything else. Keep in mind that practicing the Patterns is crucial to fully master them.  Be sure to use TDD (Test Driven Development).

DESIGN PATTERNS SAGA #15: REAL WORLD SITUATIONS WITH STATE

DESIGN PATTERNS SAGA #14: REAL WORLD SITUATIONS WITH VISITOR

Sometimes we need to implement different methods for a POJO with different business requirements. We could certainly create several methods inside the POJO but we would not be utilizing the main benefits of powerful code – cohesion and low coupling. When we want to encapsulate different business requirements inside a cohesive class we can use the Visitor Pattern!

Basically, when using Visitor Pattern we encapsulate the business requirements inside the Visitor classes making our code very flexible.

visitor_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

Let’s see a bad example of code if we aren’t using the Visitor Pattern.

1 – Generic Interface: It’s basically the interface that declares the main method to calculate shipping.

public interface CardDevice {
	public double calculateShipping();
}

2 – Business POJOs: Now we have all the POJOs implementing the Generic interface in order to define the behavior to calculate shipping.

public class Mobile implements CardDevice {
	@Override
	public double calculateShipping() {
		return 6;
	}
}

public class WiredPos implements CardDevice {
	@Override
	public double calculateShipping() {
		return 9;
	}
}

public class WirelessPos implements CardDevice {
	@Override
	public double calculateShipping() {
		return 7;
	}
}

3 – Invoker: Now we can see the problem. We have the code very coupled with the specific calculateShipping method.

public class CardDeviceOrder implements CardDevice {

	private List<CardDevice> cardDevices = new ArrayList<>();

	public CardDeviceOrder() {
		super();
	}

	public void addPart(CardDevice cardDevice) {
		cardDevices.add(cardDevice);
	}

	public List<CardDevice> getCardDevices() {
		return Collections.unmodifiableList(cardDevices);
	}

	public double calculateShipping() {
		double shippingCost = 0;
		for (CardDevice cardDevice : cardDevices) {
			shippingCost += cardDevice.calculateShipping();
		}
		return shippingCost;
	}

}

4 – Unit Test: Let’s see if the calculateShipping method is working:

public class BadExampleVisitorTest {

	public static final double EXPECTED_SHIPPING_COST = 22.0;

	@Test
	public void visitorBadExampleTest() {
		CardDeviceOrder order = new CardDeviceOrder();
		order.addPart(new Mobile());
		order.addPart(new WiredPos());
		order.addPart(new WirelessPos());

		double shippingCost = order.calculateShipping();

		Assert.assertTrue(EXPECTED_SHIPPING_COST == shippingCost);
	}

}

Now let’s see the same example using the Visitor Pattern. Now you will realize that we will have more flexibility in the code.

1 – Visitor interface: We are going to define every business requirement inside this Visitor in order to manipulate these rules in an uncoupled mode. We are going to implement the rules inside the Visitor implementation.

public interface CardDeviceVisitor {
	void visit(WirelessPos wirelessPos);
	void visit(Mobile mobile);
	void visit(WiredPos wiredPos);
	void visit(CardDeviceOrder cardDeviceOrder);
}

2 – Visitor implementations: You will realize that the business requirements are implemented directly in the Visitor classes. They implement the Visitor generic interface and execute what is necessary for the business.

CardDeviceDisplayVisitor: Displays basic device information.
CardDeviceShippingVisitor: Calculates the shipping from each card device.

public class CardDeviceDisplayVisitor implements CardDeviceVisitor {

	@Override
	public void visit(WirelessPos wirelessPos) {
		System.out.println("We have a: " +  wirelessPos);
	}

	@Override
	public void visit(Mobile mobile) {
		System.out.println("We have a: " + mobile);
	}

	@Override
	public void visit(WiredPos wiredPos) {
		System.out.println("We have: " + wiredPos);
	}

	@Override
	public void visit(CardDeviceOrder cardDeviceOrder) {
		System.out.println("We have an: "+ cardDeviceOrder);
	}

}

public class CardDeviceShippingVisitor implements CardDeviceVisitor {

	double shippingValue = 0;

	@Override
	public void visit(WirelessPos wirelessPos) {
		System.out.println("Calculating Wireless Pos shipping.");
		shippingValue += 15;
	}

	@Override
	public void visit(Mobile mobile) {
		System.out.println("Calculating Mobile shipping");
		shippingValue += 3;
	}

	@Override
	public void visit(WiredPos wiredPos) {
		System.out.println("Calculating Wired Pos shipping.");
		shippingValue += 9;
	}

	@Override
	public void visit(CardDeviceOrder order) {
		System.out.println("If they bought more than 3 things "
				+ "there will be a discount in the shipping.");
		List<CardDevice> cardDevices = order.getCardDevices();
		if (cardDevices.size() > 3) {
			shippingValue -= 5;
		}
		System.out.println("Shipping amount is: " + shippingValue);
	}

	public double getShippingValue() {
		return shippingValue;
	}
}

3 – Business POJOs: We can clearly see that the POJOs are already different. They are not invoking the method to execute the specific business requirements. Now we invoke a method from a generic visitor. It decouples the code and the business requirement is manipulated inside the Visitor. Check it out:

public class Mobile implements CardDevice {
	@Override
	public void accept(CardDeviceVisitor visitor) {
		visitor.visit(this);
	}
}

public class WiredPos implements CardDevice {
	@Override
	public void accept(CardDeviceVisitor visitor) {
		visitor.visit(this);
	}
}

public class WirelessPos implements CardDevice {
	@Override
	public void accept(CardDeviceVisitor visitor) {
		visitor.visit(this);
	}
}

4 – Orchestrator, Invoker: The CardDeviceOrder class is responsible for orchestrating the cardDevices classes and invoking every method from the Visitors according to the specific Visitor class implementation.

public class CardDeviceOrder implements CardDevice {

	private List<CardDevice> cardDevices = new ArrayList<>();

	public CardDeviceOrder() {
		super();
	}

	public void addPart(CardDevice cardDevice) {
		cardDevices.add(cardDevice);
	}

	public List<CardDevice> getCardDevices() {
		return Collections.unmodifiableList(cardDevices);
	}

	@Override
	public void accept(CardDeviceVisitor visitor) {
		for (CardDevice cardDevice : cardDevices) {
			cardDevice.accept(visitor);
		}
		visitor.visit(this);
	}
}

5 – Unit Tests: Let’s test our Visitors! You will see the business methods being invoked through the Visitor classes.

First, add all the devices to the list of CardDeviceOrder.
Second, instantiate both visitors and pass them into the accept method from CardDeviceOrder.
Third, confirm the calculated shipping value is correct.

public class GoodExampleVisitorTest {

	public static final double EXPECTED_SHIPPING_COST = 27.0;

	@Test
	public void visitorGoodExampleTest() {
		CardDeviceOrder order = new CardDeviceOrder();
		order.addPart(new WirelessPos());
		order.addPart(new Mobile());
		order.addPart(new WiredPos());

		CardDeviceShippingVisitor shipping
			= new CardDeviceShippingVisitor();

		order.accept(shipping);
		order.accept(new CardDeviceDisplayVisitor());

		Assert.assertTrue(EXPECTED_SHIPPING_COST ==
				shipping.getShippingValue());
	}

}

Summary of actions:

  1. Created the Visitor generic interface.
  2. Implemented the Visitor classes with the necessary business requirements.
  3. Created the business POJOs delegating responsibilities to the Visitor classes.
  4. Created the orchestrator class responsible to manipulate the invocations.

To practice the Visitor Pattern you can create another Visitor class with another specific business requirement, for example calculating the rent from every card device. Create another test method to make sure it works. Be sure to use TDD (Test Driven Development).

DESIGN PATTERNS SAGA #14: REAL WORLD SITUATIONS WITH VISITOR