Showing posts with label state. Show all posts
Showing posts with label state. Show all posts

Tuesday, August 12, 2014

Programming Design Pattern - State Pattern Applied - Best Practise

Hi there!

Today i'm gonna show the state design pattern in action. The state design pattern is a very useful programming design pattern while dealing with state maschines.

I'm assuming here you already know the concepts and i'll be focusing on practise. The example i will provide is a nice way to show it how it could looks like. You can always come back here, take it, adapt it and use it in your applictions as you may need. So be sure you bookmark it or join the group here on the right side of this post subscribing it.

First of all, let's take a look at the UML diagram of it. After that we will take the analogy for our example.

The simpliest UML State Pattern

Pay close attention, because once you understand that, everything will become clear and simple to understand. That's the reason I'm putting always the UML first. That way you'll get an eye for it with the time.

The State Interface

Here we can see how simple it is. Let's implement some real states from our ticket automat to get more familiar with. The MoneyState will be set, when the user has paid for the ticket and will calculate the exchange if some.

public interface State {
    void handle();
}
public class MoneyState implements State {
    private TicketAutomat context;
    public MoneyState(TicketAutomat context) {
        this.context = context;
    }
    @Override
    public void handle() {
        System.out.println("PAYMENT RECEIVED! CALCULATING EXCHANGE ...");
        context.setCurrentState(context.getSoldState());
        context.getCurrentState().handle();
    }
}

The TicketSoldState

This state says to the user that the ticket has been sold out successfully and sets the NoMoneyState asking the user to pay for a ticket if we still have tickets available, otherwise will set the SoldOutStore which shows to the user, that all tickets are sold out.

public class TicketSoldState implements State {
    private TicketAutomat context;
    public TicketSoldState(TicketAutomat context) {
        this.context = context;
    }
    @Override
    public void handle() {
        context.updateTicketsAvailable();
        context.setPaid(false);
        System.out.println("YOUR TICKET WAS PRINTED OUT!");
        if(context.isTicketAvailable()){
            context.setCurrentState(context.getNoMoneyState());
        }else{
            context.setCurrentState(context.getSoldOutState());
            context.getCurrentState().handle();
        }
    }
}

TicketsSoldOutState

This state says, "Sorry no more tickets available" or sets the NoMoneyState if we have tickets available.

public class TicketsSoldOutState implements State {
    private TicketAutomat context;
    public TicketsSoldOutState(TicketAutomat context) {
        this.context = context;
    }
    @Override
    public void handle() {
        if(context.isTicketAvailable()){
            context.getNoMoneyState().handle();
        }else{
            System.out.println("SORRY! THERE IS NO MORE TICKETS AVAILABLE!");
            context.setCurrentState(context.getSoldOutState()); 
        }
    }
}

NoMoneyState

This state is the first message the user will see, if we have tickets to sell. It sets the MoneyState to show to the user, that it has received the money and it is processing it.

public class NoMoneyState implements State {
    private TicketAutomat context;
    public NoMoneyState(TicketAutomat context) {
        this.context = context;
    }
    @Override
    public void handle() {
        System.out.println("PLEASE PAY FOR THE TICKET YOU WANT!");
        context.setCurrentState(context.getMoneyState());
        context.getCurrentState().handle();
    }
}

The Context - TicketAutomat

This is the context class. It contais all states and has the some simple logic in it

// THE TICKET AUTOMAT IS THE CONTEXT
public class TicketAutomat {
    
    private State soldOutState;
    private State noMoneyState;
    private State moneyState;
    private State soldState;
    private State currentState;
    
    private int ticketsAvailable = 10;
    private boolean paid=false;
    
    TicketAutomat(int ticketsAvailable){
        soldState =  new TicketSoldState(this);
        soldOutState =  new TicketsSoldOutState(this);
        noMoneyState =  new NoMoneyState(this);
        moneyState =  new MoneyState(this);
        initCurrentState(ticketsAvailable);
    }
    
    private void initCurrentState(int ticketsAvailable){
        this.ticketsAvailable=ticketsAvailable;
        if(this.ticketsAvailable>0){
            setCurrentState(noMoneyState);
        }else{
            setCurrentState(soldOutState);
        }
    }
        
    public State getSoldOutState() {return soldOutState;}
    public State getNoMoneyState() {return noMoneyState;}
    public State getMoneyState() {return moneyState;}
    public State getSoldState() {return soldState;}
    public State getCurrentState() {return currentState;}
    public void setCurrentState(State currentState) {this.currentState = currentState;}
    public int getTicketsAvailable() {return ticketsAvailable;}
    public void setTicketsAvailable(int ticketsAvailable) {this.ticketsAvailable = ticketsAvailable;}
    public void updateTicketsAvailable(){this.ticketsAvailable-=1;}
    public boolean isTicketAvailable(){return this.ticketsAvailable>0;}
    public boolean hasPaid(){return paid;}
    public void setPaid(boolean paid){this.paid=paid;}
}

Testing it

Finally our client which tests it. With a Thread we are simulating a full cycle waiting 5 seconds between each state.

public class Client {
    public static void main(String[] args) {
        new Thread(){
            int ticketsAvailable = 5;
            final TicketAutomat automat = new TicketAutomat(ticketsAvailable);
            public void run() {
                while(automat.isTicketAvailable()){
                    automat.setPaid(true);
                    automat.getCurrentState().handle();
                    try {
                        sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            };
        }.start();
    }
}
That's all! Hope you like it!

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†

Wednesday, November 6, 2013

How to create a bit state register java android

Hi there! Today i'gonna share/show how we could create a bit state register, manupulate bit states doing OR and AND operations on it. Favor/consider always the state pattern whenever possible over this solution here. I use it when the state pattern is not our first choice or is inappropriate. (when it gets to complex or i'm doing simple state checks and the design is simple, fixed and not intented to be extended) It is a simple 32 states bit processor which can hold up to max 32 states. The result at the end will be something like in the class diagram bellow:



BitStates

/**
 * Bit states to represent 32 possible states. The first state is the mask state to reset states.
 * Those states can be used to define component transition states while animating it.
 * 
INSTRUCTIONS ON HOW TO USE IT:

 * In combination with a state pattern, you may associate any bit state to a transition, position, animation or whatever you need to monitor in a proper sequence. 
 * For example: If you want to know that a button X has been pressed, animation Y is done and Fragment Z is shown, associate a bit state to each of them
 * and do an "or-operation" on it. You'll be able now to extract all those information (3 states) from just one bit combination without having to explicitly ask for it using a lot of if/else cases.
 * 
  BIT STATE REPRESENTATION            HEX CODE REPRESENTATION
  00000000000000000000000000000000 0
 00000000000000000000000000000001 1
 00000000000000000000000000000010 2
 00000000000000000000000000000100 4
 00000000000000000000000000001000 8
 00000000000000000000000000010000 10
 00000000000000000000000000100000 20
 00000000000000000000000001000000 40
 00000000000000000000000010000000 80
 00000000000000000000000100000000 100
 00000000000000000000001000000000 200
 00000000000000000000010000000000 400
 00000000000000000000100000000000 800
 00000000000000000001000000000000 1000
 00000000000000000010000000000000 2000
 00000000000000000100000000000000 4000
 00000000000000001000000000000000 8000
 00000000000000010000000000000000 10000
 00000000000000100000000000000000 20000
 00000000000001000000000000000000 40000
 00000000000010000000000000000000 80000
 00000000000100000000000000000000 100000
 00000000001000000000000000000000 200000
 00000000010000000000000000000000 400000
 00000000100000000000000000000000 800000
 00000001000000000000000000000000 1000000
 00000010000000000000000000000000 2000000
 00000100000000000000000000000000 4000000
 00001000000000000000000000000000 8000000
 00010000000000000000000000000000 10000000
 00100000000000000000000000000000 20000000
 01000000000000000000000000000000 40000000
 10000000000000000000000000000000 80000000
 * 
* @author Ricardo Ferreira 01/11/2013 * */ public enum BitStates { STATE_00(0x0), STATE_01(0x1), STATE_02(0x2), STATE_03(0x4), STATE_04(0x8), STATE_05(0x10), STATE_06(0x20), STATE_07(0x40), STATE_08(0x80), STATE_09(0x100), STATE_10(0x200), STATE_11(0x400), STATE_12(0x800), STATE_13(0x1000), STATE_14(0x2000), STATE_15(0x4000), STATE_16(0x8000), STATE_17(0x10000), STATE_18(0x20000), STATE_19(0x40000), STATE_20(0x80000), STATE_21(0x100000), STATE_22(0x200000), STATE_23(0x400000), STATE_24(0x800000), STATE_25(0x1000000), STATE_26(0x2000000), STATE_27(0x4000000), STATE_28(0x8000000), STATE_29(0x10000000), STATE_30(0x20000000), STATE_31(0x40000000), STATE_32(0x80000000); private int state; private BitStates(int state) { this.state = state; } public int getState() { return state; } }

BitStateRegister

import java.util.HashMap;
import java.util.Map;

// Singleton Pattern
/**
 * Use this register to associate bit states to concrete states in a state pattern.
 * This register can hold up to 33 bit states,while the 0 state is per default the
 * zero state (reset mask state).
 * @author Ricardo Ferreira 02/11/2013
 *
 */
public class BitStateRegister {

 private static final BitStateRegister INSTANCE = new BitStateRegister();
 private static final Map stateRegister = new HashMap();
 private static final int registerMaxSize = 33;

 private BitStateRegister() {
  // Singleton Pattern
 }

 public static BitStateRegister getInstance() {
  registerZeroStateOnlyOnce();
  return INSTANCE;
 }
 
 private static void registerZeroStateOnlyOnce(){
  if (!stateRegister.containsKey("zero")) {
   stateRegister.put("zero", BitStates.STATE_00.getState());
  }
 }

 /**
  * State Register. It registers a new state only if not exists already. 

  * This Register is able to register from 1 up to 32 states in a 32 bit system.

  * You do not have to care about it. The states will be created and increased

  * automatically, when registered.

 
  * 
  * To obtain the zero state(reset mask state), call getState("zero"); on it.

  * To check if the register is already completely full, call isRegisterComplete(); on it.
  * 
  * @param stateClassSimpleName the simple class name provided by calling: ConcreteState.class.getSimpleName(); on your concrete state.
  * @return true if the new state was created, false if the state already exists or the register is full.
  */
 public boolean registerStateFor(String stateClassSimpleName) {
  boolean operationResult = false;
  if (!stateRegister.containsKey(stateClassSimpleName) && stateRegister.size() < registerMaxSize) {
   int nextStateIndex = stateRegister.size();
   int newState = BitStates.values()[nextStateIndex].getState();
   stateRegister.put(stateClassSimpleName, newState);
   operationResult = true;
  }
  return operationResult;
 }

 public boolean unregisterStateFor(String stateClassSimpleName){
  boolean operationResult = false;
  if (stateRegister.containsKey(stateClassSimpleName)) {
   Integer bitState = stateRegister.get(stateClassSimpleName);
   stateRegister.remove(bitState);
   operationResult = true;
  }
  return operationResult;
 }

 public int getStateFor(String stateClassSimpleName) {
  return stateRegister.get(stateClassSimpleName);
 }

 /**
  * Returns true if the Register is already completely filled up with 32 states , false otherwise.
  * 
  * @return true if the Register is already completely filled up with 32 states , false otherwise
  */
 public boolean isRegisterComplete() {
  return stateRegister.size() == registerMaxSize;
 }
 
 /**
  * Checks if the state of the given state class name is set in the current bit state.
  * @param currentBitState the current bit state
  * @param stateClassSimpleName the simple class name provided by calling: ConcreteState.class.getSimpleName(); on your concrete state.
  * @return true if the bit is set, false otherwise.
  */
 public boolean isBitStateSetted(int currentBitState, String stateClassSimpleName){
  boolean operationResult = false;
  if(stateRegister.containsKey(stateClassSimpleName)){
   int stateFor = getStateFor(stateClassSimpleName);
   if((stateFor&currentBitState)==stateFor){
    operationResult = true;
   }
  }
  return operationResult;
 }

}

BitStateProcessor

/**
 * A bit state processor with a process state capacity of max 32 states.
 * Favor/consider always the usage of a state pattern instead of it. 
 * But in case the state pattern is inappropriate, you can use it.
 * 
 * @author Ricardo Ferreira 06/11/2013
 * 
 */
public class BitStateProcessor {
 private int resetMask = BitStateRegister.getInstance().getStateFor("zero");
 private int currentBitState = 0x0;
 private int internalState = 0x0;
 private String stateClassSimpleName;

 /**
  * @param stateClassSimpleName
  *            the simple class name of your concrete state provided by calling ConcreteState.class.getSimpleName();
  */
 public BitStateProcessor(int currentBitState, String stateClassSimpleName) {
  this.currentBitState = currentBitState;
  this.stateClassSimpleName = stateClassSimpleName;
  BitStateRegister.getInstance().registerStateFor(stateClassSimpleName);
  this.internalState = BitStateRegister.getInstance().getStateFor(stateClassSimpleName);
 }

 public int getCurrentBitState() {
  return this.currentBitState;
 }

 public void setCurrentBitState(int currentBitState) {
  this.currentBitState = currentBitState;
 }

 public void resetCurrentBitState() {
  this.currentBitState = this.currentBitState & this.resetMask;
 }

 public boolean isBitStateSetted() {
  return BitStateRegister.getInstance().isBitStateSetted(this.currentBitState, this.stateClassSimpleName);
 }

 public boolean unregisterStateFor(String stateClassSimpleName) {
  return BitStateRegister.getInstance().unregisterStateFor(stateClassSimpleName);
 }

 public boolean isRegisterComplete() {
  return BitStateRegister.getInstance().isRegisterComplete();
 }

 public int getStateFor(String stateClassSimpleName) {
  return BitStateRegister.getInstance().getStateFor(stateClassSimpleName);
 }

 /**
  * Returns a new bit state.
  * 
  * @param currentBitState the actual bit state passed to this class or method
  * @return the new bit state after an "or-operarion" with its internal state.
  */
 public int processCurrentBitState(int currentBitState) {
  this.currentBitState = this.internalState | currentBitState;
  return this.currentBitState;
 }

}

That's all! hope you like it!

😱👇 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘‡

Be sure to read, it will change your life!
Show your work by Austin Kleonhttps://amzn.to/34NVmwx

This book is a must read - it will put you in another level! (Expert)
Agile Software Development, Principles, Patterns, and Practiceshttps://amzn.to/30WQSm2

Write cleaner code and stand out!
Clean Code - A Handbook of Agile Software Craftsmanship: https://amzn.to/33RvaSv

This book is very practical, straightforward and to the point! Worth every penny!
Kotlin for Android App Development (Developer's Library): https://amzn.to/33VZ6gp

Needless to say, these are top right?
Apple AirPods Pro: https://amzn.to/2GOICxy

😱👆 PROMOTIONAL DISCOUNT: BOOKS AND IPODS PRO ðŸ˜±ðŸ‘†