Minggu, 18 Desember 2016

Turnstile - State Design Pattern





Mesin Coin Operated Turnstile merupakan sebuah alat yang berfungsi sebagai penghalang jalan yang hanya bisa dibuka jika kita memasukkan koin ke dalam mesin.

State Diagram


Berikut adalah state diagram dari mesin turnstile



Terdapat 2 state, yaitu LOCKED dan UNLOCKED. State awal adalah LOCKED. Panah pada gambar merupakan representasi dari perubahan suatu state. Untuk berubah state, maka perlu adanya event tertentu, misal memasukkan token/koin untuk menuju state unlocked.

Use Case


CRC


Turnstile

Responsibilities
Collaborator
Allow user to pass through the machine
UnlockedState
Allow user to insert token

Allow user to get refund

Turn on alarm


LockedState

Responsibilities
Collaborator
Set machine state to unlocked
Turnstile

UnlockedState


Responsibilities
Collaborator
Set machine state to locked
Turnstile

Deployment Diagram




Class Diagram




Source Code

Turnstile.java

 public class Turnstile  
 {  
   private State state;  
   private final State lockedState;  
   private final State unlockedState;  
   public Turnstile()  
   {  
     lockedState = new LockedState(this);  
     unlockedState = new UnlockedState(this);  
 // set initial state of turnstile  
     state = lockedState;  
   }  
   public State getState()  
   {  
     return state;  
   }  
   public void setState(State state)  
   {  
     this.state = state;  
   }  
   public void insertToken()  
   {  
     state.insertToken();  
   }  
   public void passThru()  
   {  
     state.passThru();  
   }  
   public void lock()  
   {  
     System.out.println("Locking the turnstile...");  
     setState(lockedState);  
     System.out.println(getState());  
   }  
   public void unlock()  
   {  
     System.out.println("Unlocking the turnstile...");  
     setState(unlockedState);  
     System.out.println(getState());  
   }  
   public void alarm()  
   {  
     System.out.println("Alert! Cannot pass through without inserting a token!!");  
   }  
   public void refund()  
   {  
     System.out.println("Refunding the token...");  
   }  
   public String toString()  
   {  
     StringBuffer result = new StringBuffer();  
     result.append("\n-- Welcome to the Turnstile Application --\n");  
     result.append(getState());  
     return result.toString();  
   }  
 }  

State.java

 public interface State  
 {  
   public void insertToken();  
   public void passThru();  
 }  

UnlockedState.java

 public class UnlockedState implements State  
 {  
   private final Turnstile turnstile;  
   public UnlockedState(Turnstile turnstile)  
     {  
     this.turnstile = turnstile;  
     }  
   public void insertToken()  
     {  
     System.out.println("insertToken(): Accepting token in the " + turnstile.getState() +  
     " state...");  
     turnstile.refund();  
     }  
   public void passThru()  
     {  
     System.out.println("passThru(): Passing through in the " + turnstile.getState() + " state...");  
     turnstile.lock();  
     }  
   public String toString()  
     {  
     return "UNLOCKED";  
     }  
 }  

LockedState.java

 public class LockedState implements State  
 {  
   private final Turnstile turnstile;  
   public LockedState(Turnstile turnstile)  
   {  
     this.turnstile = turnstile;  
   }  
   public void insertToken()  
   {  
     System.out.println("insertToken(): Accepting token in the " + turnstile.getState() +  
         " state...");  
     turnstile.unlock();  
   }  
   public void passThru()  
   {  
     System.out.println("passThru(): Passing through in the " + turnstile.getState() + " state....");  
     turnstile.alarm();  
   }  
   public String toString()  
   {  
     return "LOCKED";  
   }  
 }  

Berikut adalah source code untuk client

TurnstileApp.java

 import java.util.Scanner;  
 /**  
  * Created by A-BILAL on 12/18/2016.  
  */  
 public class TurnstileApp  
 {  
   private TurnstileApp()  
   {  
 // using default private constructor in lieu of creating a Singleton object  
   }  
   public static void main(String[] args)  
   {  
     Turnstile turnstile = new Turnstile();  
 // first person inserts a token and passes through the turnstile  
     System.out.println(turnstile);  
     turnstile.insertToken();  
     turnstile.passThru();  
 // second person attempts to pass through turnstile without inserting a token  
     System.out.println(turnstile);  
     turnstile.passThru();  
     turnstile.insertToken();  
     turnstile.passThru();  
 // third person attempts to pass through turnstile without initially inserting a token.  
     System.out.println(turnstile);  
     turnstile.insertToken();  
     turnstile.insertToken();  
     turnstile.passThru();  
     while(true){  
 //      System.out.println(turnstile);  
       Scanner reader = new Scanner(System.in); // Reading from System.in  
       System.out.println("Enter action (1 = Insert Token, 2 = Pass Through), 3 = Exit: ");  
       int n = reader.nextInt(); // Scans the next token of the input as an int.  
       if(n == 1){  
         turnstile.insertToken();  
       }  
       else if(n == 2){  
         turnstile.passThru();  
       }  
       else if(n == 3){  
         break;  
       }  
       else{  
         System.out.println("Input Tidak Valid");  
       }  
     }  
   }  
 }  

Output


Terdapat 3 percobaan pada program client, yaitu :

  1. Memasukkan token dan melewati mesin turnstile
    State akan berubah menjadi UNLOCKED dan mesin bisa terlewati lalu state akan kembali ke LOCKED
  2. Mencoba melewati mesin turnstile tanpa memasukkan token
    State tetap pada LOCKED dan tidak bisa melewati mesin serta terdapat pemanggilan fungsi alarm
  3. Memasukkan token 2 kali
    State pada mesin berubah menjadi UNLOCKED. Setelah memasukkan token ke-2 maka user akan mendapatkan refund. Setelah melewati mesin maka state kembali ke LOCKED.

Untuk input User :

  • 1 = Insert Token
  • 2 = Pass Through



Referensi :