2015-06-27 18 views
2

這是包含方法的類calculateTotalTipOnTable()calculateTotalTipOnTable方法使用Customer類中的方法,並且該方法在測試時沒有問題我認爲某種方式c​​alculateTotalTipOnTable操作雙端隊列(當我測試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()); 
    } 
} 

回答

2

你是不是在這裏創建重複:

public TableDeque duplicate() 
{ 
    TableDeque duplicate1 = new TableDeque(); 
    duplicate1 = this; 
    return duplicate1; 
} 

您在返回refernce到原來的實例。

取而代之的是duplicate方法,你可以使用一個拷貝構造函數:

public TableDeque (TableDeque copy) 
{ 
    // copy properties from the source TableDeque to the new instance 
} 

然後,而不是調用

duplicate = this.duplicate(); 

你會打電話給

duplicate = new TableDeque(this); 
+0

我想做你說的,但我不明白「從源TableDeque複製到新實例的屬性」意味着沒有使用「=」。我如何複製原構造函數所具有的所有數據? –

+0

@정구현通過在新的構造函數的第一行中調用this(),可以使用與原始構造函數相同的代碼初始化新實例。但是您必須將原始實例的所有節點複製到新實例。 – Eran

+0

我真的很感謝你的回覆,我嘗試過...但我仍然不知道如何複製Deque .....;(................... ......... –

相關問題