2
這是包含方法的類calculateTotalTipOnTable()calculateTotalTipOnTable方法使用Customer類中的方法,並且該方法在測試時沒有問題我認爲某種方式calculateTotalTipOnTable操作雙端隊列(當我測試calculateTotalTipOnTable,它收縮TableDequeue的大小)莫名其妙我的一個方法改變了它的字段,即使當我自己複製時
package com.kristopher.restaurantmanager;
import sofia.graphics.RectangleShape;
public class TableDeque
extends RectangleShape
implements Deque<Customer>
{
// ~ Instance/static variables ............................................
private Node<Customer> head;
private Node<Customer> tail;
private int size;
private double totalDue = 0;
private double totalTip = 0;
private boolean authorized;
private TableDeque duplicate;
/**
* Constructor of the TableDeque class.
*/
public TableDeque()
{
head = new Node<Customer>(null);
tail = new Node<Customer>(null);
head.join(tail);
size = 0;
this.setImage("table");
}
/**
* Insert a new Customer at the rear (the tail) of the Tabledequeue.
*
* @param value
* the Customer to insert.
*/
public void enqueueCustomerAtRear(Customer value)
{
Node<Customer> oldRear = tail.previous();
tail.previous().split();
oldRear.join((new Node<Customer>(value)).join(tail));
size++;
}
// ----------------------------------------------------------
/**
* Remove the Customer at the front (the head) of the deque.
*
* @return The Customer that was removed
*/
public Customer dequeueCustomerAtFront()
{
Node<Customer> oldFrontNext = head.next().next();
Node<Customer> oldFront = head.next();
head.next().split();
head.split();
head.join(oldFrontNext);
size--;
return oldFront.data();
}
// ----------------------------------------------------------
/**
* Insert a new Customer at the front (the head) of the deque.
*
* @param value
* the Customer to insert.
*/
public void enqueueCustomerAtFront(Customer value)
{
Node<Customer> oldFront = head.next();
head.split();
head.join((new Node<Customer>(value)).join(oldFront));
size++;
}
// ----------------------------------------------------------
/**
* Remove the Customer at the rear (the tail) of the deque.
*
* @return The Customer that was removed
*/
public Customer dequeueCustomerAtRear()
{
Node<Customer> oldRearPrevious = tail.previous().previous();
Node<Customer> oldRear = tail.previous();
oldRearPrevious.split();
oldRear.split();
oldRearPrevious.join(tail);
size--;
return oldRear.data();
}
// ----------------------------------------------------------
/**
* Get the Customer at the front (the head) of the deque. Does not alter the
* deque.
*
* @return the Customer at the front of the deque.
*/
public Customer frontCustomer()
{
return head.next().data();
}
// ----------------------------------------------------------
/**
* Get the Customer at the rear (the tail) of the deque. Does not alter the
* deque.
*
* @return the Customer at the rear of the deque.
*/
public Customer rearCustomer()
{
return tail.previous().data();
}
// ----------------------------------------------------------
/**
* Get the number of items in this deque. Does not alter the deque.
*
* @return The number of items this deque contains.
*/
public int size()
{
return size;
}
// ----------------------------------------------------------
/**
* Empty the deque.
*/
public void clear()
{
while (frontCustomer() != null)
{
dequeueCustomerAtRear();
}
}
// ----------------------------------------------------------
/**
* Returns a string representation of this deque. A deque's string
* representation is written as a comma-separated list of its contents (in
* front-to-rear order) surrounded by square brackets, like this:
*
* <pre>
* [koo, david, karl, tom]
* </pre>
* <p>
* An empty deque is simply <code>[]</code>.
* </p>
*
* @return Customer lists on a signle table.
*/
public String customerList()
{
String s = "[";
int count = 0;
Node<Customer> c = head.next();
while (c != tail)
{
if (count < size() - 1)
{
s = s + c.data().getName() + ", ";
c = c.next();
}
else
{
s = s + c.data().getName() + "]";
c = c.next();
}
count++;
}
return s;
}
// -----------------------------------------------------
// Table money process methods
// -----------------------------------------------------
// ----------------------------------------------------------
/**
* tableDue calculate the total due amount of the table. This method use
* duplicated information of the table not to hurt any stored value beside
* the double value totalDue
*
* @return total due on the table.
*/
public double tableDue()
{
duplicate = this.duplicate();
while (duplicate.size() != 0)
{
totalDue += duplicate.dequeueCustomerAtFront().getDueAmount();
}
duplicate = null;
return totalDue;
}
// ----------------------------------------------------------
// somehow this method change the table itself(not duplicated table.)
// has to be fixed
/**
* calculateTotalTipOnTable method calculate the total tip amount that
* customers gives you. This method must be called only when all of the
* customer has done payingProcess
*
* @return total tip amount on table
*/
public double calculateTotalTipOnTable()
{
duplicate = this.duplicate();
while (duplicate.size() != 0)
{
totalTip += duplicate.frontCustomer().totalTipAmount();
duplicate.dequeueCustomerAtFront();
}
duplicate = null;
return totalTip;
}
// ----------------------------------------------------------
/**
* This method will determine if it is okey to remove table based on the
* bollean value stored in this class, and customer class. This method count
* the number of customers that is already authorized(means they paid). If
* counts equal to the size of the deque, this table is authorized and ready
* to dismiss.
*
* @return name of the customer who didn't fully pay yet.
*/
public String payingProcess()
{
duplicate = this.duplicate();
int count = 0;
String str = "";
if (duplicate.size() != 0)
{
while (duplicate.size() != 0)
{
if (duplicate.frontCustomer().isPaid())
{
count++;
this.dequeueCustomerAtFront();
duplicate.dequeueCustomerAtFront();
}
else
{
str += duplicate.frontCustomer().getName();
duplicate.dequeueCustomerAtFront();
}
}
authorized = (count == this.size());
duplicate = null;
return str;
}
else
{
duplicate = null;
authorized = true;
return "table is empty";
}
}
// ----------------------------------------------------------
/**
* return boolean if this table is ready to be dismissed
*
* @return boolean authorized
*/
public boolean isPaid()
{
return authorized;
}
// ----------------------------------------------------------
/**
* this is the helper method to produce duplicate Table.
* @return duplicated table.
*/
public TableDeque duplicate()
{
TableDeque duplicate1 = new TableDeque();
duplicate1 = this;
return duplicate1;
}
**payingProcess method of Customer Class.**
public double payingProcess(double d, double t)
{
actualTip = t;
totalTip += t;
double x = d - this.getDueAmount();
if (d >= 0.0)
{
authorized = (x >= 0.0);
}
else
{
throw new IllegalStateException("negative value of payment");
}
if (authorized)
{
totalPayDue = 0;
paidAmount = paidAmount + d;
return x;
}
else
{
totalPayDue -= d;
paidAmount = paidAmount + d;
return Math.abs(x);
}
}
測試用例文件 錯誤部分>> //////的assertEquals(table.calculateTotalTipOnTable(),15.0); /// ///////////// assertEquals(customer1.totalTipAmount(),15.0); ////
package com.kristopher.restaurantmanager;
import junit.framework.TestCase;
public class TableDequeTests
extends TestCase
{
private TableDeque table;
private Customer customer1;
private Customer customer2;
private Customer customer3;
private Customer customer4;
private Food food1;
private Food food2;
private Food food3;
public void setUp()
{
table = new TableDeque();
customer1 = new Customer("Kristopher");// customer who don't order
customer2 = new Customer("Mike");// customer who order one food
customer3 = new Customer("Yilong");// customer who order two foods
customer4 = new Customer("Barnette");// customer who order three foods
food1 = new Food("Kimchi", 10.00);
food2 = new Food("Bulgogi", 20.00);
food3 = new Food("GamzaTang", 30.00);
// -------------------------------------------------------------------
customer2.setOrderedFood(food1);// Mike
customer3.setOrderedFood(food1);// Yilong
customer3.setOrderedFood(food2);
customer4.setOrderedFood(food1);// Barnette
customer4.setOrderedFood(food2);
customer4.setOrderedFood(food3);
}
// ----------------------------------------------------------
/**
* Test if tableDue method correctly caclulate the total due of the table.
*/
public void testTableDue()
{
table.enqueueCustomerAtFront(customer3);
assertEquals(table.tableDue(), 30.0, 0.0);
}
// ----------------------------------------------------------
/**
* This method must calculate the total tip on the table.
*/
public void testCalculateTotalTipOnTable()
{
table.enqueueCustomerAtFront(customer1);
table.enqueueCustomerAtFront(customer2);
customer1.payingProcess(0.0, 15.0);
customer2.payingProcess(0.0, 35.0);
assertEquals(50.0, table.calculateTotalTipOnTable());
}
// ----------------------------------------------------------
/**
* Testing if enqueueCustomerAtRear correctly enque at rear of the table
* deque.
*/
public void testTableForSingleCustomer()
{
table.enqueueCustomerAtFront(customer1);
assertEquals(table.size(), 1);
assertEquals(table.frontCustomer().getName(), "Kristopher");
Exception thrown = null;
try
{
table.rearCustomer().getOrderFood();
}
catch (Exception e)
{
thrown = e;
}
assertTrue(thrown instanceof IllegalStateException);
assertEquals(
thrown.getMessage(),
"This customer did not order any foods yet");
assertEquals(table.customerList(), "[Kristopher]");
assertEquals(table.tableDue(), 0.0, 0.0);
customer1.payingProcess(0.0, 15.0);
//////assertEquals(table.calculateTotalTipOnTable(), 15.0);////////////
//// assertEquals(customer1.totalTipAmount(), 15.0);////
assertEquals(table.payingProcess(), "table is empty");
assertTrue(table.isPaid());
}
}
我想做你說的,但我不明白「從源TableDeque複製到新實例的屬性」意味着沒有使用「=」。我如何複製原構造函數所具有的所有數據? –
@정구현通過在新的構造函數的第一行中調用this(),可以使用與原始構造函數相同的代碼初始化新實例。但是您必須將原始實例的所有節點複製到新實例。 – Eran
我真的很感謝你的回覆,我嘗試過...但我仍然不知道如何複製Deque .....;(................... ......... –