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.

Design Pattern: Flyweight Pattern

Chapters

Flyweight Pattern

Flyweight pattern refers to an object that minimizes memory usage by sharing some of its data with other similar objects. The flyweight pattern is useful when dealing with large numbers of objects with simple repeated elements that would use a large amount of memory if individually stored.

This example demonstrates flyweight pattern.
import java.util.Queue;
import java.util.ArrayDeque;

public class ClientCode{

  public static void main(String[] args){
    int x = 0;
    int y = 0;
    
    TileFlyWeightFactory tileFactory =
    TileFlyWeightFactory.getInstance();
    
    //4x4 grid
    for(int i = 0; i < 4; i++){
      for(int j = 0; j < 4; j++){
        tileFactory.
        useThenAdd().
        draw(x, y);
        x += 64;
      }
      x = 0;
      y += 64;
      System.out.println();
    }
    
  }
}

interface TileInterface{

  void draw(int posx, int posy);
}

class Tile implements TileInterface{
  //intrinsic state
  private final String tileSource;
  
  Tile(String tileSource){
    this.tileSource = tileSource;
  }
  
  @Override
  public void draw(int posx, int posy){
    System.out.println
    (tileSource + " is drawn at " +
     posx + ", " + posy);
  }
  
}

//singleton
class TileFlyWeightFactory{
  private static TileFlyWeightFactory instance;
  private Queue<TileInterface> cache;
  
  private TileFlyWeightFactory(){
    cache = new ArrayDeque<>();
    cache.add(new Tile("Tile1.jpg"));
    cache.add(new Tile("Tile2.jpg"));
    cache.add(new Tile("Tile3.jpg"));
    cache.add(new Tile("Tile4.jpg"));
  }
  
  public static TileFlyWeightFactory getInstance(){
    if(instance == null)
      instance = new TileFlyWeightFactory();
    return instance;
  }
  
  public TileInterface useThenAdd(){
    TileInterface target = null;
    
    if(!cache.isEmpty()){
      target = cache.poll();
      cache.add(target);
    }
    return target;
  }
  
}

Result
Tile1.jpg is drawn at 0, 0
Tile2.jpg is drawn at 64, 0
Tile3.jpg is drawn at 128, 0
Tile4.jpg is drawn at 192, 0

Tile1.jpg is drawn at 0, 64
Tile2.jpg is drawn at 64, 64
Tile3.jpg is drawn at 128, 64
Tile4.jpg is drawn at 192, 64

Tile1.jpg is drawn at 0, 128
Tile2.jpg is drawn at 64, 128
Tile3.jpg is drawn at 128, 128
Tile4.jpg is drawn at 192, 128

Tile1.jpg is drawn at 0, 192
Tile2.jpg is drawn at 64, 192
Tile3.jpg is drawn at 128, 192
Tile4.jpg is drawn at 192, 192
First off, we store two states to our flyweight class (Tile class in this case). One of them is the intrinsic state. This state is constant. The next one is the extrinsic state. This state is not constant and likely to change overtime. In the example above, tileSource variable is the intristic state; posx and posy are extrinsic states.

In the example above, I reuse instantiated Tile objects in order to reuse their tileSource constants (intrinsic) and draw them anywhere on the screen using posx and posy variables (extrinsic). This technique saves a lot of system resources because I don't need to create a new instance of Tile class in order to reuse a tile image that's been already used.

Other information such as caching, retrieval, concurrency can be found in this wiki.

Thursday, June 9, 2022

Design Pattern: Facade Pattern

Chapters

Facade Pattern

facade pattern (also spelled façade) is a software-design pattern commonly used in object-oriented programming. Analogous to a facade in architecture, a facade is an object that serves as a front-facing interface masking more complex underlying or structural code in order to simplify the complexity of the system behind the facade.

To implement this pattern, we need a class that implements an interface and the implementations of the methods of the interface are delegated to the system behind the facade. Although, the interface may perform additional functionality before/after forwarding a request. Take a look at this example.

/*
Client
*/

public class ClientCode{

  public static void main(String[] args){
    RoomInterface ri = 
    new RoomController(new RoomControl());
    
    ri.openThenMark();
    System.out.println();
    ri.unmarkThenClose();
  }
}

/*
Facade
*/

interface RoomInterface{

  void openMarkThenClose();
  void openUnmarkThenClose();
  void openThenMark();
  void openThenUnmark();
  void markThenClose();
  void unmarkThenClose();
}

class RoomController implements RoomInterface{
  RoomControlInterface rci;
  
  RoomController(RoomControlInterface rci){
    this.rci = rci;
  }
  
  @Override
  public void openMarkThenClose(){
    rci.openRoom();
    rci.markRoom();
    rci.closeRoom();
  }
  
  @Override
  public void openUnmarkThenClose(){
    rci.openRoom();
    rci.unmarkRoom();
    rci.closeRoom();
  }
  
  @Override
  public void openThenMark(){
    rci.openRoom();
    rci.markRoom();
  }
  
  @Override
  public void openThenUnmark(){
    rci.openRoom();
    rci.unmarkRoom();
  }
  
  @Override
  public void markThenClose(){
    if(!rci.openRoom()){
      System.out.println("Room is not open.");
      System.out.println
      ("Therefore, it can't be closed.");
      return;
    }
    rci.markRoom();
    rci.closeRoom();
  }
  
  @Override
  public void unmarkThenClose(){
    if(!rci.openRoom()){
      System.out.println("Room is not open.");
      System.out.println
      ("Therefore, it can't be closed.");
      return;
    }
    rci.unmarkRoom();
    rci.closeRoom();
  }
  
}

/*
Complex System
*/

interface RoomControlInterface{
  
  boolean openRoom();
  void markRoom();
  void unmarkRoom();
  void closeRoom();
}

class RoomControl implements RoomControlInterface{
  private boolean isMarked = false;
  private boolean isOpen = false;
  
  @Override
  public boolean openRoom(){

    if(isOpen){
      System.out.println
      ("Room is already open!");
    }
    else{
      System.out.println
      ("Room has been opened!");
      isOpen = true;
    }
    return isOpen;
  }
  
  @Override
  public void markRoom(){
     if(isMarked){
      System.out.println
      ("Room is already marked. "+
       "no need to mark again.");
    }
    else{
      isMarked = true;
      System.out.println
      ("Room has been marked!");
    }
  }
  
  @Override
  public void unmarkRoom(){
    if(!isMarked){
      System.out.println
      ("Room is already unmarked. "+
       "no need to unmark again.");
    }
    else{
      isMarked = false;
      System.out.println
      ("Room has been unmarked!");
    }
  }
  
  @Override
  public void closeRoom(){
    
    if(isOpen){
      System.out.println
      ("Room has been closed!");
      isOpen = false;
    }
  }
}

Result
Room has been opened!
Room has been marked!

Room is already open!
Room has been unmarked!
Room has been closed!