Monday, June 20, 2022

Design Pattern: Observer Pattern

Chapters

Observer Pattern

Observer pattern is a design pattern that consists of observers and a subject. Subject is an entity that is being observed by observers. Observer is an entity that observes the Subject. Most event handling systems implement observer pattern.

This example demonstrates observer pattern.
import java.util.ArrayList;

public class ClientCode{

  public static void main(String[] args){
    Subject playerOne = new Controller("Player One");
    Subject playerTwo = new Controller("Player Two");
    Subject.Observer input = new InputManager();
    
    playerOne.addObserver(input);
    playerTwo.addObserver(input);
    
    playerOne.moveUp();
    playerTwo.moveDown();
  }
}

abstract class Subject{
  private String name;
  private ArrayList<Observer> obsList = 
  new ArrayList<>();
  
  Subject(String name){
    this.name = name;
  }
  
  public void addObserver(Observer obs){
    obsList.add(obs);
  }
  
  public void removeObserver(Observer obs){
    obsList.remove(obs);
  }
  
  private void notifyObservers(String name, String event){
    obsList.
    stream().
    forEach(obs -> obs.update(name, event));
  }
  
  public static abstract class Observer{

    protected abstract void update(String name, String event);
  }
  
  public void moveUp(){
    notifyObservers(name, "up");
  }
  
  public void moveDown(){
    notifyObservers(name, "down");
  }
  
}

class Controller extends Subject{
  
  Controller(String name){
    super(name);
  }
}

class InputManager extends Subject.Observer{
  
  @Override
  protected void update(String name, String event){
    System.out.println
    (name + " pressed " + event + " button.");
    System.out.println
    ("InputManager updates the monitor screen and"+ 
    " moves its character " + event + ".");
  }
}

Result
Player One pressed up button.
InputManager updates the monitor screen and moves its character up.
Player Two pressed down button.
InputManager updates the monitor screen and moves its character down.
In the example above, observer and subject are still tightly coupled. The observer design above is alright but if you want to decouple the two further, you may wanna use publish-subscribe pattern where publishers are subjects and subscribers are observers.

Unlike in the example above, publish-subscribe pattern doesn't send a message directly to observers. It instead sends the message to an entity and that entity sends the message to observers. In java, Flow API implements publish-subscribe pattern. I discussed the API in this article.

If your observers are being notified in quick succession, you may want to implement a timer in order to improve the performance of your application. One example that this scenario may happen is redrawing a GUI window. Everytime we redraw the window on our screen, observers that observe the redrawing process will be notified.

Friday, June 17, 2022

Design Pattern: Memento Pattern

Chapters

Memento Pattern

Memento pattern is a design pattern that exposes the private internal state of an object. One example of how this can be used is to restore an object to its previous state (undo via rollback), another is versioning, another is custom serialization.

This pattern consists of three parts: Originator, Caretaker and Memento. Originator is an object with an internal state. Caretaker is an object that retrieves states from the originator and handles them. Memento is an object that contains a state of Originator. Take note that when implementing this pattern, the Originator must be the only one that can retrieve the state in a Memento.

This diagram shows how to implement a memento pattern Diagram
Courtesy of Wikipedia

This example demonstrates memento pattern.
import java.util.ArrayDeque;

public class ClientCode{

  public static void main(String[] args){
    Caretaker stateManager = 
    new Caretaker("A");
    
    System.out.println("State: " + 
    stateManager.getValue());
    stateManager.saveState();
    
    stateManager.append("B");
    stateManager.saveState();
    System.out.println("State: " + 
    stateManager.getValue());
    
    stateManager.append("C");
    stateManager.saveState();
    System.out.println("State: " + 
    stateManager.getValue());
    System.out.println();
    
    System.out.println("Undo...");
    stateManager.loadState();
    System.out.println("State: " + 
    stateManager.getValue());
    
    stateManager.loadState();
    System.out.println("State: " + 
    stateManager.getValue());
    
    stateManager.loadState();
    System.out.println("State: " + 
    stateManager.getValue());
  }
}

//Originator can have other members
//that is not part of the state of
//this class
class Originator{
  private StringBuilder state;
  
  Originator(String value){
    state = new StringBuilder(value);
  }
  
  void append(String value){
    state.append(value);
  }
  
  String getValue(){
    return state.toString();
  }
  
  Memento saveState(){
    return new Memento(
    new StringBuilder(state.toString()));
  }
  
  void loadState(Memento memento){
    state = memento.getSavedState();
  }
  
  public static class Memento{
  private final StringBuilder savedState;
    
    Memento(StringBuilder state){
      savedState = state;
    }
    
    //Making this private ensures that
    //only the Originater can retrieve
    //the state in a memento
    private StringBuilder getSavedState(){
      return savedState;
    }
  }
  
}

class Caretaker{
  private Originator originator;
  private ArrayDeque<Originator.Memento> states;
  
  public Caretaker(String value){
    originator = new Originator(value);
    states = new ArrayDeque<>();
  }
  
  public void append(String value){
    originator.append(value);
  }
  
  public String getValue(){
    return originator.getValue();
  }
  
  public void saveState(){
    states.addFirst(originator.saveState());
  }
  
  public void loadState(){
    if(states.isEmpty()){
      System.out.println("No states!");
      return;
    }
    originator.loadState(states.removeFirst());
  }
  
}

Result
State: A
State: AB
State: ABC

Undo...
State: ABC
State: AB
State: A

Thursday, June 16, 2022

Design Pattern: Mediator Pattern

Chapters

Mediator Pattern

Mediator Pattern is a design pattern that encapsulates interactions between objects. This pattern promotes loose coupling between objects and their interactions. Thus, making our code more flexible and maintainable.

This example demonstrates mediator pattern.
public class ClientCode{

  public static void main(String[] args){
    BookShelf bookShelf1 = 
    new RoomBookShelf(new String[]{"1", "2", "3"});
    BookShelf bookShelf2 = 
    new RoomBookShelf(new String[]{"A", "B", "C"});
    
    Mediator mediator = 
    new BookShelfInteractions(bookShelf1, bookShelf2);
    
    System.out.println("Shelf1: " + bookShelf1.getBook(0));
    System.out.println("Shelf2: " + bookShelf2.getBook(2));
    mediator.swapBooks("1", "C");
    System.out.println("After Swap...");
    System.out.println("Shelf1: " + bookShelf1.getBook(0));
    System.out.println("Shelf2: " + bookShelf2.getBook(2));
  }
}

/*
Assume classes below are in different package
*/

interface Mediator{
  void swapBooks(String bookInShelf, 
                 String bookInAnotherShelf);
}

class BookShelfInteractions implements Mediator{
  private BookShelf bookShelf1, bookShelf2;
  
  BookShelfInteractions(BookShelf bookShelf1,
                        BookShelf bookShelf2){
    this.bookShelf1 = bookShelf1;
    this.bookShelf2 = bookShelf2;
  }
  
  @Override
  public void swapBooks(String bookInShelf1, 
                        String bookInShelf2){
    boolean bookIsInShelf1 = false;
    boolean bookIsInShelf2 = false;
    
    String[] shelf1 = 
    bookShelf1.getBookShelf();
    String[] shelf2 = 
    bookShelf2.getBookShelf();
    
    int bookShelf1Index = 0;
    int bookShelf2Index = 0;
    for(int i = 0; i < shelf1.length; i++)
      if(shelf1[i].equals(bookInShelf1)){
        bookIsInShelf1 = true;
        bookShelf1Index = i;
        break;
      }
    if(!bookIsInShelf1){
      System.out.println
      ("Book " + bookInShelf1 + 
       "Doesn't exist!");
       return;
    }
    
    for(int i = 0; i < shelf2.length; i++)
      if(shelf2[i].equals(bookInShelf2)){
        bookIsInShelf2 = true;
        bookShelf2Index = i;
        break;
      }
    if(!bookIsInShelf2){
      System.out.println
      ("Book " + bookInShelf2 + 
       "Doesn't exist!");
       return;
    }
    
    String tempShelf = shelf2[bookShelf2Index];
    shelf2[bookShelf2Index] = 
    shelf1[bookShelf1Index];
    shelf1[bookShelf1Index] = tempShelf;
    System.out.println("Books have been swapped!");
  }
  
}

abstract class BookShelf{
  private String[] books;
  
  BookShelf(String[] books){
    this.books = books;
  }
  
  public String getBook(int index){
    if(index < 0 || index >= books.length)
      throw new ArrayIndexOutOfBoundsException();
    
    return books[index];
  }
  
  String[] getBookShelf(){
    return books;
  }
}

class RoomBookShelf extends BookShelf{
  
  RoomBookShelf(String[] books){
    super(books);
  }
  
}

Result
Shelf1: 1
Shelf2: C
Books have been swapped!
After Swap...
Shelf1: C
Shelf2: 1

Wednesday, June 15, 2022

Design Pattern: Iterator Pattern

Chapters

Iterator Pattern

Iterator pattern is a design pattern used to access and traverse a collection such as a list. This pattern decouples algorithms from containers.

Some programming languages have built-in iterator in them. Those built-in and general-purpose iterators are can solve most problems and I recommend using them. For example, java provides Iterator interface that is used to traverse collections such as ArrayList and others.

This diagram shows a structure of an iterator pattern Diagram
Courtesy of Wikipedia

This example demonstrates iterator pattern. Take note that this example is just a mere demonstration and not recommended to be reproduced in production.
import java.util.List;
import java.util.ArrayList;

public class ClientCode{

  public static void main(String[] args){
    Aggregate collection = 
    new ConcreteAggregate();
    
    collection.add("A");
    collection.add("B");
    collection.add("C");
    collection.add("D");
    collection.add("E");
    
    SampleIterator iterator =
    collection.createIterator();
    
    while(iterator.hasNext())
      System.out.println(iterator.next());
  }
}

/*
Assume classes below are in different package
and they're all public except for 
ConcreteIterator class
*/
interface Aggregate{

  void add(String element);
  SampleIterator createIterator();
}

class ConcreteAggregate implements Aggregate{
  private List<String> list;
  private SampleIterator iterator;
  
  ConcreteAggregate(){
    list = new ArrayList<>();
  }
  
  @Override
  public void add(String element){
    list.add(element);
  }
  
  @Override
  public SampleIterator createIterator(){
    return new ConcreteIterator(list);
  }
}

interface SampleIterator{

  String next();
  boolean hasNext();
}

class ConcreteIterator implements SampleIterator{
  private List<String> list;
  private int pointer;
  
  ConcreteIterator(List<String> list){
    this.list = list;
  }
  
  @Override
  public String next(){
    if(pointer >= list.size())
      throw new ArrayIndexOutOfBoundsException();
    String result = list.get(pointer);
    pointer++;
    return result;
  }
  
  @Override
  public boolean hasNext(){
    if(pointer >= list.size())
      return false;
    else
      return true;
  }
  
}

Result
A
B
C
D
E

Tuesday, June 14, 2022

Design Pattern: Command Pattern

Chapters

Command Pattern

Command pattern is a design pattern that wraps an object (receiver) to another object (command) with necessary information that can be processed by a handler (invoker). Command pattern consists of four entities: Client, Command, Receiver and Invoker.

Client is the one that uses our code. Could be a programmer or class. Command are classes that instantiate command objects. Command objects are objects that contain a receiver object and necessary information, sucn as function (instruction) to be called and variables, that is needed by an ivoker in order to perform requests that clients want.

Receiver are classes that instantiate receiver objects. Receiver objects are objects that are receiving commands. Invoker are classes that instantiate invoker objects. These objects contain commands that are executed by them.

This pattern promotes loose coupling between commands and handlers or executors. It means that commands and handlers don't need to be tighly coupled in order to function properly. Thus, increasing the flexibility of our code. Moreover, command pattern is often used in conjunction with chain-of-responsibility pattern.

This diagram shows how to implement a command pattern Diagram
Courtesy of Wikipedia

This example demonstrates command pattern.
//Client
public class ClientCode{
  
  public static void main(String[] args){
    
    //Receiver instance
    Controller computerController = 
    new ComputerController();
    Controller consoleController = 
    new ConsoleController();
   
    //command instance
    Command moveUp = 
    new MoveCommand(computerController,
                    Controller.DirectMove.UP);
    Command moveTopLeft = 
    new MoveDiagonalCommand(
    computerController,
    Controller.DiagonalMove.TOP_LEFT);
    
    //Invoker instance
    MoveInput controllerInput = 
    new MoveInput(moveUp, moveTopLeft);  
    controllerInput.move();
    controllerInput.moveDiagonally();
    System.out.println();  
    
    //Command instance
    Command moveDown = 
    new MoveCommand(consoleController,
                    Controller.DirectMove.DOWN);
    Command moveBotRight = 
    new MoveDiagonalCommand(
    consoleController,
    Controller.DiagonalMove.BOTTOM_RIGHT);
    
    MoveInput consoleInput = 
    new MoveInput(moveDown, moveBotRight);
    consoleInput.move();
    consoleInput.moveDiagonally();
  
  }
}

//Receiver interface
interface Controller{
  public enum DirectMove{
    UP, RIGHT, DOWN, LEFT
  }
  
  public enum DiagonalMove{
    TOP_LEFT, TOP_RIGHT, 
    BOTTOM_LEFT, BOTTOM_RIGHT
  }
  
  void move(DirectMove direction);
  void moveDiagonally(DiagonalMove direction);
}
  
//Receiver
class ConsoleController implements Controller{
  
  @Override
  public void move(DirectMove direction){
    System.out.println
    ("Console controller moves " + direction);
  }
  
  @Override
  public void moveDiagonally(DiagonalMove direction){
    System.out.println
    ("Console controller diagonally moves " + direction);
  }
}
  
//Receiver
class ComputerController implements Controller{
  
  @Override
  public void move(DirectMove direction){
    System.out.println
    ("Computer controller moves " + direction);
  }
  
  @Override
  public void moveDiagonally(DiagonalMove direction){
    System.out.println
    ("Console controller diagonally moves " + direction);
  }
}

//command interface
interface Command{
  
  void execute();
}
  
//command
class MoveCommand implements Command{
  
  private Controller controller;
  private Controller.DirectMove movement;
  
  public MoveCommand(Controller controller,
                     Controller.DirectMove movement){
    this.controller = controller;
    this.movement = movement;
  }
  
  @Override
  public void execute(){
    controller.move(movement);
  }
}
  
//command
class MoveDiagonalCommand implements Command{
  
  private Controller controller;
  private Controller.DiagonalMove movement;
  
  public MoveDiagonalCommand(Controller controller,
                             Controller.DiagonalMove movement){
    this.controller = controller;
    this.movement = movement;
  }
  
  @Override
  public void execute(){
    controller.moveDiagonally(movement);
  }
}
  
//invoker
class MoveInput{
  private Command directMovement;
  private Command diagonalMovement;
  
  public MoveInput(Command directMovement,
                   Command diagonalMovement){
    this.directMovement = directMovement;
    this.diagonalMovement = diagonalMovement;
  }
  
  public void move(){
    directMovement.execute();
  }
  
  public void moveDiagonally(){
    diagonalMovement.execute();
  }
}
  
Result
Computer controller move UP
Computer controller diagonally moves TOP_LEFT
  
Console controller moves DOWN
Console controller diagonally moves BOTTOM_RIGHT

Sunday, June 12, 2022

Design Pattern: Chain-of-responsibility pattern

Chapters

Chain-of-responsibility pattern

Chain-of-responsibility pattern is a behavioral design pattern that consists of command objects and processing objects. Command objects are objects that are being processed by processing objects.

Typically, every class in the chain has different responsibilities from one another. However, many implementations(such as UI event handling, servlet filters in Java and the example below) breaks this concept and allow several classes in the chain to take the same responsibility. This pattern promotes loose coupling as its processing objects are not closely tied up to command objects.

This example demonstrates chain-of-responsibility pattern.
import java.util.List;
import java.util.Arrays;

public class ClientCode{
  
  public static void main(String[] args){
  
    Handler handler = 
    new Adult(Arrays.asList(Handler.Fruits.all()), "Timothy").
    addHandler(
     new YoungAdult(
     Arrays.asList(Handler.Fruits.APPLE, Handler.Fruits.GUAVA),
                   "Samantha")).
    addHandler(
     new Child(
     Arrays.asList(Handler.Fruits.APPLE, Handler.Fruits.ORANGE),
                   "Louis"));
                   
     handler.offer(Handler.Fruits.APPLE);
     System.out.println();
     handler.offer(Handler.Fruits.GUAVA);
     System.out.println();
     handler.offer(Handler.Fruits.ORANGE);
     System.out.println();
     handler.offer(Handler.Fruits.MELON);
  }
}

//functional interface
interface Handler{
  public enum Fruits{
    AVOCADO, ORANGE, APPLE, GUAVA, MELON;
    
    public static Fruits[] all(){
      return values();
    }
  }
  
  //No need to add Handler reference after
  //Fruits reference. This method is in the
  //scope of Handler already
  //
  //classes that implement this method also
  //don't need to add Handler reference after
  //Fruits reference
  void offer(Fruits fruit);
  
  default Handler addHandler(Handler nextHandler){
    return (fruit) -> {
      offer(fruit);
      nextHandler.offer(fruit);
    };
  }
  
}

abstract class Patron{
  protected List<Handler.Fruits> preferredFruit;
  protected String name;
  
  Patron(List<Handler.Fruits> preferredFruit, 
         String name){
    this.preferredFruit = preferredFruit;
    this.name = name;
  }
  
  protected boolean checkPreferredFruit(Handler.Fruits fruit){
    boolean result = false;
    
    for(Handler.Fruits f : preferredFruit)
      if(f == fruit)
        result = true;
    return result;
  }
  
}

class Child extends Patron implements Handler{
  
  Child(List<Handler.Fruits> preferredFruit, 
         String name){
    super(preferredFruit, name);
  }
  
  @Override
  public void offer(Fruits fruit){
    if(!checkPreferredFruit(fruit))
      return;
    
    System.out.println
    (name + ", a child, took " + fruit);
  }
}

class YoungAdult extends Patron implements Handler{
  
  YoungAdult(List<Handler.Fruits> preferredFruit, 
         String name){
    super(preferredFruit, name);
  }
  
  @Override
  public void offer(Fruits fruit){
    if(!checkPreferredFruit(fruit))
      return;
  
    System.out.println
    (name + ", a young adult, took " + fruit);
  }
}

class Adult extends Patron implements Handler{
  
  Adult(List<Handler.Fruits> preferredFruit, 
         String name){
    super(preferredFruit, name);
  }
  
  @Override
  public void offer(Fruits fruit){
    if(!checkPreferredFruit(fruit))
      return;
    
    System.out.println
    (name + ", an adult, took " + fruit);
  }
}

Result
Timothy, an adult, took APPLE
Samantha, a young adult, took APPLE
Louis, a child, took APPLE

Timothy, an adult, took GUAVA
Samantha, a young adult, took GUAVA

Timothy, an adult, took ORANGE
Louis, a child, took ORANGE

Timothy, an adult, took MELON
In the example above, fruits in the Fruits enum are command objects whereas Adult, Child and YoungAdult instances are processing objects.

Friday, June 10, 2022

Design Pattern: Proxy Pattern

Chapters

Proxy Pattern

proxy pattern is a software design pattern. A proxy, in its most general form, is a class functioning as an interface to something else.

The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate. In short, a proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes.

Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy, extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked. For the client, usage of a proxy object is similar to using the real object, because both implement the same interface.

This diagram shows how to implement a proxy pattern Diagram
Courtesy of Wikipedia

This example demonstrates proxy pattern.
public class ClientCode{

  public static void main(String[] args){
    StringConcatInterface sci = 
    new StringConcatProxy(new StringConcat("My "));
    
    sci.concat("String!");
    System.out.println(sci.getText());
    sci.concat("String!String!");
    System.out.println(sci.getText());
    sci.concat("String!String!String!");
    System.out.println(sci.getText());
  }
}

interface StringConcatInterface{

  void concat(String str);
  String getText();
}

class StringConcat implements StringConcatInterface{
  private StringBuilder builder;
  
  StringConcat(String text){
    builder = new StringBuilder(text);
  }
  
  @Override
  public void concat(String str){
    builder.append(str);
  }
  
  @Override
  public String getText(){
    return builder.toString();
  }
}

class StringConcatProxy implements StringConcatInterface{
  private StringConcat sc;
  
  StringConcatProxy(StringConcat sc){
    this.sc = sc;
  }
  
  @Override
  public void concat(String str){
    if(sc.getText().length() > 10){
      System.out.println
      ("Max characters has been reached!");
    }
    else
      sc.concat(str);
  }
  
  @Override
  public String getText(){
    return sc.getText();
  }
  
}

Result
My String!
My String!String!String!
Max characters has been reached!
My String!String!String!
You might have noticed that proxy pattern is similar to decorator pattern. Their structure is similar but their purpose are not. We use decorator pattern if we want to add functionalities to a class while not affecting other related classes. We use proxy pattern if we want some kind of mirror that mirrors our class.