如何通过Product实体对象调用服务方法?是否需继承实体类?
问题
我有一个名为Product的实体类,定义如下:
public String email; public int age; public double price; public double discount;
我想为它创建一个服务类来实现计算逻辑,请问是否需要继承Product类来使用email、age、price等变量进行计算?另外,我是否必须创建服务类对象,还是可以通过Product实体对象直接调用服务方法?
目前我的main方法中是这样创建服务对象的:Service service = new Service("email", 1, 30)
但我希望能创建Product实体对象,再通过该对象调用服务方法,即:Product product = new Product ("email", 1, 30)
现有代码示例
Main类
public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); TaxService taxService = new TaxService("The Little Prince", 12345, 20.25); int option = 0; do { menu(); option = scanner.nextInt(); switch (option) { case 1: taxService.tax(); break; case 2: System.out.println( "\nThank you for using the program. Goodbye!\n"); System.exit(0); break; default: System.out.println("Invalid input"); break; } } while (option != 9); } public static void menu() { System.out.println("Choose action"); System.out.println("1. Tax calculate\n"); System.out.println("2: Exit program"); System.out.print("Enter your selection: "); } }
Product实体类
public class Product { public String name; public int UPC; public double price; public double tax; public Product() { } public Product(String name, int UPC, double price) { this.name = name; this.UPC = UPC; this.price = price; this.tax = 20; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getUPC() { return UPC; } public void setUPC(int UPC) { this.UPC = UPC; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public double getTax() { return tax; } public void setTax(double tax) { this.tax = tax; } }
TaxService服务类
public class TaxService extends Product { Scanner scanner = new Scanner(System.in); public TaxService(String name, int UPC, double price) { super(name, UPC, price); } public void tax() { System.out.println("Do you want to change tax percentage? (y / n)"); String answer = scanner.nextLine(); if (answer.equalsIgnoreCase("y")) { System.out.println("Please enter a new tax percentage: "); double newTaxPercentage = scanner.nextInt(); scanner.nextLine(); if (newTaxPercentage < 0) { System.out.println("Wrong input, try again."); } else { double calculateTax = (price * (newTaxPercentage / 100)); double result = calculateTax + price; System.out.println("Calculation finished"); System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", price, result, newTaxPercentage); } } else { double calculateTax = (price * (tax / 100)); double result = calculateTax + price; System.out.println("Calculation finished"); System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", price, result, tax); } } private boolean isTaxValid() { return tax < 0; } }
解答
1. 是否需要继承Product类?
不需要。继承的核心是**"is-a"**关系(比如Dog extends Animal表示狗是一种动物),但TaxService显然不是一种Product,强行继承会违背面向对象的设计原则,还会让代码耦合性过高。
正确的做法是依赖注入:在服务类中接收Product对象作为参数,通过它的get方法访问属性。这样既符合单一职责原则(Product负责存储数据,Service负责计算逻辑),也让代码更易维护和扩展。
2. 能否通过Product对象直接调用服务方法?
两种方式都可行,分场景选择:
- 如果想让业务逻辑和实体数据解耦,保持Product的纯粹性(只负责存储数据),就保留独立的服务类,通过服务类接收Product对象执行计算。
- 如果计算逻辑是Product的固有行为(比如计算最终售价),也可以把方法直接写在Product类里,这样就能直接用Product对象调用。但这种方式会让实体类承担业务逻辑,适合简单场景。
代码改造示例
改造后的TaxService(不继承,依赖Product)
public class TaxService { private Scanner scanner = new Scanner(System.in); // 接收Product对象作为参数,通过get方法访问属性 public void calculateTax(Product product) { System.out.println("Do you want to change tax percentage? (y / n)"); String answer = scanner.nextLine(); if (answer.equalsIgnoreCase("y")) { System.out.println("Please enter a new tax percentage: "); double newTaxPercentage = scanner.nextInt(); scanner.nextLine(); if (newTaxPercentage < 0) { System.out.println("Wrong input, try again."); return; } double calculateTax = product.getPrice() * (newTaxPercentage / 100); double result = calculateTax + product.getPrice(); System.out.println("Calculation finished"); System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", product.getPrice(), result, newTaxPercentage); // 可选:更新产品的税率 product.setTax(newTaxPercentage); } else { double calculateTax = product.getPrice() * (product.getTax() / 100); double result = calculateTax + product.getPrice(); System.out.println("Calculation finished"); System.out.printf("Product price reported as $%.2f before tax and $%.2f after %.0f%% tax.\n", product.getPrice(), result, product.getTax()); } } }
改造后的Main方法(先创建Product,再传给服务类)
public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 先创建Product实体对象 Product product = new Product("The Little Prince", 12345, 20.25); // 创建服务类对象 TaxService taxService = new TaxService(); int option = 0; do { menu(); option = scanner.nextInt(); scanner.nextLine(); // 处理输入后的换行符 switch (option) { case 1: // 把Product对象传给服务方法执行计算 taxService.calculateTax(product); break; case 2: System.out.println("\nThank you for using the program. Goodbye!\n"); System.exit(0); default: System.out.println("Invalid input"); break; } } while (option != 2); // 修正循环条件,和菜单选项保持一致 } public static void menu() { System.out.println("Choose action"); System.out.println("1. Tax calculate"); System.out.println("2: Exit program"); System.out.print("Enter your selection: "); } }
额外优化点
- 原代码中
Product的属性是public的,建议改为private,通过get/set方法访问,符合封装原则。 - 服务类里的Scanner可以在Main中创建后传入,避免重复创建实例。
- 原Main方法的循环条件
option !=9和菜单选项不符,改成option !=2更合理。
内容的提问来源于stack exchange,提问作者Sefan Jankovic
相关产品推荐
相关产品推荐

