Наличных денег-снятие денег в банкомате


Я ищу отзыв комментарии (дизайн, производительность и т. д.) на основе постановки задачи:

Написать функцию CashWithDrawal в банкомате, который в зависимости от пользователя указанную сумму обходится без банкноты. Убедитесь, что следующие позаботились

  • Минимальное количество банкнот отпускаются
  • Наличие различных конфессий в банкомате сохраняется
  • Код должен быть гибким, чтобы заботиться о любом банке деноминации пока оно кратно 10
  • Код должен поддерживать параллельный вывод средств, т. е. два или более клиентов одновременно могут снимать деньги
  • Заботиться о исключительных ситуации

package com.assignment.atm;

import java.util.Scanner;


/**
 * The Class Main.
 */
public class Main
{

    /**
     * The main method.
     * 
     * @param args the arguments
     */
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.println("Enter Amount to be withdrawn: ");
        int amount = input.nextInt();
        if(amount%10!=0){
            System.out.println("Please enter the amount in multiples of 10");
        }
        else{
            ATM atm = new  ATM(amount);
            ATM.calcTotalCorpus();
            Thread t1 = new Thread(atm);
            t1.start();
            /*ATM.calcTotalCorpus();
            Thread t1 = new Thread(new ATM(1200));
            Thread t2 = new Thread(new ATM(2400));
            t1.start();
            t2.start();
            try{
            t2.sleep(2000);
            }
            catch(Exception e){
                //Sysout Exception trace
            }*/
        }




    }
}

package com.assignment.atm;


/**
 * The Class ATM.
 */
class ATM implements Runnable{

    /** The Constant Currency Denominations. */
    protected static final int[] currDenom = { 1000, 500, 100, 50 , 10 };

    /** The Number of Currencies of each type*/
    protected static int[] currNo = {1,4,2,2,10};

    /** The count. */
    protected  int[] count = { 0, 0, 0, 0 ,0};

    /** The total corpus. */
    protected static int totalCorpus = 0;

    /** The amount. */
    protected  int amount=0;

    /**
     * Instantiates a new aTM.
     * 
     * @param amount The Amount of type int
     */
    public ATM(int amount){
        this.amount=amount;
    }


    /**
     * Calc total corpus.
     */
    public static void calcTotalCorpus(){       
        for(int i = 0; i < currDenom.length; i++){
            totalCorpus=totalCorpus+currDenom[i]*currNo[i];
        }
    }

    /**
     * Withdraw cash.
     */
    public  synchronized  void  withdrawCash(){
        if(amount<=totalCorpus){
            for (int i = 0; i < currDenom.length; i++) {
                if (currDenom[i] <= amount) {//If the amount is less than the currDenom[i] then that particular denomination cannot be dispensed
                    int noteCount = amount / currDenom[i];
                    if(currNo[i]>0){//To check whether the ATM Vault is left with the currency denomination under iteration
                        //If the Note Count is greater than the number of notes in ATM vault for that particular denomination then utilize all of them 
                        count[i] = noteCount>=currNo[i]?currNo[i]:noteCount;
                        currNo[i] =  noteCount>=currNo[i]?0:currNo[i]- noteCount;
                        //Deduct the total corpus left in the ATM Vault with the cash being dispensed in this iteration
                        totalCorpus=totalCorpus-(count[i]*currDenom[i]);
                        //Calculate the amount that need to be addressed in the next iterations
                        amount = amount -(count[i]*currDenom[i]);
                    }                
                }
            }
            displayNotes();
            displayLeftNotes();

        }
        else{
            System.out.println("Unable to dispense cash at this moment for this big amount");
        }

    }

    /**
     * 
     * 
     */
    public void run()
    {
        withdrawCash();

    }

    /**
     * Display notes.
     */
    private void displayNotes(){
        for (int i = 0; i < count.length; i++) {
            if (count[i] != 0) {
                System.out.println(currDenom[i] + " * " + count[i] + " = "+ (currDenom[i] * count[i]));
            }
        }
    }

    /**
     * Display left notes.
     */
    private void displayLeftNotes(){
        for(int i = 0; i < currDenom.length; i++){
            System.out.println("Notes of "+currDenom[i]+" left are "+currNo[i]);
        }

    }
}


Комментарии
2 ответа

(1) API-это немного странно. Почему мне нужно вызвать некоторые статические методы, после того, как я instatiated объект и хотите уже использовать его? Банкомат атм = новый банкомат(сумма); банкомат.calcTotalCorpus();

(2) есть небольшой бардак с модификаторами доступа. Например, почему защищал ? защищенный тип int количество=0;
И почему этот метод ? общественного синхронизированы недействительными withdrawCash()

(3)Этот метод пустоту withdrawCash() полно комментариев, но было бы намного лучше разделить этот метод на более мелкие функции, чтобы сделать его более читабельным. Рассмотрим

public  synchronized  void  withdrawCash(){
if(isAmountSufficient()){
for (int i = 0; i < currDenom.length; i++) {
if (canDispenseDenomination()) {
getNoteCount();
if(canProceedWithIterations()){
doCalculations();
deductTotalCorpuse()
calculateAmmountForNextIteration();
}
}
}
displayNotes();
displayLeftNotes();

}
else{
reportInsufficientAmmount();
}

(4) Существует также некоторые нечетные синхронизации. Наличие 2 клиента означает, что у вас 2 темы, которые, однако, работать с одного банкомата в вашем случае у вас есть только один поток для одного банкомата и ни одновременный доступ к данному банкомату от разных заказчиков. Я бы сделал это в следующих способов:

 public class Consumer extends Thread {
private final ATM atm;
public Consumer (ATM atm) {this.atm = atm;}

public void Run() {
this.atm.dispense(10);
Thread.sleep(10);
this.atm.dispense(20);
}
}

public static void main(String[] args) {
ATM atm = new ATM(1000);
Consumer c1 = new Consumer(atm);
Consumer c2 = new Consumer(atm);
c1.Start();
c2.Start();
....
}

В dispsense() функция может реализовать логику от withdrawCash() функция.

8
ответ дан 28 августа 2011 в 07:08 Источник Поделиться

В этот тип проблемы (работа с деньгами), я бы рьяно сосредоточены прежде всего на исключительные случаи, а затем убедиться, что код хорошо структурирован и прост для понимания.

Первое, что ударило меня, было то, что у вас нет проверки на отрицательное число входных данных.

Если вы идете с классом в банкомате с суммой в конструктор, я хотел бы предложить, чтобы добавить проверку вводимых данных в конструкторе - для начала тестирования, что входной сигнал является положительным и кратным десяти. Если входной сигнал является недопустимым, то IllegalArgumentException (или ваш собственный подкласс она) летит.

Кроме того, я хотел сделать поле Сумма закрытый финал - тогда и менять весь остальной код (использовать переменный метод, чтобы отслеживать количество осталось утилизировать) и в итоге конструкция с учетом этих изменений. Это объясняется тем, что я предпочитаю дополнительный параноик с чувствительной, как эти данные.

2
ответ дан 30 августа 2011 в 08:08 Источник Поделиться