Sabtu, 13 Mei 2017

OOP Dalam Mesin ATM

Pada kesempatan kali ini, saya akan membagikan ilmu mengenai cara membuat Mesin ATM sederhana menggunakan Java, dengan panduan dari buku “Java How To Program” karya Paul Deitel dan Harvey Deitel.

Untuk class diagram dengan attr dan operations, bisa digambarkan sebagai berikut.




Langsung ke bagian source code:


  • Class ATM
public class ATM
{
    private boolean userAuthenticated;
    private int currentAccountNumber;
    private Screen screen;
    private Keypad keypad;
    private CashDispenser cashDispenser;
    private DepositSlot depositSlot;
    private BankDatabase bankDatabase;
   
    private static final int BALANCE_INQUIRY = 1;
    private static final int WITHDRAWAL = 2;
    private static final int DEPOSIT = 3;
    private static final int EXIT = 4;
   
    public ATM()
    {
        userAuthenticated = false;
        currentAccountNumber = 0;
        screen = new Screen();
        keypad = new Keypad();
        cashDispenser = new CashDispenser();
        depositSlot = new DepositSlot();
        bankDatabase = new BankDatabase();
       
    }
   
    public void run()
    {
        while ( true )
        {
            while ( !userAuthenticated )
            {
                screen.displayMessageLine( "\nWelcome!" );
                authenticateUser();
            }
           
            performTransactions();
            userAuthenticated = false;
            currentAccountNumber = 0;
            screen.displayMessageLine( "\nThank you! Goodbye!" );
        }
    }
   
    private void authenticateUser()
    {
        screen.displayMessage( "\nPlease enter your account number: " );
        int accountNumber = keypad.getInput();
        screen.displayMessage( "\nEnter your PIN: " );
        int pin = keypad.getInput();
       
        userAuthenticated =
           bankDatabase.authenticateUser( accountNumber, pin );
       
        if ( userAuthenticated )
        {
            currentAccountNumber = accountNumber;
        }
        else
        {
            screen.displayMessageLine("Invalid account number or PIN. Please try again." );
        }
    }
   
    private void performTransactions()
    {
        Transaction currentTransaction = null;
        boolean userExited = false;
       
        while ( !userExited )
        {
            int mainMenuSelection = displayMainMenu();
           
            switch ( mainMenuSelection )
            {
                case BALANCE_INQUIRY:
                case WITHDRAWAL:
                case DEPOSIT:
                     currentTransaction = createTransaction( mainMenuSelection );
               
                     currentTransaction.execute();
                     break;
                case EXIT:
                    screen.displayMessageLine( "\nExiting the system..." );
                    userExited = true;
                    break;
                default:
                    screen.displayMessageLine("\nYou did not enter a valid selection. Try again." );
                    break;
            }
        }
    }
   
    private int displayMainMenu()
    {
        screen.displayMessageLine( "\nMain menu:" );
        screen.displayMessageLine( "1 - View my balance" );
        screen.displayMessageLine( "2 - Withdraw cash" );
        screen.displayMessageLine( "3 - Deposit funds" );
        screen.displayMessageLine( "4 - Exit\n" );
        screen.displayMessage( "Enter a choice: " );
        return keypad.getInput();
    }
   
    private Transaction createTransaction( int type )
    {
        Transaction temp = null;
       
        switch ( type )
        {
            case BALANCE_INQUIRY:
                temp = new BalanceInquiry( currentAccountNumber, screen, bankDatabase );
                break;
            case WITHDRAWAL:
                temp = new Withdrawal( currentAccountNumber, screen, bankDatabase, keypad, cashDispenser );
                break;
            case DEPOSIT:
                temp = new Deposit( currentAccountNumber, screen, bankDatabase, keypad, depositSlot );
                break;
        }
       
        return temp;
    }
}
  • Class Screen
public class Screen
{
    public void displayMessage( String message )
    {
        System.out.print( message );
    }
   
    public void displayMessageLine( String message )
    {
        System.out.println( message );
    }
   
    public void displayDollarAmount( double amount )
    {
        System.out.printf( "$%,.2f", amount );
    }
   
}
  • Class Keypad
import java.util.Scanner;
 
public class Keypad
{
    private Scanner input;
   
    public Keypad()
    {
        input = new Scanner( System.in );
    }
   
    public int getInput()
    {
        return input.nextInt();
    }
   
}
  • Class Account
public class Account
{
    private int accountNumber;
    private int pin;
    private double availableBalance;
    private double totalBalance;
   
    public Account( int theAccountNumber, int thePIN,
       double theAvailableBalance, double theTotalBalance )
    {
        accountNumber = theAccountNumber;
        pin = thePIN;
        availableBalance = theAvailableBalance;
        totalBalance = theTotalBalance;
    }
   
    public boolean validatePIN( int userPIN )
    {
        if ( userPIN == pin ) return true;
        else return false;
    }
   
    public double getAvailableBalance()
    {
        return availableBalance;
    }
   
    public double getTotalBalance()
    {
        return totalBalance;
    }
   
    public void credit( double amount )
    {
        totalBalance += amount;
    }
   
    public void debit( double amount )
    {
        availableBalance -= amount;
        totalBalance -= amount;
    }
   
    public int getAccountNumber()
    {
        return accountNumber;
    }
   
}
  • Class BankDatabase
public class BankDatabase
{
    private Account[] accounts;
   
    public BankDatabase()
    {
        accounts = new Account[ 2 ];
       
        accounts[ 0 ] = new Account( 12345, 54321, 1000.0, 1200.0 );
        accounts[ 1 ] = new Account( 98765, 56789, 200.0, 200.0 );
    }
   
    private Account getAccount( int accountNumber )
    {
        for ( Account currentAccount : accounts )
        {
            if ( currentAccount.getAccountNumber() == accountNumber ) return currentAccount;
        }
       
        return null;
    }
   
    public boolean authenticateUser( int userAccountNumber, int userPIN )
    {
        Account userAccount = getAccount( userAccountNumber );
       
        if ( userAccount != null )
            return userAccount.validatePIN( userPIN );
        else
            return false;
    }
   
    public double getAvailableBalance( int userAccountNumber )
    {
        return getAccount( userAccountNumber ).getAvailableBalance();
    }
   
    public double getTotalBalance( int userAccountNumber )
    {
        return getAccount( userAccountNumber ).getTotalBalance();
    }
   
    public void credit( int userAccountNumber, double amount )
    {
        getAccount( userAccountNumber ).credit( amount );
    }
   
    public void debit( int userAccountNumber, double amount )
    {
        getAccount( userAccountNumber ).debit( amount );
    }
}
  • Class CashDispenser
public class CashDispenser
{
    private final static int INITIAL_COUNT = 500;
    private int count;
   
    public CashDispenser()
    {
        count = INITIAL_COUNT;
    }
   
    public void dispenseCash( int amount )
    {
        int billsRequired = amount / 20;
        count -= billsRequired;
       
    }
   
    public boolean isSufficientCashAvailable( int amount )
    {
        int billsRequired = amount / 20;
       
        if ( count >= billsRequired )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
  • Abstract Class Transaction
public abstract class Transaction
{
    private int accountNumber;
    private Screen screen;
    private BankDatabase bankDatabase;
   
    public Transaction( int userAccountNumber, Screen atmScreen, BankDatabase atmBankDatabase )
    {
        accountNumber = userAccountNumber;
        screen = atmScreen;
        bankDatabase = atmBankDatabase;
    }
   
    public int getAccountNumber()
    {
        return accountNumber;
    }
   
    public Screen getScreen()
    {
        return screen;
    }
   
    public BankDatabase getBankDatabase()
    {
        return bankDatabase;
    }
   
    abstract public void execute();
}
  • Class Withdrawal
public class Withdrawal extends Transaction
{
    private int amount;
    private Keypad keypad;
    private CashDispenser cashDispenser;
   
    private final static int CANCELED = 6;
   
    public Withdrawal( int userAccountNumber, Screen atmScreen,
        BankDatabase atmBankDatabase, Keypad atmKeypad,
        CashDispenser atmCashDispenser )
    {
        super( userAccountNumber, atmScreen, atmBankDatabase );
       
        keypad = atmKeypad;
        cashDispenser = atmCashDispenser;
    }
   
    @Override
    public void execute()
    {
        boolean cashDispensed = false;
        double availableBalance;
       
        BankDatabase bankDatabase = getBankDatabase();
        Screen screen = getScreen();
       
        do
        {
            amount = displayMenuOfAmounts();
           
            if ( amount != CANCELED )
            {
                availableBalance = bankDatabase.getAvailableBalance( getAccountNumber() );
               
                if ( amount <= availableBalance )
                {
                    if ( cashDispenser.isSufficientCashAvailable( amount ) )
                    {
                        bankDatabase.debit( getAccountNumber(), amount );
                       
                        cashDispenser.dispenseCash( amount );
                        cashDispensed = true;
                       
                        screen.displayMessageLine( "\nYour cash has been" +
                            " dispensed. Please take your cash now." );
                    }
                    else
                        screen.displayMessageLine(
                            "\nInsufficient cash available in the ATM." +
                            "\n\nPlease choose a smaller amount." );
                }
                else
                {
                    screen.displayMessageLine(
                        "\nInsufficient funds in your account." +
                        "\n\nPlease choose a smaller amount." );
                }
            }
            else
            {
                screen.displayMessageLine( "\nCanceling transaction..." );
                return;
            }
        } while ( !cashDispensed );
    }
   
    private int displayMenuOfAmounts()
    {
        int userChoice = 0;
       
        Screen screen = getScreen();
       
        int[] amounts = { 0, 20, 40, 60, 100, 200 };
       
        while ( userChoice == 0 )
        {
            screen.displayMessageLine( "\nWithdrawal Menu:" );
            screen.displayMessageLine( "1 - $20" );
            screen.displayMessageLine( "2 - $40" );
            screen.displayMessageLine( "3 - $60" );
            screen.displayMessageLine( "4 - $100" );
            screen.displayMessageLine( "5 - $200" );
            screen.displayMessageLine( "6 - Cancel transaction" );
            screen.displayMessage( "\nChoose a withdrawal amount: " );
           
            int input = keypad.getInput();
           
            switch ( input )
            {
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                    userChoice = amounts[ input ];
                    break;
                case CANCELED:
                    userChoice = CANCELED;
                    break;
                default:
                    screen.displayMessageLine( "\nInvalid selection. Try again." );
            }
        }
       
        return userChoice;
    }
}
  • Class Deposit
public class Deposit extends Transaction
{
    private double amount;
    private Keypad keypad;
    private DepositSlot depositSlot;
    private final static int CANCELED = 0;
   
    public Deposit( int userAccountNumber, Screen atmScreen,
        BankDatabase atmBankDatabase, Keypad atmKeypad,
        DepositSlot atmDepositSlot )
    {
        super( userAccountNumber, atmScreen, atmBankDatabase );
       
        keypad = atmKeypad;
        depositSlot = atmDepositSlot;
    }
   
    @Override
    public void execute()
    {
        BankDatabase bankDatabase = getBankDatabase();
        Screen screen = getScreen();
       
        amount = promptForDepositAmount();
       
        if ( amount != CANCELED )
        {
            screen.displayMessage( "\nPlease insert a deposit envelope containing " );
            screen.displayDollarAmount( amount );
            screen.displayMessageLine( "." );
           
            boolean envelopeReceived = depositSlot.isEnvelopeReceived();
           
            if ( envelopeReceived )
            {
                screen.displayMessageLine( "\nYour envelope has been " +
                    "received.\nNOTE: The money just deposited will not " +
                    "be available until we verify the amount of any " +
                    "enclosed cash and your checks clear." );
                bankDatabase.credit( getAccountNumber(), amount );
            }
            else
            {
                screen.displayMessageLine( "\nYou did not insert an " +
                    "envelope, so the ATM has canceled your transaction." );
            }
        }
        else
        {
            screen.displayMessageLine( "\nCanceling transaction..." );
        }
    }
   
    private double promptForDepositAmount()
    {
        Screen screen = getScreen();
       
        screen.displayMessage( "\nPlease enter a deposit amount in " +
            "CENTS (or 0 to cancel): " );
        int input = keypad.getInput();
       
        if ( input == CANCELED )
            return CANCELED;
        else
            return ( double ) input / 100;
    }
}
  • Class DepositSlot
public class DepositSlot
{
    public boolean isEnvelopeReceived()
    {
        return true;
    }
}
  • Class BalanceInquiry
public class BalanceInquiry extends Transaction
{
    public BalanceInquiry( int userAccountNumber, Screen atmScreen, BankDatabase atmBankDatabase )
    {
        super( userAccountNumber, atmScreen, atmBankDatabase );
    }
   
    @Override
    public void execute()
    {
        BankDatabase bankDatabase = getBankDatabase();
        Screen screen = getScreen();
   
        double availableBalance = bankDatabase.getAvailableBalance( getAccountNumber() );
   
        double totalBalance = bankDatabase.getTotalBalance( getAccountNumber() );
   
        screen.displayMessageLine( "\nBalance Information:" );
        screen.displayMessage( " - Available balance: " );
        screen.displayDollarAmount( availableBalance );
        screen.displayMessage( "\n - Total balance: " );
        screen.displayDollarAmount( totalBalance );
        screen.displayMessageLine( "" );
    }
}
  • Class ATMCaseStudy
public class ATMCaseStudy
{
    public static void main( String[] args )
    {
        ATM theATM = new ATM();
        theATM.run();
    }
}

Untuk implementasinya, berikut saya tampilkan beberapa contohnya:














Tidak ada komentar:

Posting Komentar