Project B-two
TASK DESCRIPTION
任务描述
This project requires students to write an Object Oriented solution for a given application, using all the concepts taught in the subject.
这个项目要求学生使用本课程所教的所有概念,为给定的应用程序编写一个面向对象的解决方案。
You may choose to complete this assessment with at most one (1) other person. To work as a pair; you and your partner MUST be in the same tutorial class. You will need to spend approx. 6 hours together working on the assessment (outside of tutorial hours). If you do not intend to spend this time working together – choose to complete the assessment on your own. Both partners must put in an equal amount of work and effort, or the group will be dissolved by the tutor.
您可以选择与最多一(1)人一起完成此评估。成对工作;你和你的伴侣必须在同一个辅导班。你将需要花费大约。6个小时一起做评估(辅导时间之外)。如果你不打算花这段时间一起工作-选择自己完成评估。双方都必须付出同等的努力,否则这个小组就会被导师解散。
Your code will be assessed against the learning outcomes below using techniques taught in the subject.
您的代码将使用本主题中教授的技术,根据以下学习结果进行评估。
LEARNING OUTCOMES
学习成果
Demonstrate a working knowledge of lists in Java.
展示 Java 中列表的工作知识。
Design a good OO solution from a specification.
根据规范设计一个好的OO解决方案。
Use inheritance in Java.
使用Java中的继承。
Construct a GUI interface
构造GUI界面
BRIEF
短暂的
This is a take home assessment to evaluate your understanding of object-oriented concepts taught so far in IAPP001. All code must compile and run in BlueJ version 4.1.2 to be marked.
这是一个带回家的评估,用来评估您对IAPP001中迄今为止所教授的面向对象概念的理解。所有代码必须在BlueJ 4.1.2版本中编译和运行才能被标记为。
You will use your Project A as the starting point for this project.
您将使用您的项目A作为这个项目的起点。
You will design a Graphical User Interface to support your application, using the domain classes from Project A.
您将使用项目 a 中的域类设计一个图形用户界面来支持您的应用程序。
Your GUI design should outline the main use cases for the application, the basic pane design and situations to handle for the application. You may use a main window and sub windows or a main window with a stacked tab pane.
您的GUI设计应该概述应用程序的主要用例、基本窗格设计和应用程序要处理的情况。您可以使用主窗口和子窗口,也可以使用带有堆叠选项卡窗格的主窗口。
You will design the windows and panes for your application. You will implement all of the GUI components following your design. You will implement the Observer pattern and test that your solution satisfies the requirements of your application.
您将为您的应用程序设计窗口和窗格。您将按照您的设计实现所有GUI组件。您将实现观察者模式并测试您的解决方案是否满足应用程序的需求。
The assessment is comprised of three (3) parts: the GUI design, the code and the explanation.
评估由三部分组成:GUI设计、代码和解释。
GUI design:
GUI设计:
Create your design for the GUI components – think about input needed from the user. Make sure your GUI design shows the GUI layout for your application. You can use paint or word tools to create the design. Make sure each panel/pane has at least 1 button to handle events.
为GUI组件创建您的设计—考虑用户需要的输入。确保您的GUI设计显示了应用程序的GUI布局。您可以使用绘画或文字工具来创建设计。确保每个面板/窗格至少有一个按钮来处理事件。
The code:
代码:
Copy your project and create a model package. Move all the domain classes to the model package. Add MyObserver and Updater to the model package. Delete the In class and changes all dependencies to use parameters for input. Write your GUI components. Make sure you are using the Observer pattern to refresh each window when the data changes in the models. You need to implement the 4 steps for the observer pattern – all model methods that change data need to call updateViews(). All panels have an implemented update() method etc.
复制您的项目并创建一个模型包。将所有域类移动到模型包中。将MyObserver和Updater添加到模型包中。删除In类并更改所有依赖项以使用参数作为输入。编写GUI组件。确保在模型中的数据更改时使用Observer模式刷新每个窗口。您需要实现观察者模式的4个步骤—所有更改数据的模型方法都需要调用updateViews()。所有面板都有一个实现的update()方法等。
The explanation: (300 words)
解释:(300字)
Write a detailed explanation of how the user would interact with your GUI to perform each of the usecase tasks. Explain how the observer pattern works by following the flow of control for one of the usecases.
编写一份详细的说明,说明用户将如何与您的GUI交互以执行每个用例任务。通过跟踪其中一个用例的控制流来解释观察者模式是如何工作的。
This is an open book assessment. You may use lecture notes and solutions to workshop exercises – however, you cannot use solutions to assessments from a previous or current semester.
这是一个开卷评估。你可以使用课堂讲稿和研讨会练习的答案,但是,你不能使用上学期或本学期的评估答案。
Every resource you use (other than subject materials) MUST be documented.
你使用的每一个资源(除了主题材料)都必须被记录下来。
Any student caught using prohibited materials will receive a fail grade for this assessment. All code submitted for assessment must be written by you (and your partner).
任何被发现使用违禁材料的学生将在本次评估中获得不及格分数。所有提交评估的代码必须由您(和您的合作伙伴)编写。
Any attempt to copy, move, alter or reproduce code files will be viewed as misconduct.
任何试图复制、移动、更改或复制代码文件的行为都将被视为不当行为。
As an exception: you may use the Gladiator Prime solution (week 6) as a replacement of your project A if you failed and/or cannot use your own project A as a base for Project B. Please note: If you use Gladiator Prime you can only receive a maximum of a Credit for this project.
作为例外:如果您失败和/或无法使用自己的项目a作为项目b的基础,您可以使用角斗士Prime解决方案(第6周)作为项目a的替代品。请注意:如果您使用角斗士Prime,您只能获得该项目的最高学分。
SUBMISSION
You will submit your assessment in MS Word document format – yourName-studNo.doc.
您将以MS Word文档格式提交您的评估-您的姓名- studno .doc。
The document will have 3 sections:
该文件将包含3个部分:
GUI Design: Your designed GUI including buttons, panels, labels and textfields to support your application.
GUI设计:您设计的GUI包括按钮,面板,标签和文本字段来支持您的应用程序。
The code: You will copy the code from your BlueJ project into this section
代码:您将把BlueJ项目中的代码复制到本节中
The explanation: you will explain your code choices and reasoning. You should place comments in the code to identify the steps in the observer pattern. You also need to include at least one screenshot of testing your code. Include any issues you had and how you resolved them. Minimum 300 words.
解释:你将解释你的代码选择和推理。您应该在代码中放置注释,以识别观察者模式中的步骤。您还需要包含至少一个测试代码的屏幕截图。包括你遇到的任何问题以及你是如何解决的。最少300字。
(You will also submit a copy of your blueJ project as a zip file)
(您还将以zip文件的形式提交blueJ项目的副本)
The deadline for submission of this project is Friday 11:59pm in week 10.
这个项目的提交截止日期是第10周的周五晚上11:59。
Draft Project B: due Tutorial B Week 10 – draft GUI design review by tutor
项目B草案:交教程B第10周-由导师审阅GUI设计草案
All projects submitted after the deadline will incur late penalties of 1 grade band every 2 days (or part thereof).
所有在截止日期后提交的项目将每2天(或部分时间)被罚1个等级。
REMINDER: ALL of the code must be your own unique work using concepts and techniques taught in the subject to satisfy academic integrity.
提醒:所有的代码必须是你自己独特的工作,使用的概念和技术,在学科教授,以满足学术诚信。
详情
LEARNING OUTCOMES
1. Demonstrate a working knowledge of lists in Java.
2. Design a good OO solution from a specification.
3. Use inheritance in Java.
4. Construct a GUI interface
BRIEF
This is a take home assessment to evaluate your understanding of object-oriented concepts taught so far in IAPP001. All code must compile and run in BlueJ version 4.1.2 to be marked.
You will use your Project A as the starting point for this project.
You will design a Graphical User Interface to support your application, using the domain classes from Project A.
Your GUI design should outline the main use cases for the application, the basic pane design and situations to handle for the application. You may use a main window and sub windows or a main window with a stacked tab pane.
You will design the windows and panes for your application. You will implement all of the GUI components following your design. You will implement the Observer pattern and test that your solution satisfies the requirements of your application.
The assessment is comprised of three (3) parts: the GUI design, the code and the explanation.
GUI design:
Create your design for the GUI components – think about input needed from the user. Make sure your GUI design shows the GUI layout for your application. You can use paint or word tools to create the design. Make sure each panel/pane has at least 1 button to handle events.
The code:
Copy your project and create a model package. Move all the domain classes to the model package. Add MyObserver and Updater to the model package. Delete the In class and changes all dependencies to use parameters for input. Write your GUI components. Make sure you are using the Observer pattern to refresh each window when the data changes in the models. You need to implement the 4 steps for the observer pattern – all model methods that change data need to call updateViews(). All panels have an implemented update() method etc.
The explanation: (300 words)
Write a detailed explanation of how the user would interact with your GUI to perform each of the usecase tasks. Explain how the observer pattern works by following the flow of control for one of the usecases.
Cafe.java
```java
//import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
// "Cafe" 类表示咖啡馆
public class Cafe {
private List<Product> availableProducts; // 可供选择的产品列表
private List<Order> orders; // 已完成的订单列表
// 构造函数
public Cafe() {
// this.availableProducts = new ArrayList<>();
// this.orders = new ArrayList<>();
this.availableProducts = new LinkedList<>(); // 将 ArrayList 更改为 LinkedList
this.orders = new LinkedList<>(); // 将 ArrayList 更改为 LinkedList
}
// 向咖啡馆添加产品
public void addProduct(Product product) {
availableProducts.add(product);
}
// 记录新的订单
public void newOrder(Order order) {
orders.add(order);
}
// 获取可供选择的产品列表
public List<Product> getAvailableProducts() {
return availableProducts;
}
}
```
Drink.java
```java
// "Drink" 类是 "Product" 的子类,代表饮料
public class Drink extends Product {
private boolean isCold; // 判断是否是冷饮
// 构造函数
public Drink(String name, double price, boolean isCold) {
super(name, price);
this.isCold = isCold;
}
// 返回饮料是否是冷的
public boolean isCold() {
return isCold;
}
// 实现父类的抽象方法,返回产品类型
@Override
public String getType() {
return "Drink";
}
// 覆盖toString方法返回产品详情
@Override
public String toString() {
return super.toString() + " - " + (isCold ? "Cold" : "Hot");
}
}
```
Food.java
```java
// "Food" 类是 "Product" 的子类,代表食物
public class Food extends Product {
// 构造函数
public Food(String name, double price) {
super(name, price);
}
// 实现父类的抽象方法,返回产品类型
@Override
public String getType() {
return "Food";
}
}
```
Main.java
```java
import java.util.Scanner;
public class Main {
private static Cafe cafe = new Cafe();
private static Scanner scanner = new Scanner(System.in);
public static void main(String[] args) {
while (true) {
showMainMenu();
int choice = scanner.nextInt();
scanner.nextLine(); // consume newline
switch (choice) {
case 1:
displayProducts();
break;
case 2:
addNewProduct();
break;
case 3:
createNewOrder();
break;
case 4:
System.out.println("Exiting...");
System.exit(0);
break;
default:
System.out.println("Invalid choice. Please try again.");
}
}
}
private static void showMainMenu() {
System.out.println("===== CAFE MENU =====");
System.out.println("1. Display Available Products");
System.out.println("2. Add New Product");
System.out.println("3. Create New Order");
System.out.println("4. Exit");
System.out.print("Please enter your choice: ");
}
private static void displayProducts() {
System.out.println("===== PRODUCTS =====");
for (Product product : cafe.getAvailableProducts()) {
System.out.println(product);
}
}
private static void addNewProduct() {
System.out.println("===== ADD NEW PRODUCT =====");
System.out.println("1. Drink");
System.out.println("2. Food");
System.out.print("Enter type (1 or 2): ");
int type = scanner.nextInt();
scanner.nextLine(); // consume newline
System.out.print("Enter product name: ");
String name = scanner.nextLine();
System.out.print("Enter product price: ");
double price = scanner.nextDouble();
scanner.nextLine(); // consume newline
if (type == 1) {
System.out.print("Is the drink cold? (yes or no): ");
boolean isCold = scanner.nextLine().equalsIgnoreCase("yes");
cafe.addProduct(new Drink(name, price, isCold));
} else if (type == 2) {
cafe.addProduct(new Food(name, price));
} else {
System.out.println("Invalid type. Product not added.");
}
}
private static void createNewOrder() {
Order order = new Order();
while (true) {
displayProducts();
System.out.println("Enter product name to add (or type 'done' to finish): ");
String productName = scanner.nextLine();
if (productName.equalsIgnoreCase("done")) {
break;
}
Product selectedProduct = null;
for (Product product : cafe.getAvailableProducts()) {
if (product.getName().equalsIgnoreCase(productName)) {
selectedProduct = product;
break;
}
}
if (selectedProduct != null) {
order.addProduct(selectedProduct);
System.out.println(productName + "adding to order.");
} else {
System.out.println("Product not found.");
}
}
cafe.newOrder(order);
System.out.println("Order created: " + order);
}
}
```
Order.java
```java
//import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
// "Order" 类表示顾客的订单
public class Order {
private List<Product> products; // 该订单中的产品列表
// 构造函数
public Order() {
// this.products = new ArrayList<>();
this.products = new LinkedList<>(); // 将ArrayList更改为LinkedList
}
// 向订单中添加产品
public void addProduct(Product product) {
products.add(product);
}
// 获取订单的总价格
public double getTotalPrice() {
double total = 0;
for (Product product : products) {
total += product.getPrice();
}
return total;
}
// 覆盖toString方法返回订单详情
@Override
public String toString() {
return "Order: " + products.toString() + " Total Price: " + getTotalPrice();
}
}
```
Product.java
```java
// 抽象父类 "Product" 代表所有的产品
public abstract class Product {
private String name; // 产品名称
private double price; // 产品价格
// 构造函数
public Product(String name, double price) {
this.name = name;
this.price = price;
}
// 获取产品名称
public String getName() {
return name;
}
// 获取产品价格
public double getPrice() {
return price;
}
// 抽象方法获取产品类型(由子类实现)
public abstract String getType();
// 覆盖toString方法返回产品名称和价格
@Override
public String toString() {
return name + " (" + price + ")";
}
}
```
ProductType.java
```java
// 枚举 "ProductType" 定义产品的种类
public enum ProductType {
DRINK, // 饮料
FOOD; // 食物
}
```
Cafe.java
```java
package model;
import java.util.LinkedList;
import java.util.List;
public class Cafe {
private List<Product> availableProducts;
private List<Order> orders;
private List<Observer> observers = new LinkedList<>();
public Cafe() {
this.availableProducts = new LinkedList<>();
this.orders = new LinkedList<>();
}
public void addProduct(Product product) {
availableProducts.add(product);
notifyObservers();
}
public List<Product> getAvailableProducts() {
return availableProducts;
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
private void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
// 记录新的订单
public void newOrder(Order order) {
orders.add(order);
}
}
```
Drink.java
```java
package model;
// "model.Drink" 类是 "model.Product" 的子类,代表饮料
public class Drink extends Product {
private boolean isCold; // 判断是否是冷饮
// 构造函数
public Drink(String name, double price, boolean isCold) {
super(name, price);
this.isCold = isCold;
}
// 返回饮料是否是冷的
public boolean isCold() {
return isCold;
}
// 实现父类的抽象方法,返回产品类型
@Override
public String getType() {
return "model.Drink";
}
// 覆盖toString方法返回产品详情
@Override
public String toString() {
return super.toString() + " - " + (isCold ? "Cold" : "Hot");
}
}
```
Food.java
```java
package model;
// "model.Food" 类是 "model.Product" 的子类,代表食物
public class Food extends Product {
// 构造函数
public Food(String name, double price) {
super(name, price);
}
// 实现父类的抽象方法,返回产品类型
@Override
public String getType() {
return "model.Food";
}
}
```
Observer.java
```
package model;
// 在model包中
public interface Observer {
void update();
}
```
Order.java
```java
package model;//import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
// "model.Order" 类表示顾客的订单
public class Order {
private List<Product> products; // 该订单中的产品列表
// 构造函数
public Order() {
// this.products = new ArrayList<>();
this.products = new LinkedList<>(); // 将ArrayList更改为LinkedList
}
// 向订单中添加产品
public void addProduct(Product product) {
products.add(product);
}
// 获取订单的总价格
public double getTotalPrice() {
double total = 0;
for (Product product : products) {
total += product.getPrice();
}
return total;
}
// 覆盖toString方法返回订单详情
@Override
public String toString() {
return "model.Order: " + products.toString() + " Total Price: " + getTotalPrice();
}
}
```
Product.java
```java
package model;
// 抽象父类 "model.Product" 代表所有的产品
public abstract class Product {
private String name; // 产品名称
private double price; // 产品价格
// 构造函数
public Product(String name, double price) {
this.name = name;
this.price = price;
}
// 获取产品名称
public String getName() {
return name;
}
// 获取产品价格
public double getPrice() {
return price;
}
// 抽象方法获取产品类型(由子类实现)
public abstract String getType();
// 覆盖toString方法返回产品名称和价格
@Override
public String toString() {
return name + " (" + price + ")";
}
}
```
ProductType.java
```java
package model;
// 枚举 "model.ProductType" 定义产品的种类
public enum ProductType {
DRINK, // 饮料
FOOD; // 食物
}
```
AddProductDialog.java
```java
package view;
import model.Cafe;
import model.Drink;
import model.Food;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddProductDialog extends JDialog {
private Cafe cafe;
public AddProductDialog(JFrame parent, Cafe cafe) {
super(parent, "Add Product", true);
this.cafe = cafe;
setSize(500, 300);
setLayout(new GridLayout(4, 2));
JLabel nameLabel = new JLabel("Name:");
JTextField nameField = new JTextField();
JLabel priceLabel = new JLabel("\nPrice:");
JTextField priceField = new JTextField();
JLabel typeLabel = new JLabel("Type (Food/Drink):");
JComboBox<String> typeComboBox = new JComboBox<>(new String[] {"Food", "Drink"});
JLabel isColdLabel = new JLabel("Is Cold? (for Drinks)");
JCheckBox isColdCheckbox = new JCheckBox();
JButton addButton = new JButton("Add Product");
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
double price = Double.parseDouble(priceField.getText());
if (typeComboBox.getSelectedItem().equals("Drink")) {
cafe.addProduct(new Drink(name, price, isColdCheckbox.isSelected()));
} else {
cafe.addProduct(new Food(name, price));
}
dispose(); // Close the dialog
}
});
add(nameLabel);
add(nameField);
add(priceLabel);
add(priceField);
add(typeLabel);
add(typeComboBox);
add(isColdLabel);
add(isColdCheckbox);
add(new JLabel()); // Empty space
add(addButton);
}
}
```
CafeWindow.java
```java
package view;
import model.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CafeWindow extends JFrame implements Observer {
private Cafe cafe;
private JTextArea productsArea;
private JButton addProductButton;
private JButton purchaseButton;
public CafeWindow(Cafe cafe) {
this.cafe = cafe;
cafe.addObserver(this);
setTitle("Cafe Application");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
productsArea = new JTextArea(10, 40);
JScrollPane scrollPane = new JScrollPane(productsArea);
add(scrollPane, BorderLayout.CENTER);
// JButton addButton = new JButton("Add Product");
// addButton.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// cafe.addProduct(new Food("ExampleFood", 5.0));
// }
// });
// add(addButton, BorderLayout.SOUTH);
addProductButton = new JButton("Add Product");
addProductButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AddProductDialog dialog = new AddProductDialog(CafeWindow.this, cafe);
dialog.setVisible(true);
}
});
add(addProductButton, BorderLayout.SOUTH);
update();
}
@Override
public void update() {
productsArea.setText("");
for (Product product : cafe.getAvailableProducts()) {
productsArea.append(product.toString() + "\n");
}
}
}
```
Main.java
```java
import view.CafeWindow;
import java.awt.*;
public class Main {
private static model.Cafe cafe = new model.Cafe();
public static void main(String[] args) {
cafe.addProduct(new model.Drink("Cola", 3.0, true));
cafe.addProduct(new model.Food("Burger", 7.0));
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
CafeWindow window = new CafeWindow(cafe);
window.setVisible(true);
}
});
}
}
```
// model/Cafe.java
package model;
import java.util.LinkedList;
import java.util.List;
public class Cafe {
private List<Product> availableProducts;
private List<Order> orders;
private List<Observer> observers = new LinkedList<>();
private Order currentOrder = new Order(); // 当前订单
public Order getCurrentOrder() {
return currentOrder;
}
public void checkout() {
newOrder(currentOrder);
currentOrder = new Order();
notifyObservers();
}
public Cafe() {
this.availableProducts = new LinkedList<>();
this.orders = new LinkedList<>();
}
public void addProduct(Product product) {
availableProducts.add(product);
notifyObservers();
}
public List<Product> getAvailableProducts() {
return availableProducts;
}
public void addObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
observers.remove(observer);
}
private void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
// 记录新的订单
public void newOrder(Order order) {
orders.add(order);
}
public boolean purchaseProduct(Product product) {
if (product.getQuantity() > 0) {
product.setQuantity(product.getQuantity() - 1);
notifyObservers();
return true;
}
return false;
}
}
// model/Drink.java
package model;
// "model.Drink" 类是 "model.Product" 的子类,代表饮料
public class Drink extends Product {
private boolean isCold; // 判断是否是冷饮
// 构造函数
public Drink(String name, double price, boolean isCold) {
super(name, price);
this.isCold = isCold;
}
// 返回饮料是否是冷的
public boolean isCold() {
return isCold;
}
// 实现父类的抽象方法,返回产品类型
@Override
public String getType() {
return "model.Drink";
}
// 覆盖toString方法返回产品详情
@Override
public String toString() {
return super.toString() + " - " + (isCold ? "Cold" : "Hot");
}
}
// model/Food.java
package model;
// "model.Food" 类是 "model.Product" 的子类,代表食物
public class Food extends Product {
// 构造函数
public Food(String name, double price) {
super(name, price);
}
// 实现父类的抽象方法,返回产品类型
@Override
public String getType() {
return "model.Food";
}
}
// model/Observer.java
package model;
// 在model包中
public interface Observer {
void update();
}
// model/Order.java
package model;//import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
// "model.Order" 类表示顾客的订单
public class Order {
private List<Product> products; // 该订单中的产品列表
// 构造函数
public Order() {
// this.products = new ArrayList<>();
this.products = new LinkedList<>(); // 将ArrayList更改为LinkedList
}
// 向订单中添加产品
public void addProduct(Product product) {
products.add(product);
}
// 获取订单的总价格
public double getTotalPrice() {
double total = 0;
for (Product product : products) {
total += product.getPrice();
}
return total;
}
// 覆盖toString方法返回订单详情
@Override
public String toString() {
return "model.Order: " + products.toString() + " Total Price: " + getTotalPrice();
}
}
// model/Product.java
package model;
// 抽象父类 "model.Product" 代表所有的产品
public abstract class Product {
private String name; // 产品名称
private double price; // 产品价格
private int quantity = 0; // 新增数量字段
// 新增getter和setter
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
// 构造函数
public Product(String name, double price) {
this.name = name;
this.price = price;
}
// 获取产品名称
public String getName() {
return name;
}
// 获取产品价格
public double getPrice() {
return price;
}
// 抽象方法获取产品类型(由子类实现)
public abstract String getType();
// 覆盖toString方法返回产品名称和价格
@Override
public String toString() {
return name + " (" + price + ")";
}
}
// model/ProductType.java
package model;
// 枚举 "model.ProductType" 定义产品的种类
public enum ProductType {
DRINK, // 饮料
FOOD; // 食物
}
// view/AddProductDialog.java
package view;
import model.Cafe;
import model.Drink;
import model.Food;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddProductDialog extends JDialog {
private Cafe cafe;
JLabel quantityLabel = new JLabel("Quantity:");
JTextField quantityField = new JTextField();
public AddProductDialog(JFrame parent, Cafe cafe) {
super(parent, "Add Product", true);
this.cafe = cafe;
setSize(500, 300);
setLayout(new GridLayout(4, 2));
JLabel nameLabel = new JLabel("Name:");
JTextField nameField = new JTextField();
JLabel priceLabel = new JLabel("\nPrice:");
JTextField priceField = new JTextField();
JLabel typeLabel = new JLabel("Type (Food/Drink):");
JComboBox<String> typeComboBox = new JComboBox<>(new String[]{"Food", "Drink"});
JLabel isColdLabel = new JLabel("Is Cold? (for Drinks)");
JCheckBox isColdCheckbox = new JCheckBox();
JButton addButton = new JButton("Add Product");
addButton.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// String name = nameField.getText();
// double price = Double.parseDouble(priceField.getText());
// if (typeComboBox.getSelectedItem().equals("Drink")) {
// cafe.addProduct(new Drink(name, price, isColdCheckbox.isSelected()));
// } else {
// cafe.addProduct(new Food(name, price));
// }
// dispose(); // Close the dialog
// }
@Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
double price = Double.parseDouble(priceField.getText());
int quantity = Integer.parseInt(quantityField.getText()); // 获取输入的数量
if (typeComboBox.getSelectedItem().equals("Drink")) {
Drink drink = new Drink(name, price, isColdCheckbox.isSelected());
drink.setQuantity(quantity); // 设置数量
cafe.addProduct(drink);
} else {
Food food = new Food(name, price);
food.setQuantity(quantity); // 设置数量
cafe.addProduct(food);
}
dispose(); // Close the dialog
}
});
add(nameLabel);
add(nameField);
add(priceLabel);
add(priceField);
add(typeLabel);
add(typeComboBox);
add(isColdLabel);
add(isColdCheckbox);
add(new JLabel()); // Empty space
add(addButton);
add(quantityLabel);
add(quantityField);
}
}
// view/CafeWindow.java
package view;
import model.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CafeWindow extends JFrame implements Observer {
private Cafe cafe;
private JTextArea productsArea;
private JButton addProductButton;
private JButton purchaseButton;
public CafeWindow(Cafe cafe) {
this.cafe = cafe;
cafe.addObserver(this);
setTitle("Cafe Application");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// Checkout
JButton checkoutButton = new JButton("Checkout");
checkoutButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double total = cafe.getCurrentOrder().getTotalPrice();
JOptionPane.showMessageDialog(CafeWindow.this, "Total Amount: " + total);
cafe.checkout(); // 结算并开始一个新订单
update();
}
});
add(checkoutButton, BorderLayout.EAST);
// 在构造方法中 Purchase Product
purchaseButton = new JButton("Purchase Product");
purchaseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String productName = JOptionPane.showInputDialog("Enter the product name to purchase:");
for (Product product : cafe.getAvailableProducts()) {
if (product.getName().equalsIgnoreCase(productName)) {
if(cafe.purchaseProduct(product)) {
JOptionPane.showMessageDialog(CafeWindow.this, "Purchased successfully!");
cafe.getCurrentOrder().addProduct(product);
update();
} else {
JOptionPane.showMessageDialog(CafeWindow.this, "Product out of stock!");
}
return;
}
}
JOptionPane.showMessageDialog(CafeWindow.this, "Product not found!");
}
});
add(purchaseButton, BorderLayout.NORTH);
productsArea = new JTextArea(10, 40);
JScrollPane scrollPane = new JScrollPane(productsArea);
add(scrollPane, BorderLayout.CENTER);
// JButton addButton = new JButton("Add Product");
// addButton.addActionListener(new ActionListener() {
// @Override
// public void actionPerformed(ActionEvent e) {
// cafe.addProduct(new Food("ExampleFood", 5.0));
// }
// });
// add(addButton, BorderLayout.SOUTH);
addProductButton = new JButton("Add Product");
addProductButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AddProductDialog dialog = new AddProductDialog(CafeWindow.this, cafe);
dialog.setVisible(true);
}
});
add(addProductButton, BorderLayout.SOUTH);
update();
}
@Override
public void update() {
productsArea.setText("");
for (Product product : cafe.getAvailableProducts()) {
// productsArea.append(product.toString() + "\n");
// productsArea.append(product.toString() + " - Quantity: " + product.getQuantity() + "\n");
productsArea.append(product.toString() + " - 数量: " + product.getQuantity() + "\n");
}
}
}
// view/AddProductDialog.java
package view;
import model.Cafe;
import model.Drink;
import model.Food;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class AddProductDialog extends JDialog {
private Cafe cafe;
JLabel quantityLabel = new JLabel("Quantity:");
JTextField quantityField = new JTextField();
public AddProductDialog(JFrame parent, Cafe cafe) {
super(parent, "Add Product", true);
this.cafe = cafe;
setSize(500, 400); // Adjust the size to accommodate the added components.
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); // Adjust the layout to BoxLayout.
JLabel nameLabel = new JLabel("Name:");
JTextField nameField = new JTextField();
JLabel priceLabel = new JLabel("\nPrice:");
JTextField priceField = new JTextField();
JLabel typeLabel = new JLabel("Type (Food/Drink):");
JComboBox<String> typeComboBox = new JComboBox<>(new String[]{"Food", "Drink"});
JLabel isColdLabel = new JLabel("Is Cold? (for Drinks)");
JCheckBox isColdCheckbox = new JCheckBox();
JButton addButton = new JButton("Add Product");
addButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String name = nameField.getText();
double price = Double.parseDouble(priceField.getText());
int quantity = Integer.parseInt(quantityField.getText()); // 获取输入的数量
if (typeComboBox.getSelectedItem().equals("Drink")) {
Drink drink = new Drink(name, price, isColdCheckbox.isSelected());
drink.setQuantity(quantity); // 设置数量
cafe.addProduct(drink);
} else {
Food food = new Food(name, price);
food.setQuantity(quantity); // 设置数量
cafe.addProduct(food);
}
dispose(); // Close the dialog
}
});
add(nameLabel);
add(nameField);
add(priceLabel);
add(priceField);
add(typeLabel);
add(typeComboBox);
add(isColdLabel);
add(isColdCheckbox);
add(quantityLabel);
add(quantityField);
add(addButton);
}
}
//package model;
import view.CafeWindow;
import java.awt.*;
public class Main {
private static model.Cafe cafe = new model.Cafe();
public static void main(String[] args) {
// cafe.addProduct(new model.Drink("Cola", 3.0, true));
// cafe.addProduct(new model.Food("Burger", 7.0));
model.Drink cola = new model.Drink("Cola", 3.0, true);
cola.setQuantity(10);
cafe.addProduct(cola);
model.Food burger = new model.Food("Burger", 7.0);
burger.setQuantity(5);
cafe.addProduct(burger);
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
CafeWindow window = new CafeWindow(cafe);
window.setVisible(true);
}
});
}
}
// 定义一个名为model的包
package model;
// 导入需要的Java库
import java.util.LinkedList;
import java.util.List;
// Cafe类定义
public class Cafe {
// 可用的产品列表
private List<Product> availableProducts;
// 订单列表
private List<Order> orders;
// 观察者列表,用于观察者模式。任何变化都会通知这些观察者。
private List<Observer> observers = new LinkedList<>();
// 当前的订单。这里默认初始化了一个新的订单。
private Order currentOrder = new Order();
// 返回当前订单的方法
public Order getCurrentOrder() {
return currentOrder;
}
// 结帐时的处理方法
public void checkout() {
// 将当前订单添加到订单列表中
newOrder(currentOrder);
// 初始化一个新的订单来替代当前订单
currentOrder = new Order();
// 通知所有观察者关于这个变化
notifyObservers();
}
// Cafe类的构造方法
public Cafe() {
// 初始化可用的产品和订单列表
this.availableProducts = new LinkedList<>();
this.orders = new LinkedList<>();
}
// 向可用产品列表中添加一个新产品的方法
public void addProduct(Product product) {
availableProducts.add(product);
// 通知所有观察者关于这个新产品
notifyObservers();
}
// 返回可用产品列表的方法
public List<Product> getAvailableProducts() {
return availableProducts;
}
// 添加观察者的方法
public void addObserver(Observer observer) {
observers.add(observer);
}
// 移除观察者的方法
public void removeObserver(Observer observer) {
observers.remove(observer);
}
// 一个私有方法,用于通知所有观察者关于某个变化
private void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
// 向订单列表中添加一个新订单的方法
public void newOrder(Order order) {
orders.add(order);
}
// 购买一个产品的方法。如果产品的数量大于0,则购买成功并减少产品数量。
public boolean purchaseProduct(Product product) {
if (product.getQuantity() > 0) {
product.setQuantity(product.getQuantity() - 1);
// 通知所有观察者关于这个购买
notifyObservers();
return true;
}
return false;
}
}
// 定义一个名为model的包
package model;
// "model.Drink" 类继承自 "model.Product" 类,这意味着每个 "Drink" 都是一个 "Product",
// 但有些特定的属性和方法只适用于饮料。
public class Drink extends Product {
// 一个私有的布尔型变量,用于标识这个饮料是否是冷的。
private boolean isCold;
// Drink的构造函数。它接受饮料的名称、价格和一个标识饮料是否冷的布尔值。
public Drink(String name, double price, boolean isCold) {
super(name, price); // 调用父类(Product)的构造函数,传递名称和价格。
this.isCold = isCold; // 初始化isCold属性。
}
// 一个公共方法,用于返回这个饮料是否是冷的。
public boolean isCold() {
return isCold;
}
// 实现父类Product的抽象方法。这个方法返回产品的类型。
// 对于Drink类,它总是返回 "model.Drink"。
@Override
public String getType() {
return "model.Drink";
}
// 覆盖了Object类的toString方法。
// 这允许我们为Drink对象提供一个自定义的字符串表示。
@Override
public String toString() {
// 调用父类的toString方法来获取基本的产品信息,
// 然后根据isCold的值添加"Cold"或"Hot"。
return super.toString() + " - " + (isCold ? "Cold" : "Hot");
}
}
// 定义一个名为model的包
package model;
// 在model包中定义一个Observer接口
public interface Observer {
// 这是观察者模式中的观察者接口。它包含一个更新方法,当被观察对象的状态发生变化时,这个方法会被调用。
void update();
}
// 定义一个名为model的包
package model;
// 导入需要的Java库
//import java.util.ArrayList; // 该行已被注释掉,表示不再使用ArrayList
import java.util.LinkedList;
import java.util.List;
// "model.Order" 类表示一个订单,主要存储顾客所选择购买的产品
public class Order {
// 定义一个私有变量,表示该订单中的所有产品。这里使用了List接口,具体实现选择了LinkedList。
private List<Product> products;
// Order类的默认构造函数
public Order() {
// 初始化产品列表。
// 该行代码已被注释掉,表示此处不再使用ArrayList来存储产品
// this.products = new ArrayList<>();
// 使用LinkedList来存储订单中的产品
this.products = new LinkedList<>();
}
// 这是一个公共方法,用于向订单中添加一个产品
public void addProduct(Product product) {
products.add(product);
}
// 这是一个公共方法,用于计算订单的总价格
public double getTotalPrice() {
double total = 0; // 初始化总价为0
// 遍历订单中的每一个产品
for (Product product : products) {
total += product.getPrice(); // 将每一个产品的价格加到总价中
}
return total; // 返回总价
}
// 重写Object类的toString方法,用于返回订单的详细信息
@Override
public String toString() {
// 返回订单中所有产品的列表,以及订单的总价
return "model.Order: " + products.toString() + " Total Price: " + getTotalPrice();
}
}
// 定义一个名为view的包
package view;
// 导入需要的模块和Java库
import model.Cafe;
import model.Drink;
import model.Food;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
// AddProductDialog类是一个继承自JDialog的对话框,用于在UI中添加新产品
public class AddProductDialog extends JDialog {
private Cafe cafe; // Cafe对象的引用,用于操作咖啡店数据
JLabel quantityLabel = new JLabel("Quantity:");
JTextField quantityField = new JTextField(); // 用户输入产品数量的文本框
// 构造函数,需要一个JFrame父对象和一个Cafe对象
public AddProductDialog(JFrame parent, Cafe cafe) {
super(parent, "Add Product", true); // 调用JDialog的构造函数设置标题和模式
this.cafe = cafe; // 初始化Cafe对象
setSize(500, 400); // 设置对话框的大小
setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS)); // 设置内容面板的布局为BoxLayout,按Y轴排列
// 定义和初始化组件
JLabel nameLabel = new JLabel("Name:");
JTextField nameField = new JTextField();
JLabel priceLabel = new JLabel("\nPrice:");
JTextField priceField = new JTextField();
JLabel typeLabel = new JLabel("Type (Food/Drink):");
JComboBox<String> typeComboBox = new JComboBox<>(new String[]{"Food", "Drink"}); // 下拉框用于选择产品类型
JLabel isColdLabel = new JLabel("Is Cold? (for Drinks)"); // 仅对Drink类产品相关的复选框标签
JCheckBox isColdCheckbox = new JCheckBox(); // 用于选择Drink是否为冷饮
JButton addButton = new JButton("Add Product"); // 添加产品的按钮
addButton.addActionListener(new ActionListener() { // 设置按钮的点击监听器
@Override
public void actionPerformed(ActionEvent e) {
// 获取并处理从对话框中输入的数据
String name = nameField.getText();
double price = Double.parseDouble(priceField.getText());
int quantity = Integer.parseInt(quantityField.getText());
// 根据选择的产品类型创建相应的对象,并设置其属性
if (typeComboBox.getSelectedItem().equals("Drink")) {
Drink drink = new Drink(name, price, isColdCheckbox.isSelected());
drink.setQuantity(quantity);
cafe.addProduct(drink); // 将Drink对象添加到cafe中
} else {
Food food = new Food(name, price);
food.setQuantity(quantity);
cafe.addProduct(food); // 将Food对象添加到cafe中
}
dispose(); // 关闭并释放对话框资源
}
});
// 将组件添加到对话框的内容面板中
add(nameLabel);
add(nameField);
add(priceLabel);
add(priceField);
add(typeLabel);
add(typeComboBox);
add(isColdLabel);
add(isColdCheckbox);
add(quantityLabel);
add(quantityField);
add(addButton);
}
}
// 导入所需的模块和Java库
package view;
import model.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
// CafeWindow类代表咖啡店的主窗口,并实现Observer接口来接收数据更新
public class CafeWindow extends JFrame implements Observer {
private Cafe cafe; // 咖啡店的引用
private JTextArea productsArea; // 显示产品的文本区域
private JButton addProductButton; // 添加产品的按钮
private JButton purchaseButton; // 购买产品的按钮
// 构造函数需要一个Cafe对象作为参数
public CafeWindow(Cafe cafe) {
this.cafe = cafe;
cafe.addObserver(this); // 将当前窗口添加为cafe的观察者
// 设置窗口的基本属性
setTitle("Cafe Application");
setSize(600, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// Checkout按钮功能实现
JButton checkoutButton = new JButton("Checkout");
checkoutButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double total = cafe.getCurrentOrder().getTotalPrice(); // 获取当前订单的总价
JOptionPane.showMessageDialog(CafeWindow.this, "Total Amount: " + total);
cafe.checkout(); // 结算并开始一个新订单
update(); // 更新界面
}
});
add(checkoutButton, BorderLayout.EAST);
// Purchase Product按钮功能实现
purchaseButton = new JButton("Purchase Product");
purchaseButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String productName = JOptionPane.showInputDialog("Enter the product name to purchase:"); // 获取要购买的产品名称
for (Product product : cafe.getAvailableProducts()) {
if (product.getName().equalsIgnoreCase(productName)) {
if(cafe.purchaseProduct(product)) {
JOptionPane.showMessageDialog(CafeWindow.this, "Purchased successfully!");
cafe.getCurrentOrder().addProduct(product);
update(); // 更新界面
} else {
JOptionPane.showMessageDialog(CafeWindow.this, "Product out of stock!");
}
return;
}
}
JOptionPane.showMessageDialog(CafeWindow.this, "Product not found!");
}
});
add(purchaseButton, BorderLayout.NORTH);
// 初始化产品显示区域并加入滚动条
productsArea = new JTextArea(10, 40);
JScrollPane scrollPane = new JScrollPane(productsArea);
add(scrollPane, BorderLayout.CENTER);
// 添加Add Product按钮功能
addProductButton = new JButton("Add Product");
addProductButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AddProductDialog dialog = new AddProductDialog(CafeWindow.this, cafe); // 打开产品添加的对话框
dialog.setVisible(true); // 显示对话框
}
});
add(addProductButton, BorderLayout.SOUTH);
update(); // 初始时更新界面
}
// 实现Observer接口的update方法,当数据发生变化时,此方法会被调用
@Override
public void update() {
productsArea.setText(""); // 清空当前显示内容
for (Product product : cafe.getAvailableProducts()) {
// 在文本区域追加产品信息和其数量
productsArea.append(product.toString() + " - 数量: " + product.getQuantity() + "\n");
}
}
}
// 导入所需的库和模块
//import view.CafeWindow; // 这个导入已经在代码中了,但被注释掉了,因为它是view模块下的CafeWindow
import java.awt.*;
// Main类包含程序的主入口点
public class Main {
// 创建一个静态的Cafe对象。由于它是静态的,所有的Main类的实例都将共享这一个cafe对象
private static model.Cafe cafe = new model.Cafe();
// 主函数,程序的入口点
public static void main(String[] args) {
// 创建一个名为"Cola"、价格为3.0的冷饮品并设置其数量为10,然后添加到cafe中
model.Drink cola = new model.Drink("Cola", 3.0, true);
cola.setQuantity(10);
cafe.addProduct(cola);
// 创建一个名为"Burger"、价格为7.0的食物并设置其数量为5,然后添加到cafe中
model.Food burger = new model.Food("Burger", 7.0);
burger.setQuantity(5);
cafe.addProduct(burger);
// 使用EventQueue的invokeLater方法来确保GUI操作在事件分派线程(EDT)上执行
// 这是一个Java的最佳实践,确保GUI操作的线程安全性
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
// 创建一个新的CafeWindow对象,并设置它为可见。CafeWindow是该应用程序的主窗口。
CafeWindow window = new CafeWindow(cafe);
window.setVisible(true);
}
});
}
}
公众号:AI悦创【二维码】

AI悦创·编程一对一
AI悦创·推出辅导班啦,包括「Python 语言辅导班、C++ 辅导班、java 辅导班、算法/数据结构辅导班、少儿编程、pygame 游戏开发、Web、Linux」,全部都是一对一教学:一对一辅导 + 一对一答疑 + 布置作业 + 项目实践等。当然,还有线下线上摄影课程、Photoshop、Premiere 一对一教学、QQ、微信在线,随时响应!微信:Jiabcdefh
C++ 信息奥赛题解,长期更新!长期招收一对一中小学信息奥赛集训,莆田、厦门地区有机会线下上门,其他地区线上。微信:Jiabcdefh
方法一:QQ
方法二:微信:Jiabcdefh
