How to separate this code into 6 classes?

Các bạn có thể giúp mình chia cái code này ra thành 6 Classes (Printer, PrinterList, PrinterListUse, Menu, I_List(interface list), I_Menu(interface menu)) được không ạ?
Can you help me separate this code into 6 classes (Printer, PrinterList, PrinterListUse, Menu, I_List(interface list), I_Menu(interface menu)) please?

//Printer.java
public class Printer implements Comparable<Printer> {
  
   private String modelNumber;
   private String type;
   private boolean isColor;
   private double price;
   private static int count = 0; // number of objects created used to generate the next model number
  
   // constructor to initialize the object attributes
   public Printer(String type, boolean isColor, double price)
   {
       count++; // increment the count
       // generate the next model number
       this.modelNumber = "PR"+String.format("%03d", count); // returns the count as a string with width 3left- padded by 0 (if number of digits in count < 3)
       // initialize the fields
       this.type = type;
       this.isColor = isColor;
       this.price = price;
   }
  
   // setters
   public void setType(String type)
   {
       this.type = type;
   }

   public void setColored(boolean isColor)
   {
       this.isColor = isColor;
   }
  
   public void setPrice(double price)
   {
       this.price = price;
   }
  
   // getters
   public String getModelNumber()
   {
       return modelNumber;
   }
  
   public String getType()
   {
       return type;
   }
  
   public boolean isColored()
   {
       return isColor;
   }
  
   public double getPrice()
   {
       return price;
   }
  
   // method that compares 2 printers based on their price and type and returns
   // -1, if this printer < other printer (less price or same price and type alphabetically lower)
   // 0 , if both printer are equal (same price and type)
   // 1, if this printer > other printer (higher price or same price and type alphabetically higher)
   @Override
   public int compareTo(Printer other) {
       // first compare based on price
       if(price < other.price)
           return -1;
       else if(price > other.price)
           return 1;
       else
       {
           // same price then compare based on type
           return(type.compareTo(other.type));
       }
   }
  
   // return string representation of the printer
   public String toString()
   {
       return String.format("%-20s%-30s%-10s%-10.2f",modelNumber,type,isColor,price);
   }
  
}
//end of Printer.java
// PrinterDriver.java
import java.util.ArrayList;
import java.util.Scanner;

public class PrinterDriver {
  
   // method that compares 2 printers based on their price and type and returns
   // -1, if this printer < other printer (less price or same price and type alphabetically lower)
   // 0 , if both printer are equal (same price and type)
   // 1, if this printer > other printer (higher price or same price and type alphabetically higher)
   @Override
   public int compareTo(Printer other) {
       // first compare based on price
       if(price < other.price)
           return -1;
       else if(price > other.price)
           return 1;
       else
       {
           // same price then compare based on type
           return(type.compareTo(other.type));
       }
   }
  
   // return string representation of the printer
   public String toString()
   {
       return String.format("%-20s%-30s%-10s%-10.2f",modelNumber,type,isColor,price);
   }
  
   // helper method to return the index of printer with modelNumber in the list if found else return -1
   private static int getPrinterIndex(ArrayList<Printer> printerList, String modelNumber)
   {
       // loop over the list
       for(int i=0;i<printerList.size();i++)
       {
           if(printerList.get(i).getModelNumber().equals(modelNumber)) // printer found
               return i;
       }
      
       return -1; // printer not found
   }
  
  
   // helper method to sort the list of printers in descending oder of price and then descending oder of type and display the list
   private static void sortAndDisplay(ArrayList<Printer> printerList)
   {
       if(printerList.size() == 0) // empty list
           System.out.println("No printers exist");
       else
       {
           // sort the list
           for(int i=0;i<printerList.size()-1;i++)
           {
               for(int j=0;j<printerList.size()-1-i;j++)
               {
                   if(printerList.get(j).compareTo(printerList.get(j+1)) < 0)
                   {
                       Printer temp = printerList.get(j);
                       printerList.set(j, printerList.get(j+1));
                       printerList.set(j+1, temp);
                   }
               }
           }
           // display the sorted list
           System.out.printf("%-20s%-30s%-10s%-10s\n","Model Number","Type","Colored","Price");  
           for(int i=0;i<printerList.size();i++)
           {
               System.out.println(printerList.get(i));
           }
       }
   }
  
   public static void main(String[] args) {

       // list to store printers
       ArrayList<Printer> printerList = new ArrayList<Printer>();
       String modelNumber, type, coloredInput;
       double price;
       int choice;
       Scanner scan = new Scanner(System.in);
       // loop that continues till the user wants
       do
       {
           // display the menu
           System.out.println("1. Add new Printer");
           System.out.println("2. Update printer");
           System.out.println("3. Print the list");
           System.out.println("4. Exit");
           System.out.print("Enter your choice(1-4): ");
           choice = scan.nextInt(); // input of choice
          
           // validate choice and re-prompt until valid
           while(choice < 1 || choice > 4)
           {
               System.out.println("Invalid choice. Re-enter: ");
               choice = scan.nextInt();
           }
          
           scan.nextLine();
          
           if(choice == 1) // add a new printer
           {
               // input the details
               System.out.print("Type: ");
               type = scan.nextLine();
              
               System.out.print("Is it colored?(yes/no) ");
               coloredInput = scan.nextLine();
               while(!coloredInput.equalsIgnoreCase("yes") && !coloredInput.equalsIgnoreCase("no"))
               {
                   System.out.print("Invalid input. Please enter yes or no. Re-enter: ");
                   coloredInput = scan.nextLine();
               }
              
               System.out.print("Price: ");
               price = scan.nextDouble();
              
               while(price <= 0)
               {
                   System.out.print("Invalid price.Price must be greater than 0. Re-enter");
                   price = scan.nextDouble();
               }
              
               scan.nextLine();
              
               // create and add the printer to the end of the list
               if(coloredInput.equalsIgnoreCase("yes"))
                   printerList.add(new Printer( type, true, price));
               else
                   printerList.add(new Printer( type, false, price));
               System.out.println("Printer with model number: "+printerList.get(printerList.size()-1).getModelNumber()+" added successfully");
           }
           else if(choice == 2) // update printer
           {
               // input model number
               System.out.print("Model Number: ");
               modelNumber = scan.nextLine();
              
               int index = getPrinterIndex(printerList, modelNumber);
              
               // validate modelNumber is present in the list
               if(index == -1)
                   System.out.println("No printer with model number: "+modelNumber+" exists");
               else
               {
                   // if present, input the updated details
                   System.out.print("Enter the updated type: ");
                   type = scan.nextLine();
                   System.out.print("Is it colored? (yes/no) ");
                   coloredInput = scan.nextLine();
                   while(!coloredInput.equalsIgnoreCase("yes") && !coloredInput.equalsIgnoreCase("no"))
                   {
                       System.out.print("Invalid input. Please enter yes or no. Re-enter: ");
                       coloredInput = scan.nextLine();
                   }
                  
                   System.out.print("Updated Price: ");
                   price = scan.nextDouble();
                  
                   while(price <= 0)
                   {
                       System.out.print("Invalid price.Price must be greater than 0. Re-enter");
                       price = scan.nextDouble();
                   }
                  
                   scan.nextLine();
                  
                   // update the fields of the printer
                   printerList.get(index).setType(type);
                   printerList.get(index).setPrice(price);
                   if(coloredInput.equalsIgnoreCase("yes"))
                       printerList.get(index).setColored(true);
                   else
                       printerList.get(index).setColored(false);
                   System.out.println("Printer with model number: "+modelNumber+" updated successfully");
               }
           }
           else if(choice == 3) // sort and display
           {
               sortAndDisplay(printerList);
           }
           System.out.println();
       }while(choice != 4);
      
   }


}

//end of PrinterDriver.java

Mình nghĩ bạn có thể tự chia code thành 6 class như trên miễn là bạn hiểu được code của bạn đang viết gì và hiểu được bộ năm nguyên tắc thiết kế trong OOP - SOLID (S.O.L.I.D) là được:

P/s: Engrisk version: I think you can separate your codes into 6 classes that you mentioned by yourself if you know what your codes are doing and understand The 5 principles of Object Oriented Design a.k.a SOLID.

4 Likes

Hi there,

First, welcome to DNH!

Regarding your question:

Yes, we can separate that code for you, but let me ask you this question first: Can you give us any reason why would we do your homework for you? :slight_smile:

6 Likes

Not a homework. It’s just for me to refer

Alright, let’s try this way, can you show us your attempt first? You may learn more if you do so.

P/s: Did you write this code?

4 Likes

No bro. I refer this code on the internet. I tried but it doesn’t work. Can you separate it first for me to refer? Then I’ll practice the other codes

You said you tried right? Can you show me your attempt?
As I mentioned before, it is better for you if you do so, since I can show you where you should improve. My purpose here is to give you a chance to improve yourself.
It is actually nonsense for us to just waste our time in refactoring this horrible code without any reason.

Now, it is up to you, either you wait for another guy who is willing to spend time on this nonsense task, or you show me your attempt and I will correct you. I suggest you to chose the 2nd one :slight_smile:

P/s: other lesson for you, a conversation is a 2-way road. You share me something and I will share mine. Nothing is free at all.

P/s 2: I wonder who asked you to separate this code into 6 classes specifically, if it is not your teacher?

P/s 3: Are you the guy who asked this question also? :smiley:
https://www.chegg.com/homework-help/questions-and-answers/guys-develop-project-6-classes-printer-printerlist-printerlistuse-menu-imenu-interface-men-q53935214

5 Likes

Okay. I’ll send you later. Because I don’t work on laptop now

2 Likes

It is really good to know there is a platform to help you do the homework. I will refer it to other guys who seek for it here.

It seems a so-called expert answered your question here. Shall we close this topic @Nguyễn Việt Thiện? :wink:

Hidden content

Quà cho ai tìm kiếm kiến thức nhé :smiley:
Refactor thành 6 classes/interfaces kể trên là không hợp lý, khi PrinterListUse là vô dụng, I_List quá trừu tượng và đã có List interface trong java collection rồi.
Tớ refactor code trên thành code dưới đây. Có 1 số chú ý:

  1. Code này sử dụng lombok để làm ngắn gọn 1 số implement như tạo getter, tạo all argument constructor, implement nhanh builder pattern, implement nhanh value object pattern.
  2. Code này sử dụng nhiều java 8 Optional và Stream API. Nếu như bạn không quen lắm với nó, chắc bạn phải tìm hiểu thêm nhiều.
  3. Tớ không áp dụng kiến trúc nào vào trong code này, chỉ đơn giản là tách các đơn vị ra theo OOP, tuân theo SOLID thôi. Tớ hi vọng nó là ví dụ tốt để bạn nhìn ra được từng method, từng object đều có 1 nhiệm vụ, và chỉ 1 nhiệm vụ thôi. Implementation cũ đã dồn quá nhiều nhiệm vụ vào PrinterDriver (chắc anh bạn ở trên nhờ ai đó code hộ).
  4. Tớ có thêm code phòng ngừa cho 1 số component mới.
  5. 1 số concept có thể bạn chưa quen mà tớ có sử dụng trong code này: Builder pattern, Singleton pattern, Value Object, First class collection, và Strategy pattern.
  6. Trong code này, tớ hạn chế dùng if (chỉ dùng chủ yếu trong lập trình phòng ngừa, và tớ không dùng else), không dùng switch case (trừ trường hợp dùng nó trong factory method). Đó là các rule mà tớ luôn theo. Tớ tin rule này rất hữu ích.
  7. Trong code này, tất cả các object đều không thể chỉnh sửa (immutable). Đó là 1 concept rất quan trọng trong OOP, nó sẽ giúp giảm thiểu bug mà bạn có thể gặp.
Dưới đây là package structure

Còn đây là implement
PrinterApplication
package code.printer;

import java.util.ArrayList;

import code.printer.domain.first_class_collection.Printers;
import code.printer.menu.logic.AddNewPrinterOption;
import code.printer.menu.logic.SortAndDisplayOption;
import code.printer.menu.logic.UpdatePrinterInfoOption;
import code.printer.menu.model.Menu;
import code.printer.menu.model.MenuElement;

public class PrinterApplication {

  public static void main(String[] args) {

    // list to store printers
    Printers printers = new Printers(new ArrayList<>());
    Menu menu = Menu
        .builder()
        .addElement(new MenuElement(1, "Add new Printer", new AddNewPrinterOption()))
        .addElement(new MenuElement(2, "Update printer", new UpdatePrinterInfoOption()))
        .addElement(new MenuElement(3, "Print the list", new SortAndDisplayOption()))
        .addElement(new MenuElement(4, "Exit", e -> System.exit(0)))
        .build();

    while (true) {
      menu.choose().execute(printers);
    }
  }
}
MenuElement
package code.printer.menu.model;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import code.printer.exception.MenuBuildFailedException;
import code.printer.service.ConsoleScannerService;
import lombok.Builder;
import lombok.Singular;

@Builder
public class Menu {

  private final ConsoleScannerService scanner = ConsoleScannerService.getInstance();
  @Singular("addElement")
  private List<MenuElement> menu;

  public Menu(List<MenuElement> menu) {
    Set<Integer> menuOptions = menu.stream().map(MenuElement::getId).collect(Collectors.toSet());
    if (menuOptions.size() != menu.size()) {
      throw new MenuBuildFailedException("Duplicated option in the menu.");
    }
    this.menu = menu.stream().sorted().collect(Collectors.toList());
  }

  private void printMenu() {
    menu.stream()
        .map(menuElement -> String.format("%d. %s", menuElement.getId(), menuElement.getDescription()))
        .forEachOrdered(System.out::println);

    System.out.print(String.format("Enter your choice (%d-%d): ", minOption(), maxOption()));
  }

  private int minOption() {
    if (menu.size() == 0) {
      return 0;
    }
    return menu.get(0).getId();
  }

  private int maxOption() {
    if (menu.size() == 0) {
      return 0;
    }
    return menu.get(menu.size() - 1).getId();
  }

  public MenuElement choose() {
    printMenu();

    int choice = scanner.scanIntBetween(minOption(), maxOption());
    if (choice == 0) {
      return MenuElement.emptyElement();
    }

    return menu.stream()
        .filter(e -> e.getId() == choice)
        .findAny()
        .orElse(MenuElement.emptyElement());
  }
}
Menu
package code.printer.menu.model;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import code.printer.exception.MenuBuildFailedException;
import code.printer.service.ConsoleScannerService;
import lombok.Builder;
import lombok.Singular;

@Builder
public class Menu {

  private final ConsoleScannerService scanner = ConsoleScannerService.getInstance();
  @Singular("addElement")
  private List<MenuElement> menu;

  public Menu(List<MenuElement> menu) {
    Set<Integer> menuOptions = menu.stream().map(MenuElement::getId).collect(Collectors.toSet());
    if (menuOptions.size() != menu.size()) {
      throw new MenuBuildFailedException("Duplicated option in the menu.");
    }
    this.menu = menu.stream().sorted().collect(Collectors.toList());
  }

  private void printMenu() {
    menu.stream()
        .map(menuElement -> String.format("%d. %s", menuElement.getId(), menuElement.getDescription()))
        .forEachOrdered(System.out::println);

    System.out.print(String.format("Enter your choice (%d-%d): ", minOption(), maxOption()));
  }

  private int minOption() {
    if (menu.size() == 0) {
      return 0;
    }
    return menu.get(0).getId();
  }

  private int maxOption() {
    if (menu.size() == 0) {
      return 0;
    }
    return menu.get(menu.size() - 1).getId();
  }

  public MenuElement choose() {
    printMenu();

    int choice = scanner.scanIntBetween(minOption(), maxOption());
    if (choice == 0) {
      return MenuElement.emptyElement();
    }

    return menu.stream()
        .filter(e -> e.getId() == choice)
        .findAny()
        .orElse(MenuElement.emptyElement());
  }
}
MenuElement
package code.printer.menu.model;

import java.util.function.Consumer;

import code.printer.domain.first_class_collection.Printers;
import lombok.Value;

@Value
public class MenuElement implements Comparable<MenuElement> {
  private static final MenuElement EMPTY = new MenuElement(0, "", printerList -> {});

  int id;
  String description;
  Consumer<Printers> optionExecution;

  @Override
  public int compareTo(MenuElement that) {
    return this.id - that.id;
  }

  public void execute(Printers printerList) {
    optionExecution.accept(printerList);
  }

  public static MenuElement emptyElement() {
    return EMPTY;
  }
}
AddNewPrinterOption
package code.printer.menu.logic;

import java.util.function.Consumer;

import code.printer.domain.Printer;
import code.printer.domain.first_class_collection.Printers;
import code.printer.service.ConsoleScannerService;

public class AddNewPrinterOption implements Consumer<Printers> {

  private ConsoleScannerService consoleScannerService = ConsoleScannerService.getInstance();

  @Override
  public void accept(Printers printers) {
    Printer printer = new Printer(scanType(), scanColor().equalsIgnoreCase("yes"), scanPrice());
    printers.add(printer);
    System.out.println("Printer with model number " + printer.getModelNumber() + " added successfully");
  }

  private String scanType() {
    System.out.print("Type: ");
    return consoleScannerService.scanType();
  }

  private double scanPrice() {
    System.out.print("Price: ");
    return consoleScannerService.scanPrice();
  }

  private String scanColor() {
    System.out.print("Color: ");
    return consoleScannerService.scanColor();
  }
}

SortAndDisplayOption
package code.printer.menu.logic;

import java.util.function.Consumer;

import code.printer.domain.first_class_collection.Printers;

public class SortAndDisplayOption implements Consumer<Printers> {

  @Override
  public void accept(Printers printers) {
    System.out.printf("%-20s%-30s%-10s%-10s\n", "Model Number", "Type", "Colored", "Price");
    printers.sort().traverseThroughEachElement(printer -> System.out.println(printer.toFormatedString("%-20s%-30s%-10s%-10.2f")));
  }
}

ConsoleScannerService
package code.printer.service;

import static java.util.Arrays.asList;

import java.util.List;
import java.util.Scanner;

public class ConsoleScannerService {
  
  private static final List<String> VALID_COLOR_INPUT_OPTIONS = asList("yes", "no");

  private static ConsoleScannerService INSTANCE;
  private Scanner scanner = new Scanner(System.in);

  private ConsoleScannerService() {
    // Do nothing but hiding this constructor
  }

  public static ConsoleScannerService getInstance() {
    if (INSTANCE == null) {
      synchronized (ConsoleScannerService.class) {
        if (INSTANCE == null) {
          INSTANCE = new ConsoleScannerService();
        }
      }
    }

    return INSTANCE;
  }

  public String scanType() {
    return scanner.nextLine();
  }

  public double scanPrice() {
    double price = scanner.nextDouble();

    while (price <= 0) {
      System.out.print("Invalid price. Price must be greater than 0. Re-enter");
      price = scanner.nextDouble();
    }
    return price;
  }

  public String scanColor() {
    System.out.print("Is it colored? (yes/no) ");

    String coloredInput = scanType();
    while (!VALID_COLOR_INPUT_OPTIONS.contains(coloredInput.toLowerCase())) {
      System.out.print("Invalid input. Please enter yes or no. Re-enter: ");
      coloredInput = scanner.nextLine();
    }
    return coloredInput;
  }

  public String scanModelNumber() {
    return scanner.nextLine();
  }
  
  public int scanIntBetween(int min, int max) {
    if(min > max) {
      throw new IllegalArgumentException("Cannot get an integer between " + min + " and " + max);
    }
    
    int choice = scanner.nextInt(); // input of choice

    // validate choice and re-prompt until valid
    while (choice < min || choice > max) {
      System.out.println("Invalid choice. Re-enter: ");
      choice = scanner.nextInt();
    }

    scanner.nextLine();
    return choice;
  }

}

Printer
package code.printer.domain;

import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;

@Getter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
public class Printer implements Comparable<Printer> {

  private static int count = 0; // number of objects created used to generate the next model number

  private String modelNumber;
  private String type;
  private boolean isColor;
  private double price;

  /**
   * Constructor to initialize the object attributes. The modelNumber will be generated automatically.
   * 
   * @param type The printer type
   * @param isColor true if it is colored printer
   * @param price The printer's price
   */
  public Printer(String type, boolean isColor, double price) {
    this("PR" + String.format("%03d", ++count), type, isColor, price);
  }

  /**
   * method that compares 2 printers based on their price and type and returns
   * 
   * @return
   *         -1 if this printer < other printer (less price or same price and type alphabetically lower)<br>
   *         0 if both printer are equal (same price and type)<br>
   *         1 if this printer > other printer (higher price or same price and type alphabetically higher)<br>
   */
  @Override
  public int compareTo(Printer that) {
    // first compare based on price
    if (this.price < that.price) {
      return -1;
    }

    if (this.price > that.price) {
      return 1;
    }

    // same price then compare based on type
    if (this.type == null && that.type == null) {
      return 0;
    }

    if (this.type == null) {
      return -1;
    }

    return this.type.compareTo(that.type);
  }

  /**
   * return string representation of the printer
   * 
   * @param format
   * @return All printer's information, including (modelNumber, type, isColor, price) in that order, in a particular format
   */
  public String toFormatedString(String format) {
    return String.format(format, modelNumber, type, isColor, price);
  }
}


Printers
package code.printer.domain.first_class_collection;

import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import code.printer.domain.Printer;
import code.printer.exception.PrinterLogicException;
import lombok.Value;

@Value
public class Printers {

  List<Printer> printerList;

  public void add(Printer printer) {
    if (printer == null) {
      throw new IllegalArgumentException("Printer object cannot be null");
    }

    if (hasModel(printer.getModelNumber())) {
      throw new PrinterLogicException("This model already exists: " + printer.getModelNumber());
    }

    printerList.add(printer);
  }

  public Printers sort() {
    return new Printers(printerList.stream().sorted().collect(Collectors.toList()));
  }

  public void traverseThroughEachElement(Consumer<Printer> action) {
    printerList.stream().forEach(action);
  }

  public boolean hasModel(String modelNumber) {
    return printerList.stream().map(Printer::getModelNumber).anyMatch(printerModel -> printerModel.equals(modelNumber));
  }

  public void upsert(Printer printer) {
    if (printer == null) {
      throw new IllegalArgumentException("Printer cannot be null");
    }

    printerList.removeIf(e -> e.getModelNumber().equals(printer.getModelNumber()));
    add(printer);
  }
}
MenuBuildFailedException
package code.printer.exception;

public class MenuBuildFailedException extends RuntimeException {

  private static final long serialVersionUID = 1L;

  public MenuBuildFailedException(String message) {
    super(message);
  }
}

PrinterLogicException
package code.printer.exception;

public class PrinterLogicException extends RuntimeException {

  private static final long serialVersionUID = 1L;

  public PrinterLogicException(String message) {
    super(message);
  }
}

4 Likes

A post was split to a new topic: How to be better at Java?

Bàn luận tiếp vui lòng qua topic này
For further discussion, please use this topic

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?